怎么样才能将标致代rcc车机升级到四代?,标致rcc四代功能

关于STM32 EC11旋转编码器计数软件消除抖动的办法

关于STM32 EC11旋转编码器计数软件消除抖动的办法

开发板:STM32F103C8T6最小系统板

开发语言:C语言

前言:本人属于前端工程师自学STM32,因为有点空闲时间,就想着去学习一下其他方面的知识,而且本人对物联网比较感兴趣,所以就想着去学会使用STM32,然后再去DIY一些智能家居方面的东西,今天刚好学习到STM32旋转编码器计数,分享一下自己的学习心得给各位,感兴趣的可以看一下。

这个是我在网上买的EC11编码器模块,一共5个引脚,分别是S1,S2,KEY,VCC和GND。

当旋转编码器旋转时,S1、S2会产生相应的高低电平变化, KEY就是普通按键。

EC11旋转编码器介绍以及应用场景:

EC11旋转编码器也叫开关编码器、旋转编码器。其广泛用于车载DVD、车载导航、汽车影音上,也经常用于家用小家电产品的旋转开关上。EC11编码器在各类仪器设备中用于频率、音量、速度、温度、电压、菜单选择、光线强弱等参数的控制。EC11旋转编码器的调节轴有金属柄和塑胶柄,轴长区间9-30mm,调节轴有全柄、半柄、螺纹柄等。EC11系列编码器主要用于汽车电子、多媒体音响、仪器仪表、家用电器、智能家居、计算机周边、医疗器械等领域。主要用于频率调节、亮度调节、温度调节、音量调节的参数控制等。

工作原理: 旋转轴带动两组同轴栅格转盘,栅格转盘间存在一定的角度偏差,旋转的栅格会对发光二极管发出的光信号进行间断遮挡,从而使光敏二极管产生高低电平变化。因为两组栅格转盘存在一定的角度偏差,所以会产生两组相位90°偏差的A/B相信号。

输出信号图:

原来在B站看的教程的代码:

void Encoder_Init(void)

{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);


GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);


GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);


EXTI_InitTypeDef EXTI_InitStructure;

EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;

EXTI_InitStructure.EXTI_LineCmd = ENABLE;

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

EXTI_Init(&EXTI_InitStructure);


NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);


NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

NVIC_Init(&NVIC_InitStructure);

}

void EXTI0_IRQHandler(void)

{

if (EXTI_GetITStatus(EXTI_Line0) == SET)

{

/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/

if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)

{

if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)

{

Encoder_Count --;

}

}

EXTI_ClearITPendingBit(EXTI_Line0);

}

}

void EXTI1_IRQHandler(void)

{

if (EXTI_GetITStatus(EXTI_Line1) == SET)

{

/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/

if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)

{

if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)

{

Encoder_Count ++;

}

}

EXTI_ClearITPendingBit(EXTI_Line1);

}

}

这个办法就是对AB相都进行下降沿中断处理,实际效果很不理想,得到的计数结果不对,计数会乱跳。

然后我在知乎看到了一篇不错的文章,文章中的办法不错,然后试了一下。

解决办法:A脚设置为上升下降沿均会进中断,下降上升一个变换周期,判断这个周期的A脚,B脚的始末状态,来判断正反转一次。

优点:只需要一个管脚的外部触发,另一脚单纯获取电平状态即可。

中断函数代码如下:

static uint8_t EC11_Flag = 0;//标志位

static uint8_t CW_1 = 0;

static uint8_t CW_2 = 0;

void EXTI0_IRQHandler(void) {

if (EXTI_GetITStatus(EXTI_Line0) == SET) {

if (EC11_Flag == 0 && GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0) {

//下降沿

CW_1 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1);

EC11_Flag = 1;

}

if (EC11_Flag == 1 && GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 1) {

//上升沿

CW_2 = !GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1);

//取反是因为 a相,b相必然异步,一高一低。

if (CW_1 == 1 && CW_2 == 1) {

Encoder_Count++;

}

if (CW_1 == 0 && CW_2 == 0) {

Encoder_Count--;

}

EC11_Flag = 0;

}

EXTI_ClearITPendingBit(EXTI_Line0);

}

}

验证结果,不错,很稳:

视频加载中...

本人是前端工程师,自学STM32,所以对单片机这一块的知识并不是很了解,有错误的地方,望各位不吝赐教,谢谢。

2023-12-26

2023-12-26