新闻详情

新闻详情

首页 / 资讯中心 / 详情

STM32 PWM舵机控制与OLED角度显示实战:从原理到代码

发布时间:2026/9/1 14:27:04来源:尧图网络
STM32 PWM舵机控制与OLED角度显示实战:从原理到代码
简介面向嵌入式初学者的STM32微控制器应用资源演示利用定时器输出脉宽调制信号驱动SG90舵机并通过有机发光二极管屏幕实时显示转动角度。压缩包共81个文件以头文件、源文件、启动文件及Keil工程配置为主完整覆盖标准外设库、系统初始化、硬件驱动等代码整体大小316KB可直接在Keil中打开编译。已有3022人学习下载适合入门阶段掌握定时器脉宽调制输出、占空比计算以及屏幕驱动原理。重点代码模块包括电机控制、屏幕显示等层次清晰便于阅读修改也可在此基础上加入按键交互、多路舵机控制等扩展功能对课程设计或项目实践有直接参考价值。工程结构规范注释明确能帮助开发者深入理解嵌入式软硬件协同工作的完整流程。 STM32的PWM驱动舵机顺带用一块OLED屏幕实时显示舵机角度——这个项目我第一次做完的时候感觉比跑通LED点灯要爽得多因为它真正把“数字世界”和“物理动作”连到了一起。你写一个角度值舵机就真的转到那个位置屏幕上也同步跳出一个数字那种“你的代码在控制真实设备”的实感是纯软件项目体会不到的。这个项目用到的核心元件就四样一块STM32F103C8T6最小系统板、一个SG90舵机、一块0.96寸OLED屏幕、几条杜邦线。成本加起来不到三十块但覆盖的知识点相当扎实定时器PWM输出原理、舵机角度控制协议、I2C通信、OLED显示驱动、HAL库工程配置……非常适合刚学完点灯想进阶的朋友也适合想快速把PWM控制逻辑跑通、后面要往机械臂或小车方向走的开发者。我最初做这个项目是因为帮朋友搭一个小型机械臂的演示样机需要用舵机控制关节角度同时要能直观看到角度反馈。当时手头正好有这些模块就顺手把它们串在了一起。做完之后发现这套组合几乎是嵌入式入门阶段性价比最高的一课很多产品原型里也常这么干——用OLED做状态显示用PWM精确控制执行机构。下面我把踩过的坑、调通的代码、整理好的配置流程都写出来照着做基本一遍过。1. 项目拆解这套组合到底在解决什么问题1.1 四个模块各司其职先把这个项目拆开看。STM32是主控负责计算和逻辑PWM是控制方式本质上是STM32用定时器输出特定占空比的方波信号舵机是执行机构把PWM信号里的脉宽信息“翻译”成转动角度OLED是人机交互界面把当前状态变成人类能直接读懂的字符和数字。很多人会把这四样东西当成四个独立小实验分别做完就丢到一边这太可惜了。把它们整合起来你会发现嵌入式项目的基本骨架就出来了控制端STM32、执行端舵机、显示端OLED。以后无论做复杂点的四轴飞行器、机械臂还是智能小车都逃不开这个框架。单独玩模块只能学“点”串起来才能学到“线”和“面”。1.2 为什么是STM32而不是Arduino或51说实话如果单纯为了控制一个舵机Arduino 一行Servo.write()就搞定了51单片机配合延时也能让舵机转起来。那为什么我还要用STM32三个原因。第一STM32的定时器是硬件级PWM发生器启动之后CPU完全不用管PWM波形会持续输出。你可以在舵机平稳转动的同时去刷新OLED、处理按键、跑算法这是51和Arduino软件模拟PWM方案做不到的。第二HAL库配合STM32CubeMX配置定时器基本就是鼠标点几下的事学习成本比想象中低。第三从实用角度看STM32是当前国内嵌入式岗位最主流的平台把这一套PWM逻辑吃透以后换F4、H7系列几乎是无缝迁移。核心原理不变变的只是库函数名。2. 硬件选型与接线按这个清单买不会出错2.1 关键器件清单先把硬件清单列出来都是便宜好买的型号。器件型号/规格作用参考价格主控板STM32F103C8T6最小系统板生成PWM信号、驱动OLED8-15元舵机SG90 9g舵机执行转动动作5-10元显示屏0.96寸I2C OLEDSSD1306显示角度等信息8-15元供电5V/3.3V面包板电源模块或USB转TTL给板子和舵机供电10元以内连接线杜邦线若干模块间连接几块钱舵机方面常见的有SG90和MG90S。SG90是塑料齿轮扭矩在1.8kg·cm左右胜在便宜炸了不心疼。MG90S是金属齿轮扭矩略大更耐造但价格也高一些。初学者先用SG90完全够。注意这里说的都是传统模拟舵机通过PWM信号控制如果是飞特舵机这类总线舵机走的是串口通信而不是PWM那属于另一套玩法后面我会在扩展部分提到。2.2 接线方案与两个关键教训接线是新手翻车率最高的一步我直接把接好的对应关系列出来。模块引脚接STM32引脚说明舵机信号线橙/黄PA0TIM2_CH1PWM输出引脚舵机VCC红5V供电舵机需要独立5V电源舵机GND棕/黑GND必须与STM32共地OLEDSCLPB6I2C1_SCLI2C时钟线OLEDSDAPB7I2C1_SDAI2C数据线OLEDVCC3.3VOLED常用3.3V供电OLEDGNDGND同样共地接线有两个关键细节都是我用教训换来的。第一舵机一定要单独供电不要直接从STM32板子的3.3V引脚给舵机供电。舵机启动瞬间电流可以达到几百毫安甚至超过1A板载LDO会被直接拉垮现象就是舵机一转STM32立刻复位。我第一次偷懒共用3.3V结果排了半天电路最后发现全是电源的锅。第二OLED的SCL和SDA接反不会烧模块但屏幕就是不亮这种“听起来是软件问题、实际是硬件接错”的情况最磨人接线时多核对一次能省半小时。3. 舵机控制原理与PWM参数计算3.1 PWM信号如何“指挥”舵机舵机内部结构其实很简单一个直流电机、一组减速齿轮、一个电位器加上一小块控制电路。输入PWM信号后控制电路会解析高电平持续的时间也就是脉宽与电位器反馈回来的当前角度做比较有误差就驱动电机转到目标位置。所以说到底舵机内部是一个小的闭环系统。说人话就是你给舵机的信号线送一列方波每隔20毫秒来一次高电平脉冲高电平持续的时间长短决定了舵机转到哪。SG90的对应关系是经典的0.5ms脉宽 → 0度1.5ms脉宽 → 90度2.5ms脉宽 → 180度中间角度和脉宽基本是线性关系。所以控制舵机本质上就是精确控制PWM的脉宽也就是控制定时器的比较寄存器值。听起来很绕实际做起来就一个公式的事。3.2 定时器参数计算一步步算给你看我用TIM2来做PWM输出配置思路是把72MHz的计数时钟分频成1MHz这样计数器每加1就代表1微秒方便直接映射脉宽。分频计算72MHz / 72 1MHz所以预分频寄存器PSC填71硬件是0到71共72分频。然后20ms的周期对应20000微秒自动重装载值ARR填19999计20000次溢出一次。此时比较寄存器CCR的值就直接等于脉宽微秒数CCR 500 → 0.5ms脉宽 → 舵机0度CCR 1500 → 1.5ms脉宽 → 舵机90度CCR 2500 → 2.5ms脉宽 → 舵机180度如果想转任意角度angle换算公式就是CCR 500 (2500 - 500) / 180 * angle 500 angle * (100 / 9) ≈ 500 angle * 11.11注意(2500-500)/180的结果不是整数代码里直接用整数除法会产生截断误差。我的做法是用浮点运算再强转成整数或者用angle * 100 / 9这种先放大再除的写法。误差是零点几微秒级别对舵机来说完全无感。4. CubeMX配置与工程生成4.1 定时器PWM的CubeMX配置步骤在STM32CubeMX里选好STM32F103C8T6芯片后按下面的路径配置左侧菜单Timers - TIM2把Channel1的模式改成PWM Generation CH1。在Parameter Settings里Prescaler填71Counter Period填19999Pulse初始值填500让舵机上电停在0度Auto Reload Preload选Enabled。RCC里把HSE设成外部晶振然后在Clock Configuration里确认TIM2时钟是72MHz。这一步非常容易翻车因为STM32的APB1预分频不是1时定时器时钟会偷偷乘2。如果你看到TIM2的时钟不是72MHzPWM频率就不对舵机压根不认。工程配置里选MDK-ARM工具链生成代码。配置完成后PA0引脚会自动变成TIM2_CH1功能硬件上把舵机信号线插到PA0就行。4.2 OLED显示的CubeMX配置OLED走I2C接口配置比定时器还简单。在Connectivity - I2C1里勾选I2C速度默认Standard Mode100kHz就好。PB6和PB7会自动分配为I2C1_SCL和I2C1_SDA。OLED驱动代码我建议直接用SSD1306的HAL库移植版本这类开源驱动在网上非常多核心API就三个初始化、清屏、显示字符串。底层只需要实现I2C写命令和写数据的函数驱动库会自动处理SSD1306那几十条初始化命令。我知道有些“硬核”教程喜欢让人从寄存器开始手写SSD1306驱动但我觉得完全没必要。SSD1306的初始化序列参数非常多涉及电荷泵电压、显示时钟分频、段重映射等概念没有一定经验很容易被绕晕。先用现成库把整个流程跑通建立“PWM和OLED在同一工程里协作”的完整认知再回头研究驱动细节效率高得多。5. 代码实现从PWM输出到OLED显示5.1 舵机角度控制函数封装HAL库的PWM操作核心就两个API// 启动PWM输出 HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1); // 动态修改比较值也就是修改脉宽 __HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_1, ccr);把这个封装成一个角度控制函数// 舵机角度控制angle范围0~180 void Servo_SetAngle(uint8_t angle) { if (angle 180) angle 180; uint16_t ccr 500 (uint16_t)((float)angle * 100.0f / 9.0f); __HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_1, ccr); }实测下来TIM2_CH1输出50Hz的PWMCCR按公式从500变到2500SG90就能从0度顺滑转到180度。这里要提醒一下如果你看到舵机在极限位置发出“嗡嗡”的抖动声说明CCR设到了超出舵机行程的值电机一直堵转在端点。赶紧把代码里的角度上下限卡死堵转时间长了舵机齿轮和电机都会挂。5.2 OLED显示逻辑OLED这边SSD1306驱动库的工作机制是“显存”模式。屏幕128x64像素对应1024字节的显存你在内存里操作像素点然后调用刷屏函数一次性把整块显存推送到屏幕上。显示角度值的代码大概是这样的#include ssd1306.h void OLED_ShowAngle(uint8_t angle) { char buf[20]; sprintf(buf, Angle: %d, angle); ssd1306_Fill(Black); // 清屏 ssd1306_SetCursor(10, 3); ssd1306_WriteString(buf, Font_11x18, White); ssd1306_UpdateScreen(); // 刷新到屏幕 }字体选择上Font_11x18在0.96寸OLED上显示效果最协调不大不小。Font_16x26适合做大数字主显示但一行放不下太多内容。建议把Font_7x10和Font_11x18混着用标题小字、数值大字信息层次更清晰。另外每次刷屏前记得调用ssd1306_Fill(Black)清屏否则新旧字符叠在一起会变成一团乱码。5.3 主程序整合与效果主循环用一个简单的“来回扫描”逻辑舵机从0度转到180度再返回0度OLED同步显示角度。int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); MX_I2C1_Init(); ssd1306_Init(); HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1); uint8_t angle 0; int8_t step 1; while (1) { Servo_SetAngle(angle); OLED_ShowAngle(angle); angle step; if (angle 180 || angle 0) step -step; HAL_Delay(20); } }20毫秒的延时配上每次1度的变化从0度到180度大约3.6秒走完肉眼看起来是平滑的摆动。这里有个很多人忽略的坑PWM启动函数必须在初始化完成后调用一次而且不要在循环里反复调用HAL_TIM_PWM_Start。我在调试时犯过这个错误把启动函数放在循环里结果舵机输出周期性顿挫排查好久才发现是重复启动导致定时器输出状态被反复重置。6. 常见问题与排查技巧实录6.1 舵机不转、抖动或乱转这个话题我太有发言权了因为每个问题都真金白银踩过。按可能性从高到低排列**电源不足或供电方式不对。**舵机旋转和堵转时电流差异巨大堵转时峰值电流能到1A。如果舵机和STM32共用同一路3.3V板子直接重启。解决思路是单独一路5V给舵机地线再和STM32共地。**PWM周期不是20ms。**舵机认的PWM频率是50Hz。如果CubeMX里PSC和ARR算错周期偏到10ms或者40ms舵机要么不转要么只抖动不定位。有示波器或逻辑分析仪的话直接量PA0引脚的波形看周期没有仪器就先把ARR改成49995ms周期听舵机有没有刺耳声音有声音说明PWM在输出只是参数不对。**信号线接错引脚。**TIM2_CH1在很多板子上默认映射到PA0但个别板子因为IO资源冲突可能需要重映射。如果确认配置没问题舵机还没反应查一下芯片手册里AFIO重映射的相关寄存器看是否需要打开__HAL_AFIO_REMAP_TIM2_ENABLE()。6.2 OLED不亮、花屏、乱码OLED的坑集中在三个点**I2C地址不匹配。**SSD1306常见地址是0x3C或0x3D由模块上地址电阻的焊接位置决定。如果驱动库里写死的地址和模块不一致屏幕完全无响应。最直接的办法在初始化前用一个I2C扫描函数把所有地址扫一遍看哪个地址有ACK响应然后改驱动库头文件里的地址宏。**I2C速度过快。**有些OLED模块在400kHz快速模式下会偶发花屏或刷新不完整。CubeMX里把I2C速度降到100kHz标准模式绝大多数情况能解决。**初始化时序问题。**带RST引脚的OLED模块如果复位引脚悬空且模块上没有上电自动复位电路驱动库初始化大概率失败。把RST引脚接到STM32任意一个GPIO初始化前先拉低10ms再拉高。如果模块是四针的无RST基本都有自动复位电路可以跳过这一步。6.3 舵机角度和OLED显示总差几度一开始我也被这个问题困扰过逻辑上角度值是从同一个变量传给舵机和OLED的理论上结果必然一致。后来才发现这是SG90这类模拟舵机的“死区”特性决定的。模拟舵机内部比较电路有滞回范围脉宽变化量小于某个阈值大概是2-5微秒时舵机根本不会响应。也就是说程序里每次把CCR改1微秒舵机可能等累计到5微秒才动一下。所以OLED显示的“目标角度”和舵机实际的“物理角度”之间存在一个系统性的静态误差在模拟舵机上完全合理不影响功能。如果想让OLED显示真实角度只能加角度传感器比如电位器或磁编码器做实反馈或者换成支持角度回传的总线舵机。对当前这个项目来说接受这几度误差就好。7. 扩展思路从舵机到机械臂再到闭环控制这个项目做完后继续扩展的方向我觉得有两条很值得走。一条是“单舵机变多舵机”。TIM2本身有4个通道可以同时输出4路独立的PWM控制4个舵机这已经是一个简单的机械臂关节控制原型了。每个通道的CCR独立设置互不干扰。如果舵机数量超过4个可以加一块PCA9685 16路PWM驱动板通过I2C接口控制代码量增加不大但舵机数量翻几倍。另一条是“开环变闭环”。给舵机输出轴上加一个角度传感器比如AS5600磁编码器通过I2C读回真实角度显示在OLED上。然后STM32把目标角度和当前角度的差值喂给PID算法计算出PWM输出值这样舵机就能精确停在设定角度上误差远小于模拟舵机的死区。这就从“控制舵机”进阶到了“伺服系统”是机械臂、云台、平衡车这些项目的核心技术路径。如果你对仿生手臂机器人感兴趣那总线舵机比如飞特舵机会是下一步的方向。总线舵机用一根信号线串联所有舵机不仅能接收控制指令还能回传位置、温度、电压等状态构建的机械臂自由度更高、走线也更简洁。但总线舵机的调试方式和PWM舵机完全不同需要先掌握串口通信和总线协议。所以我的建议是先用PWM舵机把信号控制、定时器配置、状态显示这一套基本功练扎实再上总线舵机效率最高也最不容易一头雾水。最后再分享一个我在调试中非常喜欢的小技巧OLED上除了显示角度数值还可以画一条动态“进度条”——用ssd1306_DrawRectangle画一个矩形框根据角度值按比例填充长度。别小看这一条条竖线调试舵机限位时你根本不需要眯着眼看数字变化余光扫一眼进度条就知道大概在哪个位置省精力得多。方法很简单矩形宽度等于angle * 64 / 180每次先覆盖清空再重画即可。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

