定时器、计数器和 PWM 到底是什么关系?从工作原理到 STM32 实战详解

发布时间:2026/8/3 8:21:15
定时器、计数器和 PWM 到底是什么关系?从工作原理到 STM32 实战详解 定时器、计数器和 PWM 到底是什么关系从工作原理到 STM32 实战详解前言在学习 STM32、GD32、51 单片机或者其他 MCU 时经常会遇到下面几个概念定时器计数器PWM预分频器自动重装载寄存器比较寄存器输入捕获输出比较。很多初学者会产生疑问定时器和计数器是不是两个不同的外设PWM 为什么要通过定时器产生修改 ARR 和 CCR 为什么可以改变 PWM 的频率和占空比定时器明明只是在计数为什么还能测量脉宽、输出波形甚至读取编码器实际上定时器、计数器和 PWM 并不是三个完全独立的功能。它们之间的核心关系可以用一句话概括定时器的本质是一个按照时钟脉冲不断变化的计数器而 PWM 是利用计数器数值与比较寄存器进行比较后产生的周期性高低电平信号。本文将从底层原理开始详细讲清楚三者之间的关系。一、先理解什么是计数计数就是对一个个脉冲进行累加或递减。假设每来一个脉冲计数器的值增加 1第1个脉冲到来CNT 1 第2个脉冲到来CNT 2 第3个脉冲到来CNT 3 …… 第100个脉冲到来CNT 100这里的CNT可以理解为计数器当前保存的数值。如果脉冲来自单片机内部稳定的时钟那么计数值就可以反映经过的时间。如果脉冲来自单片机外部引脚那么计数值就可以反映外部事件发生的次数。因此定时和计数的区别主要不在计数器本身而在于用来驱动计数器的脉冲来自哪里。二、什么是计数器计数器英文通常称为Counter计数器的作用是统计脉冲数量。一个最简单的计数器内部可以理解为输入脉冲 ↓ 计数逻辑 ↓ CNT计数寄存器每输入一个有效脉冲计数寄存器就增加或减少一次。例如外部传感器每检测到一个产品输出一个脉冲 ↓ 单片机计数器累计脉冲数量 ↓ 得到生产线产品数量计数器常见应用包括统计按键次数统计传感器脉冲统计产品数量测量电机转速读取旋转编码器统计流量计脉冲统计风扇 TACH 信号测量外部信号频率。例如一个风扇每旋转一圈输出 2 个脉冲在 1 秒内检测到 100 个脉冲那么风扇转速为转速 100 ÷ 2 × 60 3000 RPM三、什么是定时器定时器英文称为Timer定时器的本质仍然是计数器。区别在于定时器通常由 MCU 内部时钟驱动。例如计数器每隔 1 微秒增加一次0 μsCNT 0 1 μsCNT 1 2 μsCNT 2 3 μsCNT 3 …… 1000 μsCNT 1000因为每次计数所代表的时间是确定的所以只要知道计数次数就能知道经过了多长时间。因此时间 计数次数 × 每次计数所需时间例如每次计数时间 1 μs 计数次数 1000那么经过的时间就是1000 × 1 μs 1 ms这就是定时器能够“定时”的根本原因。四、定时器和计数器的核心区别定时器和计数器通常使用的是同一个硬件模块。它们的主要区别是时钟来源不同。对比项目定时器计数器时钟来源MCU 内部时钟外部输入脉冲统计对象时间外部事件数量主要用途延时、周期中断、PWM脉冲计数、转速统计本质对内部时钟计数对外部脉冲计数核心寄存器CNTCNT可以简单记忆为内部时钟驱动 → 定时器 外部脉冲驱动 → 计数器因此很多 MCU 的用户手册会将该外设统一称为Timer/Counter也就是“定时器/计数器”。五、定时器内部有哪些核心模块一个典型 MCU 定时器可以简化为内部时钟或外部时钟 ↓ 预分频器 PSC ↓ 计数时钟 CK_CNT ↓ 计数器 CNT ↓ ┌─────────────┴─────────────┐ ↓ ↓ 自动重装载寄存器 ARR 比较寄存器 CCR ↓ ↓ 周期控制/溢出中断 输出比较/PWM最重要的寄存器包括PSC预分频寄存器CNT计数器寄存器ARR自动重装载寄存器CCR捕获比较寄存器。下面分别介绍。六、PSC预分频器有什么作用单片机的系统时钟通常很高。例如72 MHz 168 MHz 200 MHz如果直接使用 72 MHz 时钟驱动计数器那么计数器每秒需要计数 7200 万次。每次计数时间为1 ÷ 72 MHz ≈ 13.89 ns这样的计数速度太快不方便产生毫秒级或者秒级定时。因此需要使用预分频器对时钟进行分频。假设定时器输入时钟为fTIM 72 MHz预分频寄存器设置为PSC 71那么实际计数频率为fCNT fTIM ÷ (PSC 1)代入数据fCNT 72 MHz ÷ 72 1 MHz此时计数器每计数一次所需时间为TCNT 1 ÷ 1 MHz 1 μs需要特别注意预分频倍数通常是PSC 1而不是 PSC。因为当 PSC 等于 0 时定时器仍然需要以原始时钟运行而不是停止。七、CNT计数器寄存器CNT 保存定时器当前的计数值。在向上计数模式中0 → 1 → 2 → 3 → …… → ARR → 0在向下计数模式中ARR → ARR-1 → ARR-2 → …… → 0 → ARR在中心对齐模式中0 → 1 → 2 → …… → ARR → ARR-1 → …… → 0软件可以读取 CNT从而知道定时器当前已经运行到哪个位置。例如uint32_tcurrent_count;current_count__HAL_TIM_GET_COUNTER(htim3);CNT 可以用于获取当前计数值计算两个事件之间的时间实现输入捕获测量外部信号频率统计外部脉冲产生 PWM。八、ARR自动重装载寄存器ARR 决定计数器计到多少后重新开始。例如ARR 999在向上计数模式下CNT 的变化为0 → 1 → 2 → …… → 998 → 999 → 0一共经历1000次计数也就是ARR 1如果每次计数需要 1 μs那么一个完整周期为1000 × 1 μs 1 ms定时器频率为1 ÷ 1 ms 1 kHz因此在普通向上计数模式下定时器更新频率 定时器输入时钟 ÷ [(PSC 1) × (ARR 1)]即fUPDATE fTIM / [(PSC 1) × (ARR 1)]九、什么是定时器溢出当 CNT 计数到 ARR 后重新回到 0通常会产生一次更新事件。例如CNT998 → 999 → 0这次从 ARR 回到 0 的过程通常称为溢出更新事件Update Event。如果使能更新中断MCU 就会进入定时器中断服务函数。例如voidHAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef*htim){if(htim-InstanceTIM3){/* 每次定时器溢出执行一次 */}}因此定时器可以周期性执行任务例如每 1 ms 更新系统时基每 10 ms 扫描按键每 100 ms 读取传感器每 1 s 刷新设备状态周期性喂看门狗周期性执行控制算法。十、什么是 PWMPWM 的英文全称是Pulse Width Modulation中文称为脉宽调制PWM 是一种周期固定或可调、同时可以改变高电平持续时间的方波信号。一个 PWM 信号通常包含两个重要参数频率占空比。例如高电平0.5 ms 低电平0.5 ms 总周期1 msPWM 频率为1 ÷ 1 ms 1 kHz占空比为0.5 ms ÷ 1 ms × 100% 50%PWM 波形可以表示为高电平 ┌─────┐ ┌─────┐ │ │ │ │ 低电平 ─┘ └───────┘ └─────── ←──── 一个周期 ────→十一、PWM 和定时器是什么关系PWM 并不是一个完全独立的硬件模块。大多数 MCU 都是利用定时器产生 PWM。其核心过程是定时器 CNT 不断计数CNT 与比较寄存器 CCR 比较根据比较结果控制引脚输出高电平或低电平CNT 到达 ARR 后重新开始周期性重复以上过程形成 PWM。因此ARR决定PWM周期 CCR决定高电平宽度 PSC决定计数速度 CNT表示当前计数位置这就是定时器产生 PWM 的根本原理。十二、CCR比较寄存器如何控制占空比CCR 的英文含义是Capture/Compare Register中文通常称为捕获比较寄存器在 PWM 输出模式中CCR 用作比较值。假设ARR 999 CCR 500计数器从 0 计数到 999。在常见的 PWM 模式 1、向上计数、高电平有效配置下可以理解为当 CNT CCR 时输出高电平 当 CNT ≥ CCR 时输出低电平对应过程如下CNT 0499高电平 CNT 500999低电平高电平持续 500 个计数周期总周期为 1000 个计数周期因此占空比为500 ÷ 1000 × 100% 50%一般情况下可以使用下面的近似公式计算占空比 CCR ÷ (ARR 1) × 100%需要注意0% 和 100% 占空比的边界行为可能受到PWM 模式输出极性芯片具体实现CCR 与 ARR 的关系等因素影响。实际工程中需要结合芯片参考手册确认。十三、PWM频率如何计算在普通向上计数、边沿对齐模式下PWM频率 定时器输入时钟 ÷ [(PSC 1) × (ARR 1)]即fPWM fTIM / [(PSC 1) × (ARR 1)]假设定时器输入时钟72 MHz PSC 71 ARR 999计数频率为72 MHz ÷ 72 1 MHzPWM 频率为1 MHz ÷ 1000 1 kHz如果CCR 250那么占空比约为250 ÷ 1000 × 100% 25%最终得到频率1 kHz 占空比25%十四、定时器、计数器和PWM的关系图三者之间的关系可以概括为定时器/计数器外设 │ 本质CNT计数 │ ┌──────────────┴──────────────┐ │ │ 内部时钟驱动 外部脉冲驱动 │ │ 定时器 计数器 │ │ 延时、周期中断 脉冲统计、转速测量 │ CNT与CCR进行比较 │ PWM因此可以用一句更加准确的话总结定时器和计数器是同一计数硬件在不同输入时钟下的两种用途PWM 则是定时器计数和输出比较功能组合后的结果。十五、用生活中的例子理解三者关系可以把定时器想象成一个人在数节拍。定时器节拍器每隔固定时间响一次滴、滴、滴、滴……人每听到一次声音就加 1。由于每次声音间隔固定所以数到 100 就代表经过了固定时间。这就是定时器。计数器如果不再听节拍器而是每有一个人经过门口就加 1那么统计的是人数。这就是计数器。PWM假设每数 10 个数为一轮09在 02 时打开灯在 39 时关闭灯开、开、开、关、关、关、关、关、关、关重复执行就形成了 30% 占空比的 PWM。十六、STM32定时器常见工作模式STM32 定时器不仅可以实现普通定时和 PWM还支持多种功能。1. 基本定时用于周期性产生中断。PSC ARR ↓ 确定定时周期应用系统节拍周期任务传感器采集软件定时。2. 外部脉冲计数通过外部引脚输入脉冲驱动 CNT 计数。应用流量计转速计产品计数频率统计。3. 输出比较当 CNT 等于 CCR 时执行指定动作。例如翻转输出拉高输出拉低输出产生中断。4. PWM输出通过 CNT 与 CCR 比较产生周期性高低电平。应用LED调光风扇调速电机控制舵机控制蜂鸣器DAC模拟输出。5. 输入捕获当外部引脚检测到边沿时将当前 CNT 保存到 CCR。例如第一次上升沿CCR1 100 第二次上升沿CCR1 1100两次边沿之间相差1100 - 100 1000个计数如果每次计数为 1 μs那么信号周期为1000 μs 1 ms频率为1 kHz输入捕获常用于测量频率测量周期测量脉宽测量 PWM 占空比读取风扇 TACH 信号。6. 编码器模式定时器可以同时读取编码器的 A、B 两相信号。根据相位关系判断旋转方向旋转速度旋转位置。应用电机控制旋钮机器人关节位置检测。十七、STM32产生1 kHz、50%占空比PWM实例假设条件如下定时器时钟72 MHz 目标PWM频率1 kHz 目标占空比50%首先将 72 MHz 分频到 1 MHzPSC 72 - 1 71此时计数频率 72 MHz ÷ 72 1 MHz每次计数时间为1 μs要产生 1 kHz PWM周期需要1 ÷ 1 kHz 1 ms1 ms 对应 1000 次计数因此ARR 1000 - 1 99950% 占空比对应CCR 500最终参数PSC 71 ARR 999 CCR 500十八、STM32 HAL库配置示例下面以 TIM3 通道 1 为例。1. 初始化代码#includemain.hTIM_HandleTypeDef htim3;staticvoidMX_TIM3_Init(void){TIM_ClockConfigTypeDef clock_config{0};TIM_MasterConfigTypeDef master_config{0};TIM_OC_InitTypeDef pwm_config{0};htim3.InstanceTIM3;htim3.Init.Prescaler71;htim3.Init.CounterModeTIM_COUNTERMODE_UP;htim3.Init.Period999;htim3.Init.ClockDivisionTIM_CLOCKDIVISION_DIV1;htim3.Init.AutoReloadPreloadTIM_AUTORELOAD_PRELOAD_ENABLE;if(HAL_TIM_Base_Init(htim3)!HAL_OK){Error_Handler();}clock_config.ClockSourceTIM_CLOCKSOURCE_INTERNAL;if(HAL_TIM_ConfigClockSource(htim3,clock_config)!HAL_OK){Error_Handler();}if(HAL_TIM_PWM_Init(htim3)!HAL_OK){Error_Handler();}master_config.MasterOutputTriggerTIM_TRGO_RESET;master_config.MasterSlaveModeTIM_MASTERSLAVEMODE_DISABLE;if(HAL_TIMEx_MasterConfigSynchronization(htim3,master_config)!HAL_OK){Error_Handler();}pwm_config.OCModeTIM_OCMODE_PWM1;pwm_config.Pulse500;pwm_config.OCPolarityTIM_OCPOLARITY_HIGH;pwm_config.OCFastModeTIM_OCFAST_DISABLE;if(HAL_TIM_PWM_ConfigChannel(htim3,pwm_config,TIM_CHANNEL_1)!HAL_OK){Error_Handler();}HAL_TIM_MspPostInit(htim3);}2. 启动PWMintmain(void){HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM3_Init();if(HAL_TIM_PWM_Start(htim3,TIM_CHANNEL_1)!HAL_OK){Error_Handler();}while(1){}}运行后TIM3 通道 1 对应引脚会输出频率1 kHz 占空比50%十九、运行过程中修改PWM占空比可以直接修改 CCR。例如设置为 25%__HAL_TIM_SET_COMPARE(htim3,TIM_CHANNEL_1,250);设置为 75%__HAL_TIM_SET_COMPARE(htim3,TIM_CHANNEL_1,750);可以封装成函数voidPWM_SetDuty(TIM_HandleTypeDef*htim,uint32_tchannel,floatduty_percent){uint32_tperiod;uint32_tcompare;if(duty_percent0.0f){duty_percent0.0f;}if(duty_percent100.0f){duty_percent100.0f;}period__HAL_TIM_GET_AUTORELOAD(htim)1U;compare(uint32_t)(period*duty_percent/100.0f);__HAL_TIM_SET_COMPARE(htim,channel,compare);}调用PWM_SetDuty(htim3,TIM_CHANNEL_1,30.0f);即可将占空比设置为约 30%。需要注意100% 占空比在不同 MCU、PWM 模式和输出配置下可能需要特殊处理实际使用时应确认参考手册中的比较行为。二十、运行过程中修改PWM频率PWM 频率由 PSC 和 ARR 共同决定。如果保持 PSC 不变只修改 ARRvoidPWM_SetFrequency(TIM_HandleTypeDef*htim,uint32_ttimer_count_frequency,uint32_tpwm_frequency){uint32_tarr;if((pwm_frequency0U)||(timer_count_frequencypwm_frequency)){return;}arrtimer_count_frequency/pwm_frequency;if(arr0U){return;}__HAL_TIM_SET_AUTORELOAD(htim,arr-1U);__HAL_TIM_SET_COUNTER(htim,0U);}假设计数频率为1 MHz设置 PWM 为 2 kHzPWM_SetFrequency(htim3,1000000U,2000U);计算得到ARR 1 000 000 ÷ 2000 - 1 499需要注意修改 ARR 后如果希望占空比保持不变也必须按照新的 ARR 重新计算 CCR。否则原来的 CCR 不变占空比就会发生变化。二十一、为什么修改ARR会同时影响频率和占空比假设原来ARR 999 CCR 500占空比约为500 ÷ 1000 50%现在将 ARR 改为ARR 499但 CCR 仍然是CCR 500此时 CCR 已经接近或超过计数周期范围输出可能接近持续有效。因此修改频率时必须同步调整 CCR。例如希望 ARR 改成 499 后仍保持 50%CCR (499 1) × 50% 250二十二、PWM模式1和PWM模式2有什么区别在常见的向上计数模式下可以简化理解为PWM模式1CNT CCR有效电平 CNT ≥ CCR无效电平PWM模式2CNT CCR无效电平 CNT ≥ CCR有效电平两者输出逻辑相反。如果再结合输出极性高电平有效 低电平有效最终引脚波形还会发生变化。因此出现下面问题时需要检查PWM模式选错输出极性选错CCR设置错误引脚复用错误。二十三、边沿对齐和中心对齐有什么区别1. 边沿对齐计数器只向上或只向下计数0 → 1 → 2 → …… → ARR → 0PWM 的一个边沿固定在周期起点。优点配置简单频率计算直观适合普通 LED、蜂鸣器和风扇控制。2. 中心对齐计数器先向上再向下0 → 1 → 2 → …… → ARR ARR-1 → ARR-2 → …… → 0PWM 脉冲相对于周期中心对称。优点谐波特性更好适合电机控制适合逆变器减小部分电磁干扰。中心对齐模式的周期计算与边沿对齐不同不能直接套用普通向上计数公式必须结合具体 MCU 的计数规则计算。二十四、PWM有哪些实际用途1. LED调光通过改变 PWM 占空比改变 LED 平均电流。占空比越大 → LED越亮 占空比越小 → LED越暗2. 直流电机调速PWM 控制电机驱动器的导通时间。占空比越大 → 平均电压越高 → 转速通常越高需要注意MCU 的 PWM 引脚不能直接驱动大功率电机必须经过MOSFET三极管电机驱动芯片隔离器件。3. 风扇调速四线风扇通常包含电源地TACH转速反馈PWM调速输入。MCU 输出 PWM 控制风扇速度同时通过计数器或输入捕获读取 TACH 信号。这是定时器、计数器和 PWM 同时使用的典型案例PWM输出 → 控制风扇速度 计数器/输入捕获 → 读取风扇转速 定时器中断 → 周期计算RPM4. 舵机控制常见舵机使用固定周期的 PWM 信号通过高电平脉宽控制角度。例如周期约20 ms 高电平约1 ms → 某一端角度 高电平约1.5 ms → 中间位置 高电平约2 ms → 另一端角度舵机更关心的是高电平脉宽而不只是占空比。5. 蜂鸣器发声改变 PWM 频率可以改变音调频率越高 → 音调越高 频率越低 → 音调越低改变占空比可以影响驱动效果和音量表现。6. 模拟电压输出PWM 经过低通滤波器后可以得到近似模拟电压。例如MCU PWM输出 ↓ RC低通滤波 ↓ 近似直流电压平均电压近似为VOUT ≈ VCC × 占空比如果 MCU 电压为 3.3 V占空比为 50%滤波后平均电压约为3.3 V × 50% 1.65 V二十五、一个风扇控制实例中的三者关系假设系统需要输出 25 kHz PWM 控制风扇读取风扇 TACH 脉冲每 1 秒计算一次转速。可以这样分配定时器定时器A产生PWM内部时钟 ↓ PSC和ARR设置25 kHz周期 ↓ CCR调节占空比 ↓ 输出PWM控制风扇定时器B统计TACH脉冲风扇TACH信号 ↓ 外部计数器或输入捕获 ↓ 统计1秒内脉冲数定时器C产生1秒周期中断内部时钟 ↓ 每1秒产生中断 ↓ 读取脉冲数量 ↓ 计算RPM如果风扇每转一圈输出 2 个脉冲RPM 1秒内脉冲数 × 60 ÷ 2这就是一个完整的“定时器计数器PWM”工程应用。二十六、常见问题一PWM引脚没有波形可以按照下面的顺序排查。1. 定时器时钟是否使能例如__HAL_RCC_TIM3_CLK_ENABLE();2. GPIO端口时钟是否使能例如__HAL_RCC_GPIOA_CLK_ENABLE();3. GPIO是否配置为复用功能PWM 引脚不能配置成普通输出模式需要设置为定时器复用功能。4. 复用编号是否正确不同 STM32 型号中同一个引脚可能对应不同 AF 编号。5. PWM是否启动仅完成初始化并不会自动产生输出还需要HAL_TIM_PWM_Start(htim3,TIM_CHANNEL_1);6. 通道是否匹配检查配置的是 CH1 还是 CH2引脚对应哪个通道启动函数使用哪个通道。7. ARR和CCR是否合理例如ARR 999 CCR 0输出可能一直处于无效状态。二十七、常见问题二PWM频率计算不正确最常见的原因是定时器实际输入时钟判断错误。在部分 STM32 中APB 分频为 1 时定时器时钟等于 APB 时钟APB 分频不为 1 时定时器时钟可能等于 APB 时钟的 2 倍。例如APB1时钟 36 MHz APB1预分频不为1TIM2、TIM3 等定时器的实际时钟可能是72 MHz如果错误地按照 36 MHz 计算最终 PWM 频率会相差 2 倍。因此必须根据时钟树RCC配置芯片参考手册确认定时器真实时钟。二十八、常见问题三改变占空比后波形异常可能原因包括CCR超过ARRARR改变后没有更新CCR预装载没有使能更新事件未产生PWM模式错误输出极性错误比较值在错误通道中修改。建议保证0 ≤ CCR ≤ ARR 1同时在修改 ARR 后重新计算 CCR。二十九、常见问题四低频PWM不稳定低频 PWM 通常需要很大的计数周期。如果 PSC 太小ARR 可能超过定时器位宽。例如 16 位定时器最大 ARR 通常为65535如果计算结果大于 65535就需要增大 PSC使用 32 位定时器采用软件分频使用重复计数器重新选择时钟源。三十、常见问题五高频PWM分辨率太低PWM 占空比分辨率主要由 ARR 决定。例如ARR 999一个计数单位对应1 ÷ 1000 0.1%如果ARR 99一个计数单位对应1 ÷ 100 1%因此ARR越大 → 占空比分辨率越高但是在定时器时钟固定时PWM频率越高 → ARR通常越小这意味着 PWM 频率和占空比分辨率之间存在权衡。例如高频 PWM开关速度快但占空比分辨率可能降低低频 PWMARR 可以更大分辨率更高。三十一、为什么定时器是MCU最重要的外设之一定时器并不只是用来“延时”。它实际上可以完成周期中断精确延时外部脉冲计数PWM输出输入捕获输出比较编码器读取单脉冲输出死区控制互补PWM电机换相触发ADC触发DMA多定时器同步。很多复杂功能的底层本质上仍然是计数 比较 捕获 更新理解了 CNT、PSC、ARR 和 CCR就掌握了定时器最核心的逻辑。三十二、面试中如何回答三者关系如果面试官问定时器、计数器和 PWM 有什么关系可以这样回答定时器的本质是计数器。 当计数器由内部固定时钟驱动时可以根据计数次数计算时间 因此表现为定时器。 当计数器由外部脉冲驱动时可以统计外部事件数量 因此表现为计数器。 PWM则是在定时器计数过程中将CNT与CCR比较 并根据比较结果控制输出高低电平。 其中PSC控制计数速度ARR控制PWM周期 CCR控制有效电平持续时间也就是占空比。三十三、总结定时器、计数器和 PWM 之间不是相互独立的关系。它们的核心关系是计数器是基础 定时器是对内部时钟计数 外部计数是对外部脉冲计数 PWM是计数器与比较器共同产生的输出波形四个核心寄存器的作用如下寄存器作用PSC控制计数时钟分频CNT保存当前计数值ARR决定计数周期CCR决定比较位置和PWM占空比在普通向上计数模式下计数频率 定时器时钟 ÷ (PSC 1)PWM频率 定时器时钟 ÷ [(PSC 1) × (ARR 1)]PWM占空比 ≈ CCR ÷ (ARR 1) × 100%最后用一句话总结定时器通过内部时钟驱动计数器记录时间计数器也可以统计外部脉冲而 PWM 则通过比较 CNT 与 CCR在 ARR 确定的周期内控制输出高低电平。