1、编码器是什么玩意呢,它可是一个好玩的东西,做小车测速必不可少的玩意,下面,我将从编码器的原理讲起,一直到用 stm32 的编码器接口模式,测出电机转速与方向。1.编码器图 1 编码器示意图图 1 为编码器的示意图,中间是一个带光栅的码盘,光通过光栅,接收管接收到高电平,没通过,接收到低电平。电机旋转一圈,码盘上有多少光栅,接受管就会接收多少个高电平。371 电机中的码盘就是这样的,他是 334 线码盘,具有较高的测速精度,也就是电机转一圈输出 334 个脉冲,芯片上已集成了脉冲整形触发电路,输出的是矩形波,直接接单片机 IO 就 OK。 增量式旋转编码器通过内部两个光敏接受管转化其角度码盘的时
2、序和相位关系,得到其角度码盘角度位移量增加(正方向)或减少(负方向)。下图为编码器的原理图:图 2 增量式旋转编码器A,B 两点对应两个光敏接受管,A,B 两点间距为 S2 ,码盘的光栅间距分别为 S0 和 S1。S0+S1 的距离是 S2 的四倍。这样保证了 A,B 波形相位相差 90 度。旋转的反向不同,锯齿波 A,B 先到达高电平的顺序就会不同,如上图左侧所示,顺序的不同,就可以得到旋转的方向。2.stm32 编码器接口模式(寄存器)stm32 的编码器接口模式在 STM32 中文参考手册中有详细的说明,在手册273 页,14.3.12 节。程序是完全按照 下图方式,设置寄存器的。请到本
3、文尾下载 STM32 中文参考手册 图 3从图 3 中可以看出,TI1 波形先于 TI2 波形 90时,每遇到一个边沿变化是,计数器加 1(可以通过寄存器设置加减),可以看出一个光栅,被计数了4 次。TI1 波形后于 TI2 波形 90时 ,每遇到一次边沿变化,计数器减 1。 1. /TIM2_Encoder_Init,Tim2_CH1(PA0);Tim2_CH2(PA1)2. /arr:自动重装值 0XFFFF3. /psc:时钟预分频数 ,不分频4. void TIM2_Encoder_Init(u16 arr,u16 psc)5. 6. RCC-APB1ENR|=1APB2ENR|=1C
4、RL /PA0、PA1 清除之前设置10. GPIOA-CRL|=0X00000044; /PA0、PA1 浮空输入11. 12. TIM2-ARR=arr; /设定计数器自动重装值 13. TIM2-PSC=psc; /预分频器14.15. TIM2-CCMR1 |= 1CCMR1 |= 1CCER |= 0CCER |= 0SMCR |= 3CR1 |= 1APB2ENR|=1CRL6. GPIOD-CRL|=0X00000300; /PD.2 推挽输出7. GPIOD-ODR|=1APB2ENR|=1CRL15. GPIOC-CRL|=0X00000033; /PC10 推挽输出16.
5、GPIOC-ODR|=0XFAPB1ENR|=1CRL/PA6 输出30. GPIOA-CRL|=0X0B000000;/复用功能输出 31. GPIOA-ODR|=1ARR=arr;/设定计数器自动重装值 34. TIM3-PSC=psc;/预分频器不分频35. 36. TIM3-CCMR1|=6CCMR1|=1CCER|=1CR1=0x0080; /ARPE 使能 42. TIM3-CR1|=0x01; /使能定时器 3 43. 44.45. /电机方向与速度控制,速度调节范围为-100+10046. /大于 0 时,正转,小于 0 时,反转47. / 占空比低于 0.4 时电机不转48.
6、 /(占空比是指高电平在一个周期之内所占的时间比率)49. /TIM3-CCR1 的设定范围为 0900(因为 arr=900)50. /见 STM32 参考手册,14.3.9PWM 模式。51. void Motor_Speed_Control(s16 motorSpeed) 52. 53. s16 speed = 0 ; 54. 55. if(motorSpeed100) speed = 100;56. else if (motorSpeed 0)64. 65. M_1 = 0;66. M_2 = 1;67. TIM3-CCR1 = speed * 9;68. 69. else70. 71
7、. M_1 = 1;72. M_2 = 0;73. TIM3-CCR1 = -speed * 9;74. 75. 76.复制代码电机速度与方向检测代码1. /TIM2_Encoder_Init,Tim2_CH1(PA0);Tim2_CH2(PA1)2. /arr:自动重装值 0XFFFF3. /psc:时钟预分频数 ,不分频4. /见 STM32 中文手册 14.3.12 编码器接口模式5. void TIM2_Encoder_Init(u16 arr,u16 psc)6. 7. RCC-APB1ENR|=1APB2ENR|=1CRL /PA0、PA1 清除之前设置11. GPIOA-CRL|
8、=0X00000044; /PA0、PA1 浮空输入12. 13. TIM2-ARR=arr; /设定计数器自动重装值 14. TIM2-PSC=psc; /预分频器15.16. TIM2-CCMR1 |= 1CCMR1 |= 1CCER |= 0CCER |= 0SMCR |= 3CR1 |= 1CNT = data;27. 28. /读计数个数29. int TIM2_Encoder_Read(void)30. 31. TIM2_Encoder_Write(0); /计数器清 032. delay_ms(10); /检测时间,可调节33. return (int)(s16)(TIM2-CN
9、T); /数据类型转换34. /记录边沿变化次数(一个栅格被记录 4 次)35. 复制代码这里我们只显示边沿变化次数,没有具体的算出速度。主函数1. int main(void)2. 3. / motorSpeed 的范围为-100 +100;4. s16 motorSpeed = 100; 5. Stm32_Clock_Init(9); /系统时钟设置6. delay_init(72); /延时初始化7. uart_init(72,9600); /串口 1 初始化8. LED_Init(); /初始化与 LED 连接的硬件接口9. M_Init(); /初始化电机运行方向控制端口10. TI
10、M3_PWM_Init(900,0); /不分频。PWM 频率=72000/900=8Khz11. TIM2_Encoder_Init(0xffff, 0); /计数器自动重装值为最大12.13. while(1)14. 15. LED =! LED;16. Motor_Speed_Control(motorSpeed);17. printf(“编码器值:%dn “,TIM2_Encoder_Read();18. 19. 复制代码5 估算验证这里我们只是大概的估算验证测量值是否正确,不具有完全正确性。我们设置 motorSpeed = 100 ,得到测量值如下图:图 5 motorSpeed
11、= 100因为误差是不可避免的,所以看到每次检测的值都是不一样的。我们取 462,因为一个光栅被记录了 4 次,所以在 10ms 内一共检测到了462/4=115.5,那么得到 11.55 个/ms,每 ms 内检测到 11.55 个光栅。通过码表,记录电机输出 50 圈,用时 50.2s,那么这时应该检测到的光栅个数为 50*34(电机转 34 圈,输出 1 圈)*334(每圈有 334 个光栅)=567800,除以时间,得到估算值 11.31 个/ms。可以看出估算值与测量值是相近的,认为测量是准确的。设置 motorSpeed = -50 ,得到测量值如下图 :图 6 motorSpeed=-50