一:前言
最近在使用增量式编码器当作按键控制,增量式编码器在实际应用中很常见,STM32的定时器有编码器模式,大大的方便我们的开发。使用STM32cubeMX配置工具,使得这个过程变得无比简单。
二:增量式编码器介绍
编码器的结构如上图所示: AB型编码器有5个接口,A和B接口分别连接两个触点,C接口连接金属片,当旋转编码器时,中间的金属片会跟着旋转,触点随着金属片的旋转接触脱离。A和B两个接口负责输出,同时编码器还可以当作普通按键使用,D和E接口连接着普通按键。
当顺时针转动时,A触点在前,先接触到金属片,输出低电平,B触点在后,滞后A触点输出低电平,也就是A输出的波形相位超前B输出的波形,顺时针转动输出的波形如下图所示:
同理,如果逆时针转动,B输出波形相位超前于A输出波形,逆时针转动输出的波形如下图所示:
当编码器按下时,D和E触点连接到地,可以当作普通按键使用,此时需要配置GPIO为输入上拉模式,检测按下的低电平。
三:STM32定时器编码器模式介绍
打开STM32G4系列参考手册通用定时器说明,看到通用定时器框图如上图:在从模式控制模式下有编码器接口,编码器的输入连接tim_ti1fp1与tim_ti2fp2,这两个输入经过定时器通道一与定时器通道二通过输入滤波与边沿检测后连接到编码器接口,编码器接口输出通过PSC分频器后连接到CNT计数器。所以可以把定时器增量编码器模式结构图简化一下如下图所示:
继续向下阅读芯片手册,在手册中具体的列举出了不同模式下,CNT计数器的计数方向。
在Counting on tim_ti1 only ×1 mode模式下,此模式仅检测tim_ti1的边沿,当tim_ti2是高电平时,tim_ti1上升沿,此时表示编码器逆向旋转,计数器的值减,如果tim_ti1下降沿,计数器的值增,这样编码器每转动一次,计数器的值就会加减1。
再看,在Counting on tim_ti1 and tim_ti2 ×4 mode模式下,此模式检测tim_ti1与tim_ti2两种边沿,假设编码器顺时针旋转,此时tim_ti1对应A与tim_ti2对应B的波形如下,假设只转动一转,也就是A和B的波形只有一个周期,计数器计数如下:
1.A的上升沿,B是低电平,计数器加1
2.B的上升沿,A是高电平,计数器加1
3.A的下降沿,B是高电平,计数器加1
4.B的下降沿,A是低电平,计数器加1
可以看到,在此模式下,编码器顺时针旋转一转,计数器加4,那么逆时针旋转一转,计数器减4。在数据手册中,也列出了此模式下计数器的框图:
同时此种模式也有一个好处,如果编码器一个输出通道存在jitter(抖动),那么双边沿检测可以抑制抖动。
四:程序编写
用到的编码器模块如下,使用STM32开发板,搭建实验平台。接口连接如下:
GND连接GND
+连接3V3
SW连接PA5(普通IO)
CLK连接PA6(定时器3通道1)
DT连接PA7(定时器3通道2)
打开CUBEMX选中芯片型号STM32G431RBT6(你自己的型号),配置好RCC,时钟树,sys。
选择定时器3,编码器模式:
一个计数周期设置为20。
编码器模式选择检测tim_ti1与tim_ti2两种边沿。
接下来配置串口。
配置完成后生成工程。首先重定向串口,方便使用printf打印信息,在魔术棒中勾选Use MicrolLIB。
添加代码
#include "stdio.h"
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
在使用编码器前需要打开编码器,HAL库中提供了代码,将此代码放在while循环前。
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_1 | TIM_CHANNEL_2);
编写代码获取计数器的值,并且在串口打印出来,编译后下载打开串口观察。
uint16_t TimerEncoder = 0;
void getTimerEncoder(void)
{
TimerEncoder = __HAL_TIM_GET_COUNTER(&htim3);
printf("Encoder Value %d\r\n",TimerEncoder);
HAL_Delay(500);
}
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
getTimerEncoder();
}
当编码器顺时针旋转时,计数器的值加,逆时针旋转时,计数器的值减。