共计 1064 个字符,预计需要花费 3 分钟才能阅读完成。
背景与痛点
编码器在电机控制、位置检测等场景中广泛应用,但 51 单片机处理编码器信号时,新手常遇到两个典型问题:

- 信号抖动 :机械触点式编码器在切换时会产生 10-20ms 的抖动(如图 1),直接读取会导致误计数
- 计数误差 :高速旋转时,51 单片机因主频较低(通常 12MHz),可能漏判脉冲或方向错误
技术选型:查询法 vs 中断法
查询法(轮询)
- 实现简单,在主循环中不断检测 IO 口状态
- 占用 CPU 资源高,适合低速场景(<200 转 / 分钟)
中断法(推荐)
- 通过外部中断触发,实时性更好
- 配合定时器消抖,可稳定处理 500 转 / 分钟以上的信号
核心代码实现
硬件连接(以 EC11 编码器为例)
EC11_A -> P3.2(INT0)
EC11_B -> P3.3(INT1)
GND -> 共地
初始化设置
// 中断初始化
void Encoder_Init() {
IT0 = 1; // INT0 边沿触发
IT1 = 1; // INT1 边沿触发
EX0 = 1; // 开启 INT0 中断
EX1 = 1; // 开启 INT1 中断
EA = 1; // 总中断使能
}
中断服务函数(带消抖逻辑)
volatile int encoder_count = 0;
void INT0_ISR() interrupt 0 {
static unsigned long last_time = 0;
if (millis() - last_time < 5) return; // 5ms 消抖
if (P3_3) encoder_count--; // B 相为高时逆时针
else encoder_count++; // B 相为低时顺时针
last_time = millis();}
性能优化技巧
- 资源占用对比
- 查询法:占用 100% CPU 时间
-
中断法:仅 0.1%~1% 中断开销
-
高频优化方案
- 改用 STC15 系列(1T 单片机)
- 启用 PCA 模块硬件计数
避坑指南
常见问题排查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 计数反向 | AB 相序接反 | 交换 A / B 接线 |
| 高速时漏计 | 中断处理时间过长 | 简化 ISR 代码 / 换 1T 单片机 |
| 静止时自动计数 | 未做消抖或阈值太小 | 调整消抖时间至 5 -10ms |
实战思考题
假设要做一个转速显示装置,要求:
1. 实时显示 0 -999RPM 转速
2. 通过串口上传数据
3. 按键可清零计数
如何优化现有代码实现这些功能?提示:
- 引入定时器计算脉冲间隔
- 使用串口中断避免阻塞
- 添加防误触按键处理
结语
通过本文的代码框架,我在自己的小车项目上成功实现了精确的电机测速。关键点在于:
- 消抖时间需要根据实际编码器调整(用示波器观察信号)
- 计数变量建议用 volatile 修饰防止优化错误
- 对于更复杂的应用,可以结合 T 法(测周期)和 M 法(测频率)
希望这份指南能帮你少走弯路,遇到问题欢迎在评论区交流实测效果~
正文完
