【手把手教你用STM32 HAL库驱动编码器电机与OLED显示】——(1)从零搭建电机测速与实时监控系统
1. 项目背景与硬件选型第一次接触编码器电机时我被它精准的测速能力惊艳到了。这种电机内置光电或霍尔传感器每转能输出数百个脉冲配合STM32的编码器模式可以轻松实现0.1rpm级别的测速精度。这次我们选用的是常见的直流减速电机带AB相编码器搭配STM32F103C8T6最小系统板和0.96寸OLED总成本不到50元。硬件清单STM32F103C8T6核心板72MHz主频3个通用定时器TB6612电机驱动模块比L298N发热小支持1.2A持续电流0.96寸OLED显示屏I2C接口128x64分辨率带编码器的直流减速电机6V/200RPM13线编码器12V/5V/3.3V电源系统注意电机与MCU电源隔离注意编码器线数直接影响测速分辨率常见的有13线、20线等。本文示例采用13线编码器转一圈产生13×452个脉冲2. 硬件连接详解接线时最容易出错的是编码器相位接反导致计数方向错误。我的经验是先接电机驱动部分确保电机能正常转动后再接编码器。TB6612接线AO1→电机正极AO2→电机负极AIN1→PA15方向控制1AIN2→PB3方向控制2PWMA→PB6PWM信号编码器接线A相→PA6TIM3_CH1B相→PA7TIM3_CH2OLED接线SCL→PB8I2C1_SCLSDA→PB9I2C1_SDA实测中发现若电机电源与MCU共地PWM频率建议设置在1kHz以上以避免可闻噪声3. CubeMX关键配置3.1 时钟树配置将HCLK设置为72MHzAPB1定时器时钟保持72MHz编码器模式需要。建议使用外部晶振测速更稳定。3.2 PWM输出配置TIM4选择TIM4 Channel1→PWM Generation CH1Prescaler71Counter Period999产生1kHz PWM开启TIM4输出HAL_TIM_PWM_Start(htim4, TIM_CHANNEL_1);3.3 编码器模式TIM3选择Encoder Mode触发边沿选择Rising Edge设置PA6/PA7为Pull-up避免悬空干扰计数器周期设为6553516位最大值// 编码器初始化代码 HAL_TIM_Encoder_Start(htim3, TIM_CHANNEL_ALL); __HAL_TIM_SET_COUNTER(htim3, 0); // 计数器归零3.4 中断定时器TIM1配置为10ms中断一次Prescaler720-1, Period1000-1开启中断HAL_TIM_Base_Start_IT(htim1);3.5 I2C配置使用默认400kHz速率即可注意PB8/PB9要配置为开漏输出OLED屏通常不支持时钟拉伸4. 核心代码实现4.1 速度计算算法在TIM1中断回调函数中计算实时速度void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim htim1) { int16_t pulse (int16_t)__HAL_TIM_GET_COUNTER(htim3); __HAL_TIM_SET_COUNTER(htim3, 0); // 读取后立即清零 // 速度公式脉冲数/(编码器线数×4)/时间 speed (float)pulse / (13.0 * 4) / 0.01f; // 单位转/秒 } }4.2 OLED显示优化避免在中断中刷新全屏采用局部刷新策略// 在main循环中更新显示 while(1) { char buf[16]; sprintf(buf, %.1f, speed); OLED_ShowString(0, 2, buf, 12, 0); // 仅更新数值部分 sprintf(buf, %d, encoder_counter); OLED_ShowString(0, 4, buf, 12, 0); HAL_Delay(50); }4.3 抗干扰处理实际测试中发现电机启停时会产生干扰脉冲在编码器输入引脚并联100pF电容软件滤波连续3次读数一致才更新显示// 滤波示例 int16_t last_pulse 0; uint8_t stable_cnt 0; void GET_NUM(void) { int16_t current __HAL_TIM_GET_COUNTER(htim3); if(abs(current - last_pulse) 5) { // 波动小于5个脉冲 stable_cnt; if(stable_cnt 3) { encoder_counter current; stable_cnt 0; } } last_pulse current; }5. 调试技巧与常见问题问题1电机转动但脉冲计数为零检查编码器供电通常需要3.3V-5V用示波器查看PA6/PA7是否有方波信号确认CubeMX中TIM3配置为Encoder Mode问题2速度显示跳动大尝试增加TIM1中断周期如改为20ms检查电机机械结构是否松动在电源端增加100uF电解电容问题3OLED显示花屏检查I2C上拉电阻通常4.7kΩ降低I2C时钟频率到100kHz确保初始化时有200ms延时记得第一次调试时我因为忘记设置GPIO上拉导致编码器计数方向随机变化。后来在CubeMX中配置Pull-up后问题立即解决。这也让我明白硬件问题往往需要软硬件结合排查。6. 效果展示与数据验证通过串口打印原始脉冲数和计算速度进行验证脉冲数: 260 → 速度: 1.00r/s (60rpm) 脉冲数: 390 → 速度: 1.50r/s (90rpm)与激光测速仪对比误差小于±2%满足大多数控制需求。这个项目最让我惊喜的是STM32的编码器接口稳定性——即使电机高速反转计数器也能准确记录。下一步可以尝试加入PID闭环控制让电机速度更稳定。