今天在项目中,需要用到定时器去定时检测旋转编码器,本着不重复造轮子的思想,在网上没找着,大部分都是使用两个边沿捕获的办法,那我来造轮子吧。
需求是,搞个定时器每隔1ms进入一次中断,检查一次AB口的电平做解码。
先上图,第一张图是我的代码的正转,第二张图是反转
可以清楚的看出来正转和反转其实就是AB口时序的相位差别,所以中断服务函数代码如下,可以直接复制,小改动就行。
#define ROTARY_IRQHandler TIM16_IRQHandler
#define ROTARY_TIMER_IRQn TIM16_IRQn
#define ROTARY_TIMER TIM16
#define HIGH_VOLTAGE 1
#define LOW_VOLTAGE 0
#define uchar uint8_t
void ROTARY_IRQHandler(void)
{
static uchar A_last_voltage = 0;
static uchar A_curr_voltage = 0;
uchar B_curr_voltage = 0;
if (TIM_GetITStatus(ROTARY_TIMER, TIM_IT_Update) == SET)
{
A_curr_voltage = Read_PinA(PIN_RotaryA); // 读取A引脚的电平
B_curr_voltage = Read_PinA(PIN_RotaryB); // 读取B引脚的电平
if(A_curr_voltage == LOW_VOLTAGE)
{
if(A_last_voltage == HIGH_VOLTAGE)
{
if(B_curr_voltage == HIGH_VOLTAGE)
{
// 反转,你的逻辑代码
A_last_voltage = LOW_VOLTAGE;
}
else
{
// 反转,你的逻辑代码
A_last_voltage = LOW_VOLTAGE;
}
}
}
else
{
if(A_last_voltage == LOW_VOLTAGE)
{
A_last_voltage = HIGH_VOLTAGE;
}
}
}
TIM_ClearITPendingBit(ROTARY_TIMER, TIM_FLAG_Update); // 清除中断标志位
}
具体的执行逻辑还是需要大家自己结合代码判断一下,因为硬件摆放的位置不同。