旋转编码器EC11实战:从外部中断到定时器编码器模式的实现与对比

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相都会产生一个完整的方波(一次上升沿和一次下降沿)。如果只设置单边沿,会丢失一半的计数,导致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值