热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

STM32定时器配置为编码器模式(转)

文章目录一、编码器原理二、为什么要用编码器三、STM32编码器配置相关四、STM32实战代码五、一些注意参考一、编码器原理如果两个信号相位差为90度,则这两个信号称为正交。由于两个

文章目录
一、编码器原理
二、为什么要用编码器
三、STM32编码器配置相关
四、STM32实战代码
五、一些注意
参考
一、编码器原理

技术分享图片

 

 


如果两个信号相位差为90度,则这两个信号称为正交。由于两个信号相差90度,因此可以根据两个信号哪个先哪个后来判断方向、根据每个信号脉冲数量的多少及整个编码轮的周长就可以算出当前行走的距离、如果再加上定时器的话还可以计算出速度。

二、为什么要用编码器


从上图可以看出,由于TI,T2一前一后有个90度的相位差,所以当出现这个相位差时就表示轮子旋转了一个角度。但有人会问了:既然都是脉冲,为什么不用普通IO中断?实际上如果是轮子一直正常旋转当然没有问题。仔细观察上图,如果出现了毛刺呢?这就是需要我们在软件中编写算法进行改正。于是,我们就会想到如果有个硬件能够处理这种情况那不是挺好吗?

对应的硬件的编码器就来了~

技术分享图片

 

 


我们看到STM32的硬件编码器还是很智能的,当T1,T2脉冲是连续产生的时候计数器加一或减一一次,而当某个接口产生了毛刺或抖动,则计数器计数不变,也就是说该接口能够容许抖动。

在STM32中,编码器使用的是定时器接口,通过数据手册可知,定时器1,2,3,4,5和8有编码器的功能,而其他没有。同时只有CH1和CH2是进行编码器模式的~

三、STM32编码器配置相关
编码器输入信号TI1,TI2经过输入滤波,边沿检测产生TI1FP1,TI2FP2接到编码器模块,通过配置编码器的工作模式,即可以对编码器进行正向/反向计数。

比如如果用的是定时器2,则对应的引脚是在PA0和PA1上。

通常为了提高精度我们会选择在上升沿和下降沿都进行计数!

 技术分享图片

 

 

还有一个非常重要的图这里也记录下

 技术分享图片

 

 

其中让人费解的应该是在第二列的相对信号的电平,这里就来详细谈一下吧。

其实也不难理解哈,我们上面也说了通常为了提高精度会在A、B两相的上升沿和下降沿都进行计数,那么对应在一个周期就可以计数四次,计数次数的增加也就意味着精度的提高!

编码器模式下,如果此时处于正转,那么这四次计数应该都是加的。同理,如果是反转,那么这四次计数都是减的。那么问题来了,如何判断正反转呢?

不就是在相对电平的基础上嘛!!!

 技术分享图片

 

 

仔细对照图中,在正转或者反转的情况下,A相对B的电平高低以及上表中的计数方向便可了然于心!!!

选择编码器接口模式的方法是:如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的
SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则
置SMS=011。

通过设置TIMx_CCER寄存器中的CC1P和CC2P位,可以选择TI1和TI2极性;如果需要,还可以
对输入滤波器编程。

两个输入TI1和TI2被用来作为增量编码器的接口。假定计数器已经启动(TIMx_CR1
寄存器中的CEN=’1’),计数器由每次在TI1FP1或TI2FP2上的有效跳变驱动。

配置范例:


技术分享图片技术分享图片

CC1S=’01’ (TIMx_CCMR1寄存器, IC1FP1映射到TI1)
CC2S
=’01’ (TIMx_CCMR2寄存器, IC2FP2映射到TI2)
CC1P
=’0’ (TIMx_CCER寄存器, IC1FP1不反相, IC1FP1=TI1)
CC2P
=’0’ (TIMx_CCER寄存器, IC2FP2不反相, IC2FP2=TI2)
SMS
=’011’ (TIMx_SMCR寄存器,所有的输入均在上升沿和下降沿有效).
CEN
=’1’ (TIMx_CR1寄存器,计数器使能)


View Code


四、STM32实战代码
————————————————


技术分享图片技术分享图片

1 /*TIM2初始化为编码器接口*/
2 void Encoder_Init_TIM2(void)
3 {
4 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
5 TIM_ICInitTypeDef TIM_ICInitStructure;
6 GPIO_InitTypeDef GPIO_InitStructure;
7
8 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器4的时钟
9 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口时钟
10
11 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //端口配置
12 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
13 GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA
14
15 TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
16 TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器
17 TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
18 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
19 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上计数
20 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
21 TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
22 TIM_ICStructInit(&TIM_ICInitStructure);
23 TIM_ICInitStructure.TIM_ICFilter = 10;
24 TIM_ICInit(TIM2, &TIM_ICInitStructure);
25 TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位
26 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
27 //Reset counter
28 TIM_SetCounter(TIM2,0);
29 TIM_Cmd(TIM2, ENABLE);
30 }
31
32 /*TIM4初始化为编码器接口*/
33 void Encoder_Init_TIM4(void)
34 {
35 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
36 TIM_ICInitTypeDef TIM_ICInitStructure;
37 GPIO_InitTypeDef GPIO_InitStructure;
38 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能定时器4的时钟
39 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB端口时钟
40
41 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置
42 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
43 GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB
44
45 TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
46 TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器
47 TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
48 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
49 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上计数
50 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
51 TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
52 TIM_ICStructInit(&TIM_ICInitStructure);
53 TIM_ICInitStructure.TIM_ICFilter = 10;
54 TIM_ICInit(TIM4, &TIM_ICInitStructure);
55 TIM_ClearFlag(TIM4, TIM_FLAG_Update);//清除TIM的更新标志位
56 TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
57 //Reset counter
58 TIM_SetCounter(TIM4,0);
59 TIM_Cmd(TIM4, ENABLE);
60 }
61
62 /*单位时间编码器计数 输入定时器 输出速度值*/
63 int Read_Encoder(u8 TIMX)
64 {
65 int Encoder_TIM;
66 switch(TIMX)
67 {
68 case 2: Encoder_TIM= (short)TIM2 -> CNT; TIM2 -> CNT=0;break;
69 case 3: Encoder_TIM= (short)TIM3 -> CNT; TIM3 -> CNT=0;break;
70 case 4: Encoder_TIM= (short)TIM4 -> CNT; TIM4 -> CNT=0;break;
71 default: Encoder_TIM=0;
72 }
73 return Encoder_TIM;
74 }
75
76 void TIM4_IRQHandler(void)
77 {
78 if(TIM4->SR&0X0001)//溢出中断
79 {
80 }
81 TIM4->SR&=~(1<<0);//清除中断标志位
82 }
83
84 void TIM2_IRQHandler(void)
85 {
86 if(TIM2->SR&0X0001)//溢出中断
87 {
88 }
89 TIM2->SR&=~(1<<0);//清除中断标志位
90 }


