三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

定时器与 PWM 学习笔记

定时器与 PWM 学习笔记

文章目录

  • STM32 定时器与 PWM 学习笔记
    • 一、定时器分类
      • STM32F103C8T6 定时器资源
      • 系统时钟树要点
      • 三个重要概念
      • 定时时间计算公式
    • 二、定时器中断配置流程
      • 步骤
      • 代码模板
    • 三、PWM(脉冲宽度调制)
      • 工作原理
      • PWM 模式
      • PWM 配置步骤
      • PWM 代码模板
      • 实时修改占空比
      • 通道与引脚对应关系(F103C8T6 常用)
    • 四、典型应用场景
      • 1. LED 呼吸灯
      • 2. 舵机控制
      • 3. 直流电机调速
    • 五、重要注意事项
    • 六、小结

STM32 定时器与 PWM 学习笔记

基于 B站 江科大自化协 STM32 教程整理


一、定时器分类

STM32F103C8T6 定时器资源

类型数量位数功能
高级定时器 (TIM1)116位PWM 互补输出、死区控制、刹车功能
通用定时器 (TIM2/3/4)316位定时、PWM、输入捕获、输出比较、编码器
基本定时器 (TIM6/7)216位仅定时功能(无外部 I/O)

系统时钟树要点

  • 系统时钟 SYSCLK = 72MHz(外部 8MHz 晶振 → PLL 倍频)
  • APB2 总线:72MHz(TIM1 挂载在 APB2)
  • APB1 总线:36MHz,但挂载在 APB1 上的定时器(TIM2/3/4/6/7)时钟 = 36MHz × 2 =72MHz(预分频器倍频)

三个重要概念

概念缩写作用
预分频器PSC对时钟分频,决定计数频率
自动重装载值ARR决定计数周期
计数器CNT当前计数值

定时时间计算公式

T = ( P S C + 1 ) × ( A R R + 1 ) T I M CLK T = \frac{(PSC + 1) \times (ARR + 1)}{TIM_{\text{CLK}}}T=TIMCLK(PSC+1)×(ARR+1)

例如:TIM_CLK = 72MHz,PSC = 7199,ARR = 9999 → T = 1s


二、定时器中断配置流程

