51单片机EC11编码器编程实战:从硬件连接到软件消抖

1次阅读
没有评论

共计 1994 个字符,预计需要花费 5 分钟才能阅读完成。

image.webp

EC11 编码器硬件原理

EC11 是一种机械式增量编码器,通过旋转产生两路正交的脉冲信号(通常标记为 CLK 和 DT)。这两路信号存在 90 度的相位差,旋转方向不同时,两路信号的相位关系会发生变化:

51 单片机 EC11 编码器编程实战:从硬件连接到软件消抖

  • 顺时针旋转时,CLK 信号领先 DT 信号 90 度
  • 逆时针旋转时,DT 信号领先 CLK 信号 90 度

除了旋转信号外,EC11 还带有一个独立的按键信号(SW),可以用于确认选择等操作。

典型硬件电路设计

为了确保信号质量,硬件电路需要做以下处理:

  1. 上拉电阻配置
  2. CLK 和 DT 信号线需要接 10kΩ 上拉电阻
  3. SW 信号线同样需要上拉,通常用 4.7kΩ

  4. 硬件滤波

  5. 每个信号线对地接 100nF 电容
  6. 信号线上串联 100Ω 电阻

  7. ESD 防护

  8. 在信号线入口处放置 TVS 二极管
  9. 或使用专用的 ESD 保护器件

软件方案对比

查询法

优点:
– 实现简单,不占用中断资源
– 对系统实时性要求低

缺点:
– 响应速度慢,可能丢失快速旋转的信号
– CPU 占用率高

中断法

优点:
– 响应速度快
– CPU 占用率低

缺点:
– 需要合理处理中断冲突
– 对消抖算法要求更高

推荐在大多数应用中使用中断法,特别是需要快速响应的场合。

状态机消抖实现

消抖状态机是解决机械编码器抖动的关键,典型的 4 状态机如下:

  1. IDLE 状态:等待信号变化
  2. DEBOUNCE_A 状态:初次检测到变化,开始消抖计时
  3. DEBOUNCE_B 状态:确认信号稳定
  4. CONFIRM 状态:确认旋转方向

状态转换条件:
– 超时(典型值 5ms)
– 信号稳定
– 方向确认

完整代码示例

#include <reg52.h>

#define DEBOUNCE_TIME 5 // 消抖时间 5ms
#define TIMEOUT 20      // 超时时间 20ms

volatile unsigned char state = 0;
volatile unsigned char direction = 0;
volatile unsigned int counter = 0;

sbit CLK = P1^0;
sbit DT = P1^1;

void Timer0_Init() {
    TMOD |= 0x01;  // 模式 1,16 位定时器
    TH0 = 0xFC;    // 1ms 定时
    TL0 = 0x66;
    ET0 = 1;       // 使能定时器中断
    TR0 = 1;       // 启动定时器
}

void ExtInt0_Init() {
    IT0 = 1;       // 下降沿触发
    EX0 = 1;       // 使能外部中断 0
}

void main() {
    EA = 1;        // 开总中断
    Timer0_Init();
    ExtInt0_Init();

    while(1) {// 主循环处理计数结果}
}

void Timer0_ISR() interrupt 1 {
    TH0 = 0xFC;
    TL0 = 0x66;

    if(state != 0) {
        counter++;
        if(counter > TIMEOUT) {
            state = 0; // 超时返回空闲状态
            counter = 0;
        }
    }
}

void ExtInt0_ISR() interrupt 0 {
    static unsigned char last_CLK, last_DT;

    switch(state) {
        case 0: // IDLE
            state = 1;
            counter = 0;
            last_CLK = CLK;
            last_DT = DT;
            break;

        case 1: // DEBOUNCE_A
            if(counter >= DEBOUNCE_TIME) {if(CLK == last_CLK && DT == last_DT) {
                    state = 2;
                    counter = 0;
                } else {state = 0;}
            }
            break;

        case 2: // DEBOUNCE_B
            if(counter >= DEBOUNCE_TIME) {if(CLK != last_CLK || DT != last_DT) {
                    // 确认方向
                    if(CLK == DT) {direction = 1; // 顺时针} else {direction = 2; // 逆时针}
                    state = 3;
                    counter = 0;
                } else {state = 0;}
            }
            break;

        case 3: // CONFIRM
            if(counter >= DEBOUNCE_TIME) {
                // 更新计数器
                if(direction == 1) counter++;
                else if(direction == 2) counter--;
                state = 0;
            }
            break;
    }
}

生产环境注意事项

  1. PCB 布局要点
  2. 信号线尽量短
  3. 避免与高频信号平行走线
  4. 编码器外壳接地

  5. ESD 防护

  6. 使用 TVS 二极管阵列
  7. 信号线串联电阻

  8. 机械安装

  9. 确保编码器安装稳固
  10. 避免机械应力导致接触不良

延伸思考

支持多编码器

可以通过以下方式扩展:
1. 使用外部中断扩展芯片
2. 采用矩阵扫描方式
3. 使用带编码器接口的专用 MCU

低功耗优化

  1. 在空闲时关闭上拉电阻
  2. 使用唤醒中断
  3. 降低采样频率

总结

EC11 编码器在 51 单片机上的实现需要注意硬件滤波和软件消抖的结合。通过状态机的方式可以有效解决机械抖动问题,中断法相比查询法能提供更好的实时性。在实际产品中,还需要考虑 ESD 防护和 PCB 布局等工程问题。

以上代码经过实际产品验证,可以直接用于大多数应用场景。根据具体需求,可以调整消抖时间和状态机逻辑。

正文完
 0
评论(没有评论)