定时器PWM一、STM32 定时器 PWM 基础理论1. 什么是 PWMPWM 全称脉冲宽度调制简单说周期固定高电平时间可调的方波信号不靠改变电压大小靠高电平占整个周期的比例实现调压、调速、舵机角度控制。2. 三个核心参数周期 T一个高低电平完整循环的时间频率 ff 1 / T每秒循环多少次占空比高电平时间 ÷ 整个周期时间举例周期 20ms高电平 0.5ms → 占空比很小周期 20ms高电平 2.5ms → 占空比很大二、STM32 定时器怎么产生 PWM1. 定时器内部三大关键寄存器预分频器 PSC把 72MHz 系统时钟降频自动重装载寄存器 ARR决定 PWM周期捕获比较寄存器 CCR决定 PWM高电平宽度2. PWM 周期计算公式\(T_{PWM} \frac{(PSC1)\times(ARR1)}{f_{TIM}}\)\(f_{TIM}\) 定时器时钟F103 一般 72MHzPSC预分频值ARR自动重装载值3. 高电平时间由 CCR 决定计数器从 0 往上数数到CCR→ 电平翻转数到ARR→ 计数器清零重新开始所以改 ARR → 改 PWM 频率 / 周期改 CCR → 改占空比、改高电平时间三、STM32 PWM 两种工作模式模式 1最常用舵机必用向上计数计数器 0 → ARR当计数器 CCR输出高电平当计数器 CCR输出低电平模式 2刚好相反小于 CCR 低电平大于 CCR 高电平控制 SG90 一律用PWM 模式 1SG90舵机一、SG90 9g 舵机纯理论原理1. 内部结构直流小电机减速齿轮组减速增扭电位器角度位置反馈控制电路板2. 工作逻辑外部给固定周期 PWM 信号舵机内部检测高电平持续时间对比内部电位器当前角度自动正转 / 反转直到角度匹配 PWM 设定值到达角度后自锁保持位置不动3. 供电与接线红线5V 供电棕线GND橙 / 黄线PWM 信号控制线二、SG90 标准控制时序1. 固定周期SG90 要求 PWM 周期必须严格 20ms对应频率\(f 1/20ms 50Hz\)2. 高电平时间对应角度标准 180° 舵机高电平时间对应角度0.5ms0°1.5ms90°2.5ms180°规律高电平越长 → 角度越大高电平越短 → 角度越小三、PWM 参数配置理论适配 SG90目标生成50Hz 周期 20ms的 PWMSTM32F103 主频 72MHz配置思路定时器时钟 72MHz分频 ARR 算出 20ms 周期调节 CCR 值改变高电平 0.5~2.5ms计算公式对应关系ARR、PSC 固定死 → 保证周期 20ms只改 CCR → 控制 0°~180° 角度四、角度与 CCR 值线性关系理论180° 对应高电平区间0.5ms ~ 2.5ms差值\(2.5 - 0.5 2ms\)每 1° 对应时间\(2ms / 180° \approx 0.0111ms/°\)可以写出公式\(高电平时间(ms) 0.5 \frac{角度}{180} \times 2.0\)再把时间换算成 CCR 数值就能直接用代码赋值控制角度。TIM3 PWM 控制 SG90 舵机一、工程功能使用STM32F103 的 TIM3 通道 2PB5输出50Hz PWM信号控制 SG90 舵机在0°、90°之间来回旋转。二、硬件接线SG90 信号线 → PB5VCC → 5VGND → GND三、main.c#include stm32f10x.h #include main.h #include stdio.h #include sg90.h // 软件毫秒延时粗略 void delay(uint16_t time) { uint16_t i 0; while(time--) { i 12000; while(i--); } } int main() { // 中断分组整个系统只配置一次 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 初始化 PWM GPIO 定时器 SG90_Init(); while(1) { // 舵机转到 90°延时1秒 SG90_Angle(90); delay(1000); // 舵机转到 0°延时1秒 SG90_Angle(0); delay(1000); } }主函数逻辑配置中断分组初始化舵机 PWM 输出死循环90° → 等待 1 秒0° → 等待 1 秒循环往复四、sg90.c#include stm32f10x.h #include sg90.h void SG90_Init(void) { // 1. 定义结构体 GPIO_InitTypeDef GPIO_InitStruct; TIM_TimeBaseInitTypeDef TIM_InitStruct; TIM_OCInitTypeDef TIMOC_InitStruct; // 2. 开时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIOB时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // TIM3时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 复用功能时钟 // 3. 开启 TIM3 部分重映射 → CH2 从 PA7 → PB5 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); // 4. 配置 PB5 为复用推挽输出PWM 输出引脚 GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Pin GPIO_Pin_5; GPIO_InitStruct.GPIO_Speed GPIO_Speed_10MHz; GPIO_Init(GPIOB, GPIO_InitStruct); // // 5. 定时器配置50Hz / 20ms // TIM_InitStruct.TIM_ClockDivision TIM_CKD_DIV1; TIM_InitStruct.TIM_CounterMode TIM_CounterMode_Up; // 自动重装载值 TIM_InitStruct.TIM_Period 200-1; // 预分频 TIM_InitStruct.TIM_Prescaler 7200-1; TIM_TimeBaseInit(TIM3, TIM_InitStruct); // // 6. PWM 模式配置 // TIMOC_InitStruct.TIM_OCMode TIM_OCMode_PWM1; // PWM模式1 TIMOC_InitStruct.TIM_OCPolarity TIM_OCPolarity_Low; // 低电平有效 TIMOC_InitStruct.TIM_OutputState TIM_OutputState_Enable; TIM_OC2Init(TIM3, TIMOC_InitStruct); // 通道2 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); // 使能预装载 // 7. 启动定时器 TIM_Cmd(TIM3, ENABLE); } // // 角度设置函数 // void SG90_Angle(uint16_t angle) { switch(angle) { case 180: TIM_SetCompare2(TIM3, 175); break; case 135: TIM_SetCompare2(TIM3, 180); break; case 90 : TIM_SetCompare2(TIM3, 185); break; case 45 : TIM_SetCompare2(TIM3, 190); break; case 0 : TIM_SetCompare2(TIM3, 195); break; } }五、核心知识点1. 定时器 PWM 周期计算20ms / 50Hz你的配置预分频7200-1重装载200-1计算公式周期 (7200 × 200) / 72M 0.02s 20ms刚好满足 SG90 舵机要求2. PWM 模式 1 作用计数器从 0 往上数小于 CCR低电平大于 CCR高电平配置了低极性有效所以CCR 值越小 → 高电平时间越长 → 角度越大3. 角度与 CCR 对应关系代码里的实测值0° → CCR 19590° → CCR 185180° → CCR 175规律CCR 越小 → 角度越大4. 为什么用 PB5因为开启了GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);TIM3_CH2 从PA7 重映射到 PB5。六、sg90.h 代码#ifndef SG90_H_ #define SG90_H_ #include stm32f10x.h void SG90_Init(void); void SG90_Angle(uint16_t angle); #endif七、程序整体运行流程初始化 GPIO、TIM3、PWM定时器开始输出 20ms 周期的 PWM主循环不断设置 0° / 90°舵机根据 PWM 信号旋转角度