步骤

  1. 开启定时器时钟(RCC_APB1PeriphClockCmdRCC_APB2PeriphClockCmd
  2. 配置时基单元(TIM_TimeBaseInit
  3. 使能更新中断(TIM_ITConfig
  4. 配置 NVIC(NVIC_PriorityGroupConfig+NVIC_Init
  5. 使能定时器(TIM_Cmd

代码模板

voidTimer_Init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Prescaler=7199;// PSCTIM_TimeBaseStructure.TIM_Period=9999;// ARRTIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_RepetitionCounter=0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);TIM_Cmd(TIM2,ENABLE);}voidTIM2_IRQHandler(void){if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){TIM_ClearITPendingBit(TIM2,TIM_IT_Update);// 在这里写定时触发的操作}}

三、PWM(脉冲宽度调制)

工作原理

通过改变占空比(Duty Cycle)来控制模拟量输出:

  • 频率:由 ARR 决定,f P W M = T I M C L K ( P S C + 1 ) × ( A R R + 1 ) f_{PWM} = \frac{TIM_{CLK}}{(PSC + 1) \times (ARR + 1)}fPWM=(PSC+1)×(ARR+1)TIMCLK
  • 占空比:由 CCR(捕获/比较寄存器)决定,D u t y = C C R A R R + 1 Duty = \frac{CCR}{ARR + 1}Duty=ARR+1CCR
  • 分辨率:由 ARR 的位数决定,如 ARR = 999,分辨率为 0.1%

PWM 模式

模式行为极性
PWM 模式 1CNT < CCR 时为有效电平向上计数
PWM 模式 2CNT > CCR 时为有效电平向上计数

PWM 配置步骤

  1. 开启 GPIO 时钟和复用功能(RCC_APB2PeriphClockCmd+ AFIO)
  2. 配置 GPIO 为复用推挽输出(GPIO_Init设置GPIO_Mode_AF_PP
  3. 开启定时器时钟
  4. 配置时基单元(TIM_TimeBaseInit
  5. 配置输出比较单元(TIM_OCInit
  6. 使能定时器(TIM_Cmd

PWM 代码模板

voidPWM_Init(void){// 1. GPIO 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);// 2. GPIO 配置(以 PA0 → TIM2_CH1 为例)GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;// 复用推挽输出GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);// 3. 定时器时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);// 4. 时基单元TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Prescaler=71;// 72MHz / 72 = 1MHzTIM_TimeBaseStructure.TIM_Period=999;// 1kHz PWMTIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);// 5. 输出比较配置TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse=0;// 初始占空比 0%TIM_OC1Init(TIM2,&TIM_OCInitStructure);// 6. 使能TIM_Cmd(TIM2,ENABLE);}

实时修改占空比

voidPWM_SetCompare1(uint16_tCompare){// 注意:库函数 TIM_SetCompare1 没有检查参数上限// 如果传入值 > ARR,会一直输出高电平(100% 占空比)TIM_SetCompare1(TIM2,Compare);}

通道与引脚对应关系(F103C8T6 常用)

定时器通道 1通道 2通道 3通道 4
TIM1PA8PA9PA10PA11
TIM2PA0PA1PA2PA3
TIM3PA6PA7PB0PB1
TIM4PB6PB7PB8PB9

四、典型应用场景

1. LED 呼吸灯

// 在主循环中渐变改变 CCRuint8_tdir=0;uint16_tpwm_val=0;while(1){PWM_SetCompare1(pwm_val);if(dir==0)pwm_val++;elsepwm_val--;if(pwm_val>=999)dir=1;if(pwm_val==0)dir=0;Delay_ms(1);// 控制呼吸速度}

2. 舵机控制

脉宽角度
0.5ms
1.0ms45°
1.5ms90°
2.0ms135°
2.5ms180°

设置 PWM 频率 = 50Hz(周期 20ms),ARR = 19999(PSC = 71)

// SG90 舵机常用配置(50Hz)// ARR = 20000-1, PSC = 72-1// 0°: CCR = 500// 90°: CCR = 1500// 180°: CCR = 2500

3. 直流电机调速

使用 L298N 等驱动模块,通过 PWM 占空比控制电机转速:

// 0~100% 占空比对应 0~ARRPWM_SetCompare1((uint16_t)(speed/100.0*ARR));

五、重要注意事项

  1. TIM_SetCompare 参数范围:库函数不检查传入值是否 ≤ ARR,超出会导致持续高电平而非 100% 占空比
  2. 重映射:部分引脚存在默认复用功能冲突时,需要通过 AFIO 重映射到备用引脚(如GPIO_PinRemapConfig
  3. 高级定时器 TIM1 需要额外使能TIM_CtrlPWMOutputs(TIM1, ENABLE)才能使 PWM 输出
  4. PSC 和 ARR 是 16 位寄存器,最大值为 65535
  5. 影子寄存器:PSC 和 ARR 有影子寄存器,更新事件发生时才会真正生效;可设置TIM_ARRPreloadConfig控制更新时机
  6. 时钟分割 (CKD):用于数字滤波器,不是定时器时钟的分频,配置死区时才起作用

六、小结

要实现配置要点
定时中断时基单元 + NVIC
PWM 输出时基单元 + OC 通道 + AF_PP 引脚
占空比调节TIM_SetCompareX(TIMx, val)
输入捕获测量外部信号频率/脉宽
编码器模式电机速度/位置采集

核心记忆口诀:时钟-引脚-时基-通道 四步走,PSC 决定单位时间,ARR 决定周期,CCR 决定占空比。

整理时间:2026-07-27

← 返回列表