
STM32 实现按键控制舵机与 PWM 呼吸灯,OLED 实时反馈状态
玩嵌入式开发的朋友,多半都对 “用 STM32 驱动外设” 充满兴趣。今天就给大家分享一个我亲手实现的小项目 —— 用按键控制舵机角度,同时驱动 PWM 呼吸灯,还能在 OLED 屏幕上实时显示状态。整个项目从底层驱动到上层逻辑,一步步踩坑、调试,最终顺利跑通,过程里藏着不少实用的嵌入式开发小技巧。 一、项目整体效果展示 先上成品图,直观看看效果👇
• 左侧的蓝色 LED 是 PWM 驱动的呼吸灯,亮度会随参数变化; • 右上角的蓝色小模块是 SG90 舵机,会跟着按键操作转动; • 右侧的 OLED 屏幕上,清晰显示着舵机当前的角度Angle:030和 LED 的亮度值LED:020,每一次按键操作,数值都会同步更新,非常直观。
二、核心模块的代码实现 这个项目的核心,就是用 STM32 的定时器 PWM 功能,同时驱动舵机和 LED,再用按键做交互,OLED 做状态反馈。下面拆解关键代码部分。
- PWM 底层驱动:舵机与呼吸灯的 “动力源” 舵机和呼吸灯都依赖 PWM 信号工作,所以我用了两个定时器分别控制:TIM2 驱动舵机,TIM3 驱动 LED。TIM2 的配置是重点:
舵机需要 50Hz 的 PWM 信号(周期 20ms),所以我把 TIM2 的时钟分频系数 PSC 设为 71(72MHz 主频分频后得到 1μs 的计数周期),自动重装载值 ARR 设为 19999,这样 20000 个计数周期刚好是 20ms, 完美匹配舵机的工作要求。 TIM3 的配置则更适合呼吸灯:同样用 71 分频,ARR 设为 999,得到 1ms 的周期,方便我们通过调整占空比,实现 LED 从亮到暗的平滑过渡。 为了方便上层调用,我还封装了两个设置占空比的函数,直接传入数值就能控制舵机角度和 LED 亮度,非常省心。 2. 按键驱动:实现交互的 “操作按钮” 项目里用了两个按键,一个控制舵机角度增减,一个控制 LED 亮度。为了避免按键抖动导致的误触发,我在代码里加了软件消抖:按下按键后先延时 20ms,再判断一次按键状态,确认按下后再执行操作。 同时还写了长按检测函数,后续如果想实现 “长按快速调整数值” 的功能,直接调用这个函数就能扩展,代码的可维护性拉满。 3. 舵机驱动:把角度转为 PWM 信号 舵机本身不认 “角度”,只认 PWM 的占空比,所以需要一个转换函数:0 度对应 500μs 的高电平,180 度对应 2500μs 的高电平。我用Angle / 180 * 2000 + 500这个公式,把角度值转换成对应的 PWM 计数值,再传给底层的 PWM 设置函数。 这样上层代码里,只需要调用Servo_SetAngle(30),舵机就会自动转到 30 度的位置,不用再手动计算复杂的占空比,逻辑清晰又好用。 4. OLED 显示:状态的 “可视化窗口” 为了能实时看到舵机角度和 LED 亮度,我给项目加了一个 0.96 寸的 I2C OLED 屏幕。只需要把当前的角度和亮度值格式化输出到屏幕上,每次按键操作后更新一次显示,就能实现 “操作 - 反馈” 的闭环。
屏幕上的Angle:030和LED:020,就是我当前设置的舵机角度和 LED 亮度,数值和实际效果完全对应,调试的时候再也不用对着代码猜参数了。
三、项目调试的小坑与解决 开发过程中也踩了不少常见的嵌入式坑,分享给大家避坑:
- 舵机不转:一开始舵机毫无反应,后来才发现是 PWM 的极性设置反了,把TIM_OCPolarity_High改成正确的极性后,舵机立刻就动了。
- LED 不呼吸:一开始 LED 一直亮着,查了半天发现是 TIM3 的预装载没开启,加上TIM_ARRPreloadConfig(TIM3, ENABLE)之后,亮度终于能平滑变化了。
- 按键误触发:一开始没加消抖,按一次键舵机乱跳,加上软件消抖后,操作瞬间变得稳定可靠。
四、项目的扩展与玩法 这个项目的扩展性很强,后续还能玩出更多花样: • 给舵机加个小支架,改成简易的云台,控制摄像头转动; • 把 LED 换成 RGB 灯珠,用三路 PWM 控制,实现彩色呼吸灯; • 加个温湿度传感器,让 OLED 显示环境数据,同时舵机根据温度调整风扇角度。