共计 1286 个字符,预计需要花费 4 分钟才能阅读完成。
背景痛点
在电机控制系统中,旋转编码器是测量转速和位置的关键传感器。它通过输出脉冲信号来反映电机的转动情况,但实际应用中常遇到以下问题:

- 信号抖动:机械振动导致编码器输出信号出现毛刺
- 计数丢失:高速旋转时单片机可能丢失脉冲计数
- 响应延迟:传统轮询方式无法及时响应脉冲变化
技术方案
方案对比
- 外部中断法
- 优点:响应速度快,可捕获每个脉冲
-
缺点:占用中断资源,高频时可能丢失中断
-
定时器捕获法
- 优点:硬件自动记录脉冲时间
- 缺点:需要特定定时器支持,51 单片机资源有限
最终选择:外部中断 + 定时器组合方案,兼顾响应速度和计数可靠性。
硬件设计
正交编码器接口电路:
- 上拉电阻计算:
R = (Vcc - Vih_min) / Iih 典型值:Vcc=5V,Vih_min=2V,Iih=0.1mA → R=30kΩ(取 10kΩ 标准值) - 滤波电容:100nF 陶瓷电容并联在信号线对地
核心实现
寄存器配置
// 定时器 1 模式配置
TMOD = 0x10; // 模式 1,16 位定时器
TCON = 0x50; // TR1=1, IT1=1(边沿触发)// 中断优先级设置
IP = 0x04; // 提升 INT1 中断优先级
中断服务程序
void INT1_ISR() interrupt 2 {
static uint32_t pulse_count = 0;
pulse_count++;
// 添加去抖动逻辑
if((TMR1L > 0x20) || (TMR1H > 0)) { // 最小间隔检测
valid_pulse_count++;
}
TMR1L = 0;
TMR1H = 0;
}
移动平均滤波
#define FILTER_WINDOW 8
uint16_t moving_average(uint16_t new_sample) {static uint16_t buffer[FILTER_WINDOW];
static uint8_t index = 0;
static uint32_t sum = 0;
sum -= buffer[index];
buffer[index] = new_sample;
sum += new_sample;
index = (index + 1) % FILTER_WINDOW;
return (uint16_t)(sum / FILTER_WINDOW);
}
避坑指南
- 中断响应时间
-
最大转速计算:
N_max = 1/(4×t_int) (rps) 典型 51 单片机 t_int≈10μs → N_max=25krps -
防抖动策略
- 硬件:增加 RC 滤波(时间常数≈1ms)
-
软件:最小脉冲间隔判断
-
32 位计数溢出
- 每 100ms 读取并清零计数值
- 使用
volatile修饰共享变量
验证数据
| 设定转速(RPM) | 实测值(RPM) | 误差率(%) |
|---|---|---|
| 500 | 498 | 0.4 |
| 1500 | 1492 | 0.53 |
| 3000 | 2978 | 0.73 |
扩展思考
- STM8 移植要点
- 使用 TIM1 的编码器接口模式
-
注意时钟树配置差异
-
传感器选型
- 光电编码器:高精度(>1000PPR),成本高
- 霍尔传感器:中低精度(<100PPR),抗干扰强
总结
本方案通过合理的硬件设计和软件优化,在 51 单片机上实现了可靠的转速测量。关键点在于:
- 精确的定时器配置
- 有效的软件滤波
- 严谨的中断管理
这套方法稍作修改即可适用于各种嵌入式平台,为电机控制项目提供了实用的测速解决方案。
正文完
