2. CubeMX配置PWM输出:时钟树设置、定时器配置、PWM通道引脚分配、参数计算

好,咱们正式开始动手配置。这一节我会带着你,一步步在CubeMX里把PWM输出给搭起来。别小看这个配置过程,我见过不少新手,甚至有些老手,都在这里栽过跟头。配置错了,后面调代码就是白费功夫。

2.1 时钟树设置——PWM的“心跳”来源

PWM信号的频率,说白了就是由定时器的时钟源决定的。你想想看,如果时钟源不准,那输出的PWM频率肯定也跑偏。

我个人习惯,在打开CubeMX后,第一件事就是点开Clock Configuration标签页。这里要做的,就是给定时器选一个合适的时钟源。

核心原则:定时器的时钟源,通常来自APB1或APB2总线。APB1最高频率一般是36MHz或45MHz(取决于具体型号),APB2最高频率通常是72MHz或90MHz。想要高频率PWM,优先选挂载在APB2上的定时器。

举个例子,我用的是STM32F103C8T6,它的APB2时钟最高72MHz。我一般会把TIM1(高级定时器)或TIM8挂在这里。如果只是做普通电机控制或LED调光,APB1上的TIM2、TIM3也完全够用。

这里有个坑,我曾经遇到过:

我曾经在项目里,把定时器的预分频器算错了,导致PWM频率只有预期的十分之一。查了半天,最后发现是APB1的时钟树配置里,分频系数设成了2,而我没注意到。所以,配置完时钟树后,一定要看一眼APB1/APB2的时钟频率,确认它是不是你想要的。

配置步骤很简单:

  1. 在Clock Configuration里,选择HSE或HSI作为系统时钟源。
  2. 设置PLL倍频系数,让系统时钟达到目标频率(比如72MHz)。
  3. 确认APB1和APB2的预分频系数,确保定时器时钟源正确。

嗯,这里要注意:如果你用的是STM32G0或G4系列,时钟树会更灵活,但原理是一样的——定时器的时钟源,决定了PWM的精度上限。

2.2 定时器配置——选对模式,算对参数

时钟树搞定后,咱们进入Pinout & Configuration标签页,找到你要用的定时器。比如我要用TIM2的通道1输出PWM,那就点开TIM2,在Mode里选择PWM Generation CH1。

这里有几个关键参数需要配置:

参数 说明 我的建议
Prescaler (PSC) 预分频器,用于降低定时器时钟频率 根据目标频率计算,一般设为0~65535
Counter Mode 计数模式:向上、向下、中心对齐 普通PWM用Up(向上计数)
Counter Period (ARR) 自动重装载值,决定PWM周期 与PSC配合,算出目标频率
Auto-reload Preload 自动重装载预装载,建议Enable 防止更新事件时出现毛刺
Pulse 占空比对应的计数值 初始设为ARR的一半,即50%占空比

参数计算其实就一个公式:

PWM频率 = 定时器时钟 / ( (PSC + 1) × (ARR + 1) )

举个例子:定时器时钟72MHz,想要输出1kHz的PWM,可以设PSC=71,ARR=999。这样算下来:72,000,000 / (72 × 1000) = 1000Hz,刚好1kHz。

我一般会先确定目标频率,然后反推PSC和ARR。比如做呼吸灯,频率50Hz就够了,PSC和ARR可以设大一些,让占空比调节更细腻。但如果是电机控制,频率可能需要10kHz以上,那PSC就得设小一点。

小技巧:如果你想要占空比调节精度高,那就把ARR设大一些。比如ARR=9999,那占空比就可以从0到9999精细调节。但要注意,ARR越大,PWM频率就越低,得在精度和频率之间找个平衡。

2.3 PWM通道引脚分配——别接错线

配置完定时器,接下来就是引脚分配。CubeMX会根据你选的定时器和通道,自动推荐可用的引脚。比如TIM2的通道1,默认可能是PA0,但如果你把PA0用作了其他功能,它就会自动切换到PA5或PA15。

我个人习惯,在Pinout View里,手动确认一下PWM输出引脚是不是我想要的。有时候CubeMX会自动分配一个不常用的引脚,导致你画PCB时还得改布局。

这里有个避坑指南:

我曾经在一个项目里,把TIM2的PWM输出分配到了PB3,结果发现PB3是JTDO引脚,调试器一连接就冲突。后来只能飞线解决。所以,分配引脚时,一定要避开调试接口(SWD/JTAG)和系统功能引脚(如BOOT0、NRST)。

另外,如果你用的是高级定时器(TIM1、TIM8),它们还有互补输出和刹车功能。这些功能在电机控制里很有用,但如果你只是做普通PWM,记得把Complementary Output和Break Input都关掉,不然配置会变得很复杂。

2.4 参数计算实战——手算一遍,心里有底

好,咱们来手算一个实际案例。假设我要用STM32F103,APB2时钟72MHz,TIM1输出一个20kHz的PWM,占空比可调范围0~100%。

  1. 确定目标频率:20kHz,周期50μs。
  2. 选择PSC:为了精度,我设PSC=0,这样定时器时钟就是72MHz。
  3. 计算ARR:ARR = (72,000,000 / 20,000) - 1 = 3600 - 1 = 3599。
  4. 占空比调节:Pulse值从0到3599,对应0%到100%占空比。

这样算下来,占空比调节精度是1/3600 ≈ 0.028%,相当细腻了。

注意:如果PSC=0,定时器时钟就是72MHz,那定时器的计数频率很高,功耗也会大一些。如果对功耗有要求,可以适当增大PSC,比如PSC=71,那定时器时钟就变成1MHz,ARR=49,频率还是20kHz,但精度就降到1/50=2%了。

嗯,这里要提醒一下:CubeMX里配置完参数后,可以在Parameter Settings里直接看到计算出的频率和占空比。但我还是建议你手算一遍,确认CubeMX算得对不对。我遇到过CubeMX版本bug,算出来的频率和实际不符的情况。

2.5 知识体系图:PWM配置核心流程

下面这张图,把整个PWM配置的流程串起来了。你可以对照着看,每一步都别漏掉。

PWM配置核心流程图 PWM配置核心流程 时钟树设置 定时器模式选择(PWM Generation) 参数计算(PSC/ARR/Pulse) 引脚分配(避免冲突) 生成代码并验证 提示:每一步配置完成后,建议在CubeMX的“Parameter Settings”里确认参数是否正确

2.6 常见配置错误与排查

配置过程中,我总结了几种最常见的错误,你遇到了可以对照着查:

错误现象 可能原因 解决方法
PWM无输出 引脚未使能、定时器未使能、GPIO模式错误 检查GPIO配置为AF_PP,确认定时器时钟已使能
PWM频率不对 PSC或ARR计算错误、时钟树配置错误 手算一遍频率,确认APB时钟频率
占空比无法调节 Pulse值超出ARR范围、CCR寄存器未更新 确保Pulse ≤ ARR,检查是否调用了__HAL_TIM_SET_COMPARE
PWM输出有毛刺 Auto-reload Preload未使能、中断优先级冲突 使能预装载,检查中断优先级设置

我的经验:如果PWM没输出,先用示波器或逻辑分析仪抓一下引脚波形。如果没有仪器,可以用万用表测引脚电压——如果占空比设成50%,引脚电压应该是VCC的一半左右。这个方法虽然粗糙,但能快速判断PWM是否在工作。