1. 旋转编码器EC11:硬件小白也能懂的“数字旋钮”
如果你玩过音响、调过老式收音机,或者用过一些工业设备上的旋钮,那你对旋转编码器应该不陌生。EC11就是其中非常经典的一款,它本质上是一个可以无限旋转的“数字电位器”。和我们常见的电位器(比如音量旋钮,拧到头就没法再拧了)不同,EC11旋转没有物理终点,你一直往一个方向拧,它就能一直输出信号。
这东西在嵌入式项目里简直是个“万金油”。你想做个带旋钮的智能温控器?用它。想给DIY的小设备加个菜单选择轮?用它。做个可调参数的实验电源?还是用它。它比按键更直观,比触摸屏在某些场景下(比如戴手套操作、盲操作)更可靠。
EC11通常有三个引脚:A相、B相和公共端(COM)。有些型号还带一个独立的按键开关(SW),相当于按一下旋钮,实现确认或切换功能。它的工作原理很简单:当你旋转时,内部的机械结构会让A、B两个引脚输出两路相位差90度的方波信号。关键就在这里:通过判断这两路信号的相位先后关系,我们就能知道是顺时针转还是逆时针转。
举个例子,假设顺时针转时,A相先出现高电平,然后B相再出现高电平;那么逆时针转时,顺序就反过来,B相先高,A相后高。MCU(单片机)要做的,就是实时捕捉这两个引脚的电平变化,并判断方向。
在GD32或STM32这类ARM Cortex-M内核的MCU上,实现这个功能主要有两大流派:“软件流”的外部中断轮询法,和**“硬件流”的定时器编码器模式**。前者像是个勤快但容易手忙脚乱的小工,后者则像是个配备了专用自动化流水线的高级技工。接下来,我就带你亲手搭建这两个方案,并聊聊我踩过的坑和选型心得。
2. 方案一:外部中断轮询法——亲自动手的“原始”乐趣
这个方法的核心思想很直接:把EC11的A相和B相连到MCU的两个具有外部中断功能的GPIO引脚上。任何一个引脚的电平发生变化(上升沿或下降沿),都触发一次中断,我们在中断服务函数里,立刻去读取另一个引脚的状态,根据状态组合来判断方向。
2.1 硬件连接与初始化配置
首先,我们得把EC11接上。以常见的3引脚EC11(A, B, COM)为例:
- A相 接 MCU 的某个GPIO,比如
PB6。 - B相 接 MCU 的另一个GPIO,比如
PB7。 - 公共端(COM) 接地(GND)。
EC11内部有上拉电阻,但为了信号稳定,我强烈建议在MCU端,将这两个GPIO配置为内部上拉输入模式,或者在外部加上拉电阻(通常4.7K~10K)。这样,空闲时引脚为高电平,旋转时被拉低,信号干净利落。
配置代码以STM32标准库风格为例(GD32几乎通用):
void Encoder_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 1. 开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
// 2. 配置GPIO为上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输入模式速度也建议配置
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 3. 将PB6、PB7映射到外部中断线
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource7);
// 4. 配置外部中断线(以PB6对应的EXTI_Line6为例)
EXTI_InitStructure.EXTI_Line = EXTI_Line6 | EXTI_Line7; // 同时配置两条线
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; // 双边沿触发!这是关键
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// 5. 配置NVIC(嵌套向量中断控制器)
// PB6和PB7的中断可能共享一个中断向量(如EXTI9_5_IRQn),需查数据手册
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
这里有个关键点:EXTI_Trigger_Rising_Falling 设置为双边沿触发。因为EC11旋转一格,A、B相都会产生一个完整的方波(一次上升沿和一次下降沿)。如果只设置单边沿,会丢失一半的计数,导致


2万+

被折叠的 条评论
为什么被折叠?