InfluxDB时序数据错乱、时间漂移彻底修复 2026/9/1 16:54:50

InfluxDB时序数据错乱、时间漂移彻底修复

InfluxDB时序数据错乱、时间漂移彻底修复技术栈:Kubernetes v1.32.13 Rocky Linux 8.6 InfluxDB 2.7.x Containerd 1.7.x操作环境 / 对接原理 / 详细步骤 / 完整命令 / 配置文件 / 验证流程 / 排错方案InfluxDB时序数据错乱、时间漂移彻底修复操作环境K8s 集群 3…

阅读更多 →
C# MES源码深度解析:技术选型、工单流转与落地实践 2026/9/1 16:54:50

C# MES源码深度解析:技术选型、工单流转与落地实践

简介:这是一套基于C#开发的生产制造执行系统(MES)完整源码,面向制造业信息化开发者、工业软件工程师及高校智能制造方向学习者,聚焦解决车间级生产过程管控、工序追溯与权限精细化管理等核心问题。资源包共825个文件&a…

阅读更多 →
小白程序员入门大模型:OpenClaw vs Hermes 多 Agent 架构深度解析 2026/9/1 16:54:50

小白程序员入门大模型:OpenClaw vs Hermes 多 Agent 架构深度解析

本文深入探讨了多 Agent 架构在 AI 中的应用,对比了 OpenClaw 和 Hermes 的实现路径。多 Agent 架构通过将复杂任务拆分为多个独立执行的单元,有效解决了单 Agent 在长序列处理、工具调用、错误隔离等方面的瓶颈。文章详细解析了多 Agent 的定义、使用动…

