
简介本资源面向嵌入式初学者与STM32入门开发者聚焦SG90舵机的硬件控制实践解决从理论到实操的关键断层问题——如何基于STM32生成符合规范的50Hz PWM信号以精确驱动舵机实现0°–180°角度调节。压缩包共205个文件含34个C源文件如stm32f10x_tim.c、usart.c等外设驱动、35个头文件h、36个编译中间文件o/d及Keil5工程核心文件uvprojx、uvoptx、sct等完整覆盖HAL库配置、定时器PWM模式设置、GPIO初始化与角度映射函数等核心代码模块包体大小为4.8MB。已有1497人学习下载资源结构清晰可直接导入Keil μVision5编译运行附带调试可用的hex与asm输出文件便于初学者对照波形验证、理解时钟分频与脉宽计算逻辑并快速迁移至多舵机协同控制等进阶场景。 入行嵌入式那会儿我踩得最狠的坑就是舵机。看教程里别人接上就转轮到我自己要么纹丝不动要么疯狂抖严重的时候直接把单片机给整重启了。后来才明白STC和STM32控制SG90舵机核心从来不是代码本身而是你对PWM信号和电流这两个东西的理解。这篇文章就围绕STM32控制SG90舵机这件事把原理、接线、代码、故障排查以及后续怎么扩展成机械臂或追光系统完整给你捋一遍。适合刚学会GPIO点灯、想碰“真正会动”设备的新手也适合项目里被舵机坑过、想系统排查一遍的老哥。1. SG90舵机工作原理与项目整体思路1.1 这个项目到底在做什么抛开那些花里胡哨的项目背景STM32控制SG90舵机要做的事情本质只有一句话给舵机的信号线输出一个周期20毫秒、脉宽0.5到2.5毫秒的PWM波形用脉宽去对应舵机转动的角度。很多人第一次接触会觉得奇怪为什么不是给个高电平就转、给个低电平就停这就得说到舵机和普通直流电机的区别。普通电机你给电压它就转电压越高转速越快但转到哪个位置电机自己不知道。舵机不一样它内部有位置反馈你给它一个目标角度它自己会转过去然后锁住。而“目标角度”这个信息就是通过PWM的脉宽传进去的。所以这个项目的关键不是写个延时然后翻转电平而是精确地产生一个频率稳定、脉宽可调的PWM信号。从学习角度看这个项目非常适合串知识。它把GPIO、定时器、PWM、时钟树配置、外部中断这些碎片化的知识点串在了一起。做完这个你对STM32定时器的理解会上一个台阶后面再去做电机驱动、无线遥控、机械臂项目底子就打下了。1.2 SG90内部藏着什么小舵机的大结构SG90是一颗非常经典的微型模拟舵机工作电压4.8V到6V扭矩大概1.8kg·cm重量只有9克左右价格也就几块钱几乎是所有嵌入式初学者的第一颗舵机。拆开SG90的外壳里面其实就三大件一个直流电机、一组行星减速齿轮、一个电位器。直流电机转速非常快但扭矩小通过减速齿轮把转速降下来、扭矩提上去最终带动输出轴转动。电位器装在输出轴上它相当于一个位置传感器输出轴转到哪个角度电位器的阻值就对应变化控制电路通过检测这个阻值就知道当前舵机转到哪了。控制逻辑是这样的舵机内部的电路会持续比较两路信号一路是你从STM32发过来的PWM脉宽另一路是电位器反馈回来的当前角度信息。如果两路信号不相等它就驱动电机转直到信号相等才停下来并保持锁定。你给的脉宽是1.5毫秒它就往90度转转到90度就让电位器反馈和1.5毫秒脉宽匹配上然后停住。这就是一个典型的闭环控制。1.3 PWM控制舵机的核心参数SG90的控制信号是50Hz的PWM也就是周期20毫秒。注意这里周期是固定的变的只有高电平持续的时间也就是脉宽。舵机角度脉宽占空比20ms周期下的CCR值0度0.5ms2.5%50045度1.0ms5.0%100090度1.5ms7.5%1500135度2.0ms10.0%2000180度2.5ms12.5%2500这里的CCR值我们后面会详细算。你先记住几个关键数字20毫秒周期、0.5毫秒是0度、1.5毫秒是90度、2.5毫秒是180度。还有一个细节要提醒不同批次的SG90对脉宽的敏感度略有差异有的0度对应0.4ms有的180度对应2.6ms。所以实际项目中如果发现舵机转到某个位置有点偏不要死磕标准值稍微微调一下最小脉宽和最大脉宽就行这在后面设置角度函数里会体现出来。2. 硬件准备与电路连接避坑指南2.1 元器件清单与选型建议做这个项目你需要准备的东西并不多但每一件都有讲究。STM32开发板推荐STM32F103C8T6也就是大家常说的蓝色Pill板。虽然现在STM32价格被炒得有点离谱但F103的资料最全、教程最多你遇到问题搜一下就能找到答案这对新手来说比性能重要得多。别一上来就买F407或者H7性能过剩不说配置不同很多例程跑不通学习成本翻倍。SG90舵机一个买的时候注意区分舵机版本。SG90有模拟舵机和数字舵机的区别新手买普通的就行反正代码是通用的。另外注意市面上很多“SG90”其实是兼容型号参数略有差异不影响入门使用。电源部分是最容易被忽略的。你需要一个能输出5V、持续电流1A以上的电源推荐用手机充电头加一根USB转杜邦线或者直接买一个5V/2A的电源模块。最忌讳的是直接用STM32板的3.3V引脚给舵机供电原因后面详细说。剩下的就是杜邦线若干、面包板一个。如果你觉得面包板接触不良容易导致舵机抖动也可以直接焊接但对新手来说面包板还是更方便调试。2.2 接线方案3根线怎么接SG90引出三根线颜色基本是固定的棕色线是GND红色线是VCC也就是电源正极橙色线是信号线。接线方案如下舵机引脚接到哪里棕色线GND电源负极同时和STM32的GND相连红色线VCC5V电源正极橙色线信号STM32的PA0对应TIM2_CH1这里最关键的一点是共地。舵机的电源和STM32的电源必须是同一个参考地也就是说舵机的GND和STM32的GND要连在一起。如果两个地不共STM32发出的PWM信号就没有参考基准舵机收到的是乱码表现就是疯狂抖动或者乱转。信号线接到PA0是因为PA0默认复用功能之一是TIM2_CH1。如果你想换引脚记得去查STM32F103的数据手册里定时器通道和引脚的对应关系别随便找个引脚就往上怼不是所有引脚都有定时器复用功能的。2.3 电源设计舵机不是USB口能拉的这个坑我当初踩得很惨。一开始偷懒直接把舵机的红色线接到了STM32板的3.3V输出上结果舵机转倒是转了但一顿一顿的而且一启动STM32的LCD屏幕就暗下去紧接着板子重启。原因很简单舵机正常转动时电流几十毫安但一旦堵转或者快速启动瞬间电流能冲到500毫安甚至更高而STM32板载的稳压芯片根本供不了这么大的电流电压一跌单片机就复位了。正确做法是给舵机单独供电。你可以用手机充电头通过USB线给一个面包板供电模块供5V然后把STM32通过USB线连电脑两者的GND接在一起。这样做的好处是STM32和舵机的电源彼此独立舵机启动瞬间的电流冲击不会拖垮单片机的电源。如果你在实验室身边有可调稳压电源那就更方便直接调5V输出给舵机同时把电源的GND和STM32的GND接上就行。2.4 接线检查清单每次上电之前养成检查的习惯。我给自己定的规矩是接线完成后先按这个清单过一遍再插电舵机电源正负极有没有接反SG90接反了虽然不一定立刻烧但发热严重长时间会损坏内部电路。舵机的GND有没有和STM32的GND连在一起没有共地PWM信号就是不正常的。信号线是接到PA0了吗接错引脚程序再对也白搭。供电模块输出电压是不是5V万一调到9V舵机冒烟就是一瞬间的事。3. STM32CubeMX配置与PWM参数计算3.1 开发环境与工具链现在做STM32开发我建议新手上手就直接用STM32CubeMX加HAL库配合Keil MDK或者STM32CubeIDE。有老工程师还在坚持标准外设库说它代码透明、可控性强这话有一定道理但时代变了HAL库配合CubeMX生成初始化代码能把配置定时器这种繁琐工作缩短到几分钟而且代码可读性反而更好。等你想深挖底层的时候再看标准外设库也不迟。需要安装的东西STM32CubeMX用于图形化配置引脚和生成初始化代码。Keil MDK或者STM32CubeIDE用来写用户代码并编译下载。ST-Link驱动如果你用ST-Link下载程序的话大部分山寨ST-Link需要手动装一下驱动。一个串口调试助手后面调试串口控制舵机的时候要用。3.2 CubeMX里怎么配置定时器PWM打开STM32CubeMX新建工程芯片选STM32F103C8Tx然后在PINOUT视图里操作RCC设置里HSE选择Crystal/Ceramic Resonator。这里选外部晶振是因为F103开发板上一般都有8MHz晶振用外部晶振时钟更准PWM频率才稳定。SYS设置里Debug选择Serial Wire。这个非常重要我见过太多人没配这一项程序下载第一次成功第二次就报错因为默认的Debug引脚被重新配置成普通GPIO了导致ST-Link连不上芯片。选上SerialWire之后SWDIO和SWCLK两个引脚被保留给调试器就不会出现这种问题。TIM2设置里Clock Source选Internal ClockChannel1选PWM Generation CH1。这样就生成了PWM模式。然后切换到Clock Configuration选项卡把HCLK改成72MHz。CubeMX会提示你是否确认点Yes它会自动计算出合适的PLL配置。F103的最高主频就是72MHz题外话一句很多人用内部时钟也能跑但如果你后面涉及串口波特率、PWM精确频率强烈建议用外部晶振。回到TIM2的参数配置界面重点来了填这几个参数Prescaler也就是预分频系数填71Counter Period也就是自动重装载值填19999PWM脉冲宽度也就是初始CCR值填1500表示初始90度这三个数字不是凭空拍脑门出来的下面详细算。3.3 PWM频率与占空比计算全过程先理清楚定时器产生PWM的原理。定时器的计数器从0往上数数到自动重装载值就清零重新数这个过程循环往复。计数器的时钟频率由预分频器决定而PWM的输出引脚在计数器值小于比较值CCR的时候输出高电平在计数器值大于等于CCR的时候输出低电平。所以改变CCR就能改变高电平持续的时间也就是脉宽。STM32F103的TIM2挂载在APB1总线上当系统主频配置为72MHz时APB1的分频系数是2APB1时钟是36MHz但定时器时钟倍频后是72MHz。这个细节经常有人搞错如果你把这个倍频忘了算出来的PWM频率就是错的舵机当然不转。接下来计算。定时器时钟72MHz我要把它分频到1MHz也就是每计数一次花1微秒。预分频值PSC的公式是定时器实际时钟 72MHz / (PSC 1)。要让定时器时钟等于1MHz那么PSC 1 72所以PSC 71。计数器从0数到19999一共数了20000个数每个数1微秒所以一个周期是20000微秒也就是20毫秒频率算出来是50Hz正好是SG90需要的PWM频率。所以自动重装载值ARR 19999。然后算角度对应的CCR值。因为计数器每增加1时间过去1微秒所以CCR的值就直接对应脉宽的微秒数。0度脉宽0.5ms也就是500微秒所以CCR 500。180度脉宽2.5ms也就是2500微秒所以CCR 2500。90度脉宽1.5msCCR 1500。这里我做了一个小表格方便你核对目标角度脉宽计算公式CCR值0度0.5ms0.5ms / 1us50090度1.5ms1.5ms / 1us1500180度2.5ms2.5ms / 1us2500从0度到180度CCR从500增加到2500总共差了2000对应180度的角度范围。所以每一度对应的CCR增量就是2000 / 180约等于11.11。这个比例关系就是后面写角度转换函数的数学基础。3.4 关于时钟树的几个常见误区第一个误区觉得内部时钟和外部晶振差不多。对跑个LED闪烁来说确实差不多但PWM频率要求严格的话内部RC振荡器的精度不够频率会有偏差舵机转的角度就会不准确。第二个误区APB1分频和定时器时钟的关系。很多人配置时钟树后发现APB1只有36MHz就以为定时器也是36MHz然后算出来的PSC和ARR全错。实则不然STM32的定时器时钟在APB1分频系数不为1时会自动2倍频。F103默认配置下APB1分频为2定时器时钟就是72MHz。第三个误区改完TIM2参数忘了重新生成代码导致配置是新的但代码还是旧的。CubeMX里改完参数一定要重新点击生成代码按钮让改动同步到工程里然后再去编译。这个低级错误几乎每周都能在交流群里看到人踩。4. 核心代码实现从初始化到角度控制4.1 HAL库PWM初始化代码解读CubeMX生成代码后你会在main.c里看到类似这样的定时器PWM初始化部分static void MX_TIM2_Init(void) { TIM_OC_InitTypeDef sConfigOC {0}; htim2.Instance TIM2; htim2.Init.Prescaler 71; htim2.Init.CounterMode TIM_COUNTERMODE_UP; htim2.Init.Period 19999; htim2.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_PWM_Init(htim2) ! HAL_OK) { Error_Handler(); } sConfigOC.OCMode TIM_OCMODE_PWM1; sConfigOC.Pulse 1500; sConfigOC.OCPolarity TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(htim2, sConfigOC, TIM_CHANNEL_1) ! HAL_OK) { Error_Handler(); } }逐行解读一下。Prescaler 71和我们前面算的一样把72MHz分频成1MHz。CounterMode是向上计数模式计数器从0往上加。Period 19999对应20毫秒周期。AutoReloadPreload使能意味着更新ARR值时会在周期边界生效避免中途跳变造成波形异常。然后配置PWM模式。OCMode选TIM_OCMODE_PWM1这个模式的意思是计数器小于CCR时输出高电平大于等于CCR时输出低电平。Pulse 1500这是初始CCR值对应90度。OCPolarity设HIGH极性为高也就是高电平有效。这段代码只是初始化了定时器外设但注意PWM并没有真正开始输出。你还需要在main函数里调用启动函数否则PA0上不会有波形舵机自然一动不动。4.2 角度转换函数把0到180度映射到CCR值有了前面的数学推导角度转换函数写起来非常直接void set_servo_angle(TIM_HandleTypeDef *htim, uint32_t channel, float angle) { uint16_t ccr; if (angle 0) angle 0; if (angle 180) angle 180; ccr (uint16_t)(500 (uint16_t)(2000.0f * angle / 180.0f)); __HAL_TIM_SET_COMPARE(htim, channel, ccr); }这个函数做了三件事。第一限制输入范围防止你传入负角度或者超过180的角度导致CCR超出合理区间。第二把角度换算成CCR值500是0度对应的CCR2000是180度对应CCR的跨度按比例映射到当前角度。第三通过__HAL_TIM_SET_COMPARE这个宏直接修改定时器的比较寄存器值PWM波形就会立即变化。有一点要提醒角度和CCR是线性关系但SG90实际转动范围不一定是精确的0到180度。有些舵机实际只能转170度左右你发0度的脉宽它停在极限位置时会堵转持续堵转会发热甚至损坏舵机。所以项目里如果需要长期在某个极限角度保持建议在角度函数里把范围设置为5到175给自己留一点余量。4.3 一个完整的main函数示例把前面的内容整合起来最简可运行的main函数是这样的int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1); while (1) { set_servo_angle(htim2, TIM_CHANNEL_1, 0); HAL_Delay(1000); set_servo_angle(htim2, TIM_CHANNEL_1, 90); HAL_Delay(1000); set_servo_angle(htim2, TIM_CHANNEL_1, 180); HAL_Delay(1000); } }注意几个关键点。HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1)这一行必不可少它的作用是把PWM输出真正使能。很多人初始化完发现舵机不动就是忘了这行。HAL_Delay(1000)是让程序停在当前角度1秒方便你观察舵机的转动。如果你想让舵机快速在两个角度之间来回扫动把延时缩短到200毫秒左右就有效果了。一个常见的问题是编译能通过但下载到板子上舵机不转。这时候先检查你的启动函数放的位置以及初始化代码是否真的执行到了HAL_TIM_PWM_Start。我之前见过有人把启动函数放到了某个永远不会执行到的条件分支里舵机当然不转。4.4 实现平滑转动的小技巧用上面的大角度跳变方式舵机会猛地甩过去显得很生硬。如果你想让它像机械臂那样平滑转动可以按小步长递增每走一小步延时一小段时间。例如从0度转到180度不让它一步到位而是每次增加1度延时10毫秒整个转动过程持续约1.8秒看起来就顺畅多了。void set_servo_smooth(TIM_HandleTypeDef *htim, uint32_t channel, float target_now, float target_next, uint16_t delay_ms) { if (target_next target_now) { for (float pos target_now; pos target_next; pos 1.0f) { set_servo_angle(htim, channel, pos); HAL_Delay(delay_ms); } } else { for (float pos target_now; pos target_next; pos - 1.0f) { set_servo_angle(htim, channel, pos); HAL_Delay(delay_ms); } } }这个函数的本质是把一次大角度变化拆成若干小角度变化每次只改一点点。这个方法在后面的追光系统、机械臂项目里很常用因为舵机猛甩容易让整个机械结构产生晃动影响精度。5. 常见问题与排查技巧实录5.1 舵机完全不动按这几个方向查舵机一点反应都没有是最常见的问题。我建议按照这条路径一条条排查下去而不是瞎猜乱换线。第一确认供电。用万用表量一下舵机电源正负极之间的电压是不是在4.8V到6V之间。如果电压为0说明电源没接好或者供电模块没通电。第二确认信号线接对引脚。看你CubeMX里配置的是哪个引脚对照程序里启动的定时器和通道确认橙线接的是同一个引脚。比如CubeMX里TIM2_CH1用的是PA0你就必须接PA0不能随手插到PA1上。第三确认PWM启动函数执行了。在HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1)这一行打个断点调试模式下看程序有没有运行到这里。如果程序停在别处优先检查是否进入了某个死循环。第四用逻辑分析仪或者示波器看PA0脚的波形确认频率是不是50Hz、脉宽是不是在0.5ms到2.5ms之间。手边没有仪器的话也可以把信号线插到有PWM输出的其他开发板上做交叉测试快速判断是舵机坏了还是STM32的问题。5.2 舵机抖动、乱动八成是供电或者干扰舵机抖动是最让人抓狂的问题因为它看起来像是代码有问题但真相往往很朴素。第一种情况供电不足。我用USB口直接供电时舵机空载转还行但只要用手稍微捏住舵机让它受点力就开始剧烈抖动。这是因为堵转电流瞬间增大USB口的电压跌落PWM信号也跟着不稳定了。解决办法就是前面说的独立供电并且加大电源的电流余量。第二种情况接触不良。面包板用久了簧片松弛信号线虚接导致PWM信号时有时无。排查方法是按压一下连接处看抖动是否缓解或者干脆把线直接焊到舵机引脚上。第三种情况脉宽超出了舵机的有效范围。比如你把0度对应的CCR设置成了400脉宽0.4ms低于标准的最小值舵机内部的电路就可能进入不确定状态。所以在角度函数里一定要加范围限制不要传出超出合理范围的脉宽。5.3 单片机复位、舵机把系统带崩舵机一启动STM32板子就重启或者屏幕闪一下、通信中断这些都是同一个根因瞬时大电流把整个系统的电压拉低了。尤其当你用USB口作为唯一电源时电机一启动USB口电压跌落到4V以下单片机就处于欠压状态了。解决方法有三层。最简单的是给舵机独立供电这也是最彻底的办法。其次是给舵机电源两端并联一个大电容比如470uF到1000uF的电解电容它能吸收启动瞬间的电流尖峰缓冲突发大电流对电源的冲击。第三如果你的舵机数量很多比如做一个4自由度机械臂那就需要单独的舵机电源模块并且算好总电流需求。之前看到有人在直流电机驱动项目里问选型舵机控制器的母线电容时怎么选其实道理是一样的。多路舵机同时启动时瞬间电流可能是额定电流的好几倍母线电容就是给这种瞬态冲击兜底的。SG90这种小舵机并联一个470uF电容基本就能稳住你要是带大舵机就得按最大堵转电流和电压跌落范围来计算容量了。5.4 程序卡死在延时函数有网友提到“stm32延时函数delay卡死”这个我遇到过而且不止一次。最常见的场景是你写了一个基于SysTick的延时函数同时在中断服务函数里也调用了延时由于SysTick的中断优先级不是最高导致延时函数永远等不到SysTick中断来更新计数值程序就死在那里。用HAL库的话优先使用HAL_Delay它依赖SysTick中断但不要在中断服务函数里调用它否则基本都会卡死。如果确实需要在中断里做延时用一个简单的for循环空转几微秒或者改用定时器进行非阻塞延时。另外一个坑是你启用了某个外设的中断但中断服务函数里死循环等待一个永远不会发生的标志位也会造成程序卡死在看起来无关的地方。排查方法就是打断点看卡在哪一行而不是瞎猜。5.5 用逻辑分析仪验证PWM波形如果你的舵机代码在别人那边能跑到了自己这边就不行优先级最高的排查方式就是看波形。逻辑分析仪几十块钱一个很多还支持8通道用起来很简单把探针夹在PA0引脚上在配套软件里设置采样率不低于1MHz抓一段波形然后测量周期和脉宽。一个标准的SG90驱动波形周期应该是20毫秒脉宽在0.5毫秒到2.5毫秒之间。如果你抓到波形周期是200毫秒说明PSC和ARR配置错了。如果脉宽一直是0说明CCR设置成了0或者PWM没启动。如果有波形但舵机不转说明可能是电压不够这时候再用万用表量舵机电压。有波形和电压两个数据摆在那里问题通常一眼就定位了。6. 项目扩展从单舵机到多路舵机控制6.1 多路舵机的两种实现方案学会控制一个舵机之后接下来的自然需求就是控制多个舵机比如给两个舵机做云台或者给六个舵机做小机械臂。方案一使用STM32自身的多个定时器通道。F103C8T6的TIM2、TIM3、TIM4各有4个通道理论上可以产生12路PWM每路PWM都可以独立控制一个舵机。这样做的优势是省成本、代码简单缺点是通道引脚固定你设计PCB时要注意引脚冲突。方案二使用专门的舵机驱动板比如PCA9685这款16路PWM驱动芯片。它通过I2C接口通信一个STM32最多可以接多个PCA9685扩展出几十路PWM。这样做的好处是解放了定时器资源而且PCA9685可以外接独立电源多路舵机供电问题也好解决。网上关于PCA9685的驱动代码很多驱动起来也不难。这里提一句选型心得。如果你只是做两三个舵机的云台用STM32的定时器就够用了没必要加额外的芯片。如果你是要做六自由度机械臂或者十几个舵机的机器人再考虑PCA9685。加硬件是有代价的电路复杂度上升、故障点变多能用软件解决的就别加硬件这是嵌入式里一条朴素的原则。多路舵机还有一个要注意的是启动电流的叠加。三四个舵机同时从0度猛甩到180度电流瞬间可能到两安培以上普通USB口根本顶不住。要么把多个舵机的动作错开分时启动要么就老老实实配一个能输出3A以上的5V电源模块。6.2 串口指令控制舵机给舵机加上“遥控器”一个非常实用的扩展是用串口把角度指令发给STM32让STM32解析后控制舵机。这样你就可以在上位机里输入指令来控制机械结构也是后续做上位机视觉引导的雏形。实现思路并不复杂。STM32通过USART1接收上位机发来的字符串比如“A90\n”表示1号舵机转到90度然后解析出舵机编号和角度值调用set_servo_angle函数执行。如果你希望串口接收不阻塞主循环就需要用到HAL库的串口空闲中断配合DMA接收。简单说就是让DMA把串口收到的数据放到缓冲区空闲中断在一帧数据接收完成后触发一次然后在回调函数里解析数据。这个机制在实现上位机实时控制时非常有用不了解的可以单独搜一下中断和DMA配合接收串口数据的例子。通过串口控制舵机我还发现一个实战中的小技巧单片机收到的角度值先做一次范围检查再传给舵机。因为你无法保证上位机传来的数据一定是合法的万一有人发来一个“A999”你直接当成角度传给舵机CCR就会超出合理范围舵机要么堵转要么乱冲。加一道校验是写通信代码时最基本的自我保护。6.3 舵机应用的现实场景与面试考点SG90虽然小但它代表的伺服控制思想在很多行业里都能用到。太阳能追光系统里用两个舵机组成双轴云台带着光敏传感器转向太阳最亮的方向。小型仿生手臂里每个手指一个舵机通过不同的角度组合实现抓取动作。航模和机器人领域更是离不开舵机舵机控制板、母线电容选型这类问题在实际项目中都会遇到。在嵌入式面试中STM32控制舵机也是一个非常经典的考点。面试官通常会从这几个角度问如何用定时器产生50Hz的PWM信号这考的是你对定时器预分频和自动重装载值的计算逻辑。SG90的PWM周期是多少脉宽范围是多少这考你有没有真正调过舵机还是只背过理论。舵机抖动可能是什么原因这种问题考的是排查能力和对硬件电路的理解。如果要同时控制8个舵机方案怎么设计这考的是你的方案选型能力。如果你能把这篇文章里的原理、参数计算、供电注意事项、排查思路都用自己的话讲清楚不管是在面试里还是实际项目中都会比那些只会贴代码的人高出不少。最后分享一个我自己常用的调试习惯。每次拿到一个舵机我会先在纸上把目标角度对应的脉宽、CCR、占空比写一遍再写代码。这样既加深理解也避免调参时乱了套。刚起步的时候不要怕慢把基础打牢了后面做机械臂、机器人你会发现所有复杂的控制底层逻辑和这个SG90其实是相通的。本文还有配套的精品资源点击获取