View Code

 


推荐阅读
  • 本文探讨了如何通过编程手段在Linux系统中禁用硬件预取功能。基于Intel® Core™微架构的应用性能优化需求,文章详细介绍了相关配置方法和代码实现,旨在帮助开发人员有效控制硬件预取行为,提升应用程序的运行效率。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • 本指南介绍了如何在ASP.NET Web应用程序中利用C#和JavaScript实现基于指纹识别的登录系统。通过集成指纹识别技术,用户无需输入传统的登录ID即可完成身份验证,从而提升用户体验和安全性。我们将详细探讨如何配置和部署这一功能,确保系统的稳定性和可靠性。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 使用 `git stash` 可以将当前未提交的修改保存到一个临时存储区,以便在后续恢复工作目录时使用。例如,在处理中间状态时,可以通过 `git stash` 命令将当前的所有未提交更改推送到一个新的储藏中,从而保持工作目录的整洁。此外,本文还将详细介绍如何解决 `git stash pop` 时可能出现的冲突问题,帮助用户高效地管理代码变更。 ... [详细]
  • 在《Linux高性能服务器编程》一书中,第3.2节深入探讨了TCP报头的结构与功能。TCP报头是每个TCP数据段中不可或缺的部分,它不仅包含了源端口和目的端口的信息,还负责管理TCP连接的状态和控制。本节内容详尽地解析了TCP报头的各项字段及其作用,为读者提供了深入理解TCP协议的基础。 ... [详细]
  • ClassList对象学习心得与表单事件非空校验技巧
    ClassList对象学习心得与表单事件非空校验技巧 ... [详细]
  • 在Cisco IOS XR系统中,存在提供服务的服务器和使用这些服务的客户端。本文深入探讨了进程与线程状态转换机制,分析了其在系统性能优化中的关键作用,并提出了改进措施,以提高系统的响应速度和资源利用率。通过详细研究状态转换的各个环节,本文为开发人员和系统管理员提供了实用的指导,旨在提升整体系统效率和稳定性。 ... [详细]
  • 在Linux系统中,网络配置是至关重要的任务之一。本文详细解析了Firewalld和Netfilter机制,并探讨了iptables的应用。通过使用`ip addr show`命令来查看网卡IP地址(需要安装`iproute`包),当网卡未分配IP地址或处于关闭状态时,可以通过`ip link set`命令进行配置和激活。此外,文章还介绍了如何利用Firewalld和iptables实现网络流量控制和安全策略管理,为系统管理员提供了实用的操作指南。 ... [详细]
  • 本文详细介绍了定时器输入捕捉技术的原理及其应用。通过配置定时器通道的引脚模式为输入模式,并设置相应的捕获触发条件,可以实现对外部信号的精确捕捉。该技术在实时控制系统中具有广泛的应用,如电机控制、频率测量等场景。文中还提供了具体的配置步骤和示例代码,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 解决针织难题:R语言编程技巧与常见错误分析 ... [详细]
  • CSS3 @font-face 字体应用技术解析与实践
    在Web前端开发中,HTML教程和CSS3的结合使得网页设计更加多样化。长期以来,Web设计师受限于“web-safe”字体的选择。然而,CSS3中的`@font-face`规则允许从服务器端加载自定义字体,极大地丰富了网页的视觉效果。通过这一技术,设计师可以自由选择和使用各种字体,提升用户体验和页面美观度。本文将深入解析`@font-face`的实现原理,并提供实际应用案例,帮助开发者更好地掌握这一强大工具。 ... [详细]
  • 如何精通编程语言:全面指南与实用技巧
    如何精通编程语言:全面指南与实用技巧 ... [详细]
  • 手指触控|Android电容屏幕驱动调试指南
    手指触控|Android电容屏幕驱动调试指南 ... [详细]
  • AIX编程挑战赛:AIX正方形问题的算法解析与Java代码实现
    在昨晚的阅读中,我注意到了CSDN博主西部阿呆-小草屋发表的一篇文章《AIX程序设计大赛——AIX正方形问题》。该文详细阐述了AIX正方形问题的背景,并提供了一种基于Java语言的解决方案。本文将深入解析这一算法的核心思想,并展示具体的Java代码实现,旨在为参赛者和编程爱好者提供有价值的参考。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有