完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
该实验是平衡车的一部分知识,主要是用到STM32定时器的编码模式。本文主要介绍与之相关的知识点,包括编码器的原理,STM32编码器模式,通过串口打印捕获的数据的实验代码分析。在学习中,主要遇到三个障碍,一个是编码器的原理,一个是STM32编码器模式中对电机正反转的判断,一个是C语言中int型强制类型转换成short型的溢出问题。
一、编码器 我主要以容易理解的方式进行整理,可能不是很严谨。对于平衡车来讲,它需要不断的采集此时小车的运动速度,而小车的运动速度就是电机的运动速度,但是有一个问题,如何将速度进行转化成数字信号,这样单片机才可以进行识别。而这个桥梁就是编码器。编码器是一种将旋转位移转换成一串数字脉冲信号的旋转式传感器。它需要解决的问题就是将旋转位移转换为数字脉冲,而我们可以从数字脉冲中计算出电机速度以及电机的转动方向。 二、编码器的原理 我以其中一种为例,就可以知道其工作原理了。编码器简化后有一个编码盘,一个发光二极管。我们先来了解一下编码盘,它由A相、B相、Z相组成,其中A相的白色区域(可透光)与B相的白色区域相差1/4T,而Z相只有一个白色域。那现在我们将其沿着纸面旋转90°,并在其两边分别放置发光二极管和光敏传感器。发光二极管一直都处于发光状态,当光线刚好通过白色区域时,光敏传感器接收到光信号,产生脉冲,有光时高电平信号,无光时低电平信号,因为每个白色区域或黑色区域的角度都是固定的,我们只要用单片机采集到的电平持续时间就可以计算出角速度大小。 现在还有一个问题,怎么判断正反转?其实就是利用A相与B相,我们知道A相和B相之间相差1/4T,当逆时针旋转时A相白色区域在前,先透光,先产生高电平,这样我们可以根据A和B相哪个先产生高电平来判断是顺时针还是逆时针转动。 三、STM32编码器模式 有人可能会问,产生高低电平时,直接用普通的IO中断就可以,为什么需要用到这个模式?如果电机按理想情况转动当然没问题,但是实际情况会产生毛刺(类似按键的抖动现象),这样如果单纯用普通IO中断,我们还需要写相应算法来消掉毛刺;那如果有一个硬件帮我们做了这件事情,那不是很好吗?而STM32定时器的编码器模式刚好有这个功能。 STM32编码器接口模式: 在学习此模式前,建议大家重新温习一下定时器的输入捕获知识,在输入捕获的基础上更容易理解此模式!主要根据STM32中文参考手册学习整理! 1、选择编码器接口模式的方法是:如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的 SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则置SMS=011; 2、通过设置TIMx_CCER寄存器中的CC1P和CC2P位,可以选择TI1和TI2极性;如果需要,还可以 对输入滤波器编程。 3、两个输入TI1和TI2被用来作为增量编码器的接口,也就是我们前面讲的A相和B相的脉冲信号。接下去我们要思考的问题就是,如何根据接口传来的信号进行方向判断以及记录脉冲持续时间。那就是要看懂一下这个图: 图中TI1表示通道1,TI2表示通道2; TI1FP1,是来自于通道TI1,经过滤波器后将接到捕捉比较通道IC1; TI1FP2,是来自于通道TI1,经过滤波器后将接到捕捉比较通道IC2; TI2FP1,是来自于通道TI2,经过滤波器后将接到捕捉比较通道IC1; TI2FP2,是来自于通道TI2,经过滤波器后将接到捕捉比较通道IC2; 还有这个图:(这个图的作用就是用来判断电机到底是正转还是反转) 该图比较难理解的就是第二列,所谓的相对信号电平。因为我们这个实验选择的是在TI1和TI2上计数,也就是我们一个周期会采集四次电平信号(可以看图)。那第二列可以这么来理解,我们假设编码器A相在前(也就是顺时针转动),此时TI1出现从低到高电平跳变,那么我这时要观察第3列,然后TI1相对信号其实就是TI2,此时的TI2还处在低电平状态,所以我们要看最后一列,这样就可以确定定时器此时向上计数;当TI2接着出现从低到高电平跳变,那么我这时要观察第5列,然后TI2相对信号其实就是TI1,此时的TI1处在高电平状态,所以我们要看倒数第二列,这样就可以确定定时器此时向上计数;以此类推,我们会发现当电机顺时针转动时,定时器向上计数,逆时针,定时器向下计数,从而判断出到底正转还是反转! 总结:第二列可以这么理解,TI1FP1其实就是TI1,那么它的相对电平就是TI2. 四、实验代码 encoder.c: #include "tim.h" //包含tim头文件 #include "encoder.h" int iTim4Encoder; //存放从TIM4定时器读出来的编码器脉冲 int GetTim4Encoder(void) //获取TIM4定时器读出来的编码器脉冲 { iTim4Encoder = (short)(__HAL_TIM_GET_COUNTER(&htim4)); //先读取脉冲数 __HAL_TIM_SET_COUNTER(&htim4,0);/ /再计数器清零 return iTim4Encoder; //返回脉冲数 } encoder.h : #ifndef __ENCODER_H #define __ENCODER_H int GetTim4Encoder(void); //声明函数 #endif main.c: int iTempTim4Encoder; //临时存放从TIM4编码器接口捕获到的脉冲数据 HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL) ; //开启TIM4的编码器接口模式 While(1) { HAL_Delay(5000); //延时5秒 iTempTim4Encoder = GetTim4Encoder(); //捕获TIM4脉冲数据 printf("TIM4定时器编码器模式捕获脉冲 = %d n",iTempTim4Encoder); //把脉冲数据打印出来 HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); //翻转指示灯LED的电平 } 代码有个核心问题: 在上面的代码中,并没有对数值进行正负判断赋值,脉冲值怎么会出现负数? 如果 TI1 和 TI2 分别接电机的 A 相和 B 相的话,那么,当电机正转的时候,计数器会向上计数,反转的时候会向下计数,但是向下计数并不会出现负的值,依旧是从(0-ARR)计数。 上面的代码 iTim4Encoder = (short)(__HAL_TIM_GET_COUNTER(&htim4)); 使用了强制类型装换,把寄存器的值读出来了之后,转换成了 short 型(2 字节),范围为(-32768-32767),此时当我们把计数器的初始值设置为 0 之后,如果出现反转,它就会从 0 开始向下计数(0,65535,65534,…)但是经过强制类型转换之后就变成了(0,-1,-2,…)。 五、为什么65535强制类型转换后会变成-1 接下来就来谈谈,为什么65535强制类型转换后会变成-1; |
|
|
|
只有小组成员才能发言,加入小组>>
2431 浏览 0 评论
9078 浏览 4 评论
36741 浏览 19 评论
5020 浏览 0 评论
24701 浏览 34 评论
1512浏览 2评论
1730浏览 1评论
2170浏览 1评论
1538浏览 0评论
509浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-18 12:19 , Processed in 1.270815 second(s), Total 47, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号