阅读更多 →
Claude Code 与 Codex 双向桥接:本地文件协议实现 AI Agent 协作 2026/9/1 16:54:50

Claude Code 与 Codex 双向桥接:本地文件协议实现 AI Agent 协作

做了多年 AI 编程工具落地,我最大的感受是:单个 CLI 再强,也只是“一个人干活”。真正贴近团队协作时,Claude Code 负责全局重构和方案设计,Codex 负责快速写测试和命令执行,两个工具各有长板。问题在于&am…

阅读更多 →
机器人规模化部署:从ROS 2架构到自动化运维的工程实践 2026/9/1 16:54:50

机器人规模化部署:从ROS 2架构到自动化运维的工程实践

机器人规模化落地,早已不是实验室里展示几个酷炫动作那么简单。它意味着从单台样机到成千上万台稳定运行的生产力工具,从定制化调试到标准化部署,从核心算法突破到整个供应链的成熟。这背后是一场涉及硬件选型、软件架构、生产测试、部署运维…

阅读更多 →
逻辑先行:贾子认知免疫理论——从证伪主义的逻辑破产到宣称范式的识别与免疫 2026/9/1 16:51:49

逻辑先行:贾子认知免疫理论——从证伪主义的逻辑破产到宣称范式的识别与免疫

逻辑先行:认知免疫理论 ——从证伪主义的逻辑破产到宣称范式的识别与免疫 摘要 本文从一个简单而致命的逻辑审查出发:波普尔证伪主义的核心命题"可证伪的才是科学"本身不可证伪,按其自身标准不属于科学。这不是一个需要翻遍文献才…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