共计 1753 个字符,预计需要花费 5 分钟才能阅读完成。
增量式编码器测速原理
增量式编码器通过输出两路相位差 90°的方波信号(A/ B 相),配合 51 单片机的定时器捕获功能,可以实现电机转速的精确测量。这种测速方法在智能小车、步进电机控制等场景中尤为重要——它不仅能反馈实时转速,还能通过脉冲数计算位移量。

硬件计数 vs 软件计数方案对比
- 硬件计数(PCA 模块)
- 优点:不占用 CPU 资源,适合高频脉冲(>10kHz)
-
缺点:51 单片机多数型号仅 1 个 PCA 模块,难以同时捕获 A / B 相
-
软件计数(定时器捕获)
- 优点:灵活配置,可同时处理多路信号
- 缺点:高频时可能丢失脉冲(建议 <5kHz)
推荐初学者优先使用定时器捕获方案,其实现更直观且资源占用少。
硬件电路设计要点
-
信号上拉
编码器输出端需接 10kΩ 上拉电阻至 VCC,避免悬空状态导致误触发 -
RC 消抖电路
在 A / B 相线上并联 100nF 电容 +100Ω 电阻组成低通滤波,可有效抑制毛刺 -
接线示意图
- 编码器 A 相 → P3.2(INT0)
- 编码器 B 相 → P3.3(INT1)
- GND 共地处理
定时器配置与中断实现
// 定时器 1 初始化(1ms 时基)void Timer1_Init() {
TMOD &= 0x0F; // 清除高 4 位
TMOD |= 0x10; // 16 位定时模式
TH1 = 0xFC; // 1ms@11.0592MHz
TL1 = 0x66;
ET1 = 1; // 允许中断
TR1 = 1; // 启动定时器
}
// 外部中断 0 服务函数(A 相下降沿触发)void EX0_ISR() interrupt 0 {
static uint16_t last_capture;
uint16_t current_capture = TH1 << 8 | TL1;
pulse_interval = current_capture - last_capture; // 计算脉冲间隔
last_capture = current_capture;
}
转速计算公式
假设编码器线数为 N(脉冲数 / 转),测得脉冲间隔为 t(ms):
转速 (rpm) = 60000 / (N × t)
例如:500 线编码器测得脉冲间隔 2ms → 转速 =60000/(500×2)=60rpm
软件滤波实战
采用移动平均滤波算法,建立 10 组数据的滑动窗口:
#define FILTER_WINDOW 10
volatile uint16_t speed_buf[FILTER_WINDOW];
volatile uint8_t buf_index = 0;
uint16_t Moving_Average_Filter(uint16_t new_val) {
static uint32_t sum = 0;
sum -= speed_buf[buf_index]; // 减去最旧数据
sum += new_val; // 加入新数据
speed_buf[buf_index] = new_val;
buf_index = (buf_index + 1) % FILTER_WINDOW;
return sum / FILTER_WINDOW; // 返回平均值
}
窗口大小选择原则:
– 低速场景(<100rpm):建议 15-20 点
– 高速场景(>1000rpm):5- 8 点即可
避坑指南
- 信号抖动问题
- 在中断入口添加 10ms 延时消抖
-
采用两次采样法确认有效边沿
-
高低速参数调整
- 低速时增大定时器周期(如 10ms)
-
高速时改用 PCA 计数模式
-
中断响应优化
- 关闭其他不必要中断
- 关键变量加 volatile 修饰
完整代码框架
#include <reg52.h>
volatile uint16_t pulse_interval = 0;
void main() {Timer1_Init();
EX0 = 1; // 允许 INT0 中断
IT0 = 1; // 下降沿触发
EA = 1; // 总中断允许
while(1) {uint16_t rpm = 60000 / (500 * pulse_interval);
rpm = Moving_Average_Filter(rpm);
}
}
拓展思考
要实现双向测速,可通过检测 A / B 相的相位关系:
– A 相领先 B 相 90° → 正转
– B 相领先 A 相 90° → 反转
可在中断函数中添加如下判断逻辑:
if(P3.2 && !P3.3) direction = FORWARD;
else if(!P3.2 && P3.3) direction = BACKWARD;
通过这篇教程,你应该已经掌握了 51 单片机编码器测速的核心方法。接下来可以尝试结合 PID 算法实现闭环速度控制,这将让你的电机控制项目更上一层楼。
