使用STM32 HAL库配置多路独立PWM,必须分用不同定时器(如TIM2/TIM3/TIM8)以实现异频输出;同一定时器的多通道共用ARR,频率锁定,仅占空比可独立调节;动态调占空比应通过__HAL_TIM_SET_COMPARE()实时更新CCR值,严禁重启定时器。

用 STM32 HAL 库配置多个 TIM 输出独立 PWM,别碰寄存器裸写
直接上结论:C++ 本身不提供硬件定时器抽象,必须依赖 MCU 厂商 SDK(如 STM32 的 HAL 或 LL 库),且多路 PWM 要求各通道使用不同 TIM 外设或同一 TIM 的多个互补/独立通道。HAL 库最稳妥,避免手动配 CCMR1、CCR2 这类寄存器出错。
常见错误是试图用一个 TIM 的 4 个通道输出完全异步的占空比——实际它们共用同一个 ARR(自动重装载值),频率被锁死;若需不同频率,必须分用多个 TIM(如 TIM1、TIM3、TIM8)。
- 无刷电机通常需 3 路相位差 120° 的 PWM(如三相逆变),用 1 个高级定时器(
TIM1或TIM8)+ 死区控制更合适 - 若要 3 路完全独立频率+占空比(比如调试不同电机参数),必须选 3 个通用定时器(
TIM2/TIM3/TIM4等) - HAL 初始化后,每个通道的占空比靠单独调用
__HAL_TIM_SET_COMPARE()或HAL_TIM_PWM_Start()后改htim.Instance->CCR1等寄存器实现
HAL_TIM_PWM_Start() 启动后怎么实时改占空比
启动 PWM 只是使能输出,占空比由比较寄存器(CCRx)决定。改占空比 ≠ 重启定时器,否则会抖动甚至停波。
正确做法是在运行中动态写入对应通道的比较寄存器,例如:
立即学习“C++免费学习笔记(深入)”;
// 假设 htim3 对应 TIM3_CH1,ARR=999(1kHz),想设 30% 占空比 __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 299); // 999 * 0.3 ≈ 299 // 注意:不是 HAL_TIM_PWM_SetCompare() —— 这个函数在 HAL 1.12.0+ 才有,旧版只能直接操作寄存器
- 务必确认
ARR已设为合适的值(比如 999 对应 1000 分辨率),否则CCR超出范围会导致输出异常(常表现为恒高或恒低) - 若用 HAL 库的
HAL_TIMEx_PWMN_Start()(带互补通道),必须同时更新主通道和互补通道的CCR,否则死区逻辑失效 - 在中断或 DMA 回调里改
CCR是安全的;但在主循环里高频修改时,注意加临界区(HAL_NVIC_DisableIRQ()/EnableIRQ())防抢占
用 C++ 封装多路 PWM 控制器时,别把定时器句柄当普通对象传
C++ 类可以封装,但 TIM_HandleTypeDef 是 HAL 内部管理的句柄,不能拷贝、不能跨线程共享、不能在构造函数里初始化(HAL 初始化必须在 MX_TIMx_Init() 之后)。
典型错误写法:PWMController pwm1(htim1), pwm2(htim2); —— 若 htim1 还没初始化就传入,后续所有 HAL_TIM_* 调用都会返回 HAL_ERROR。
- 推荐做法:类内只存指针(
TIM_HandleTypeDef* m_htim),构造时不初始化,用init(TIM_HandleTypeDef* htim)显式绑定 - 占空比设置接口应接受 0.0~1.0 浮点数,内部转成整型
CCR值,避免用户算错溢出 - 如果要用 std::vector 存多路控制器,确保 vector 元素是对象而非指针——否则析构时容易 double-free
htim结构体
无刷电机实际运行时,PWM 频率和死区时间必须匹配 MOSFET 开关特性
不是“占空比能调就行”。比如 IR2104 驱动芯片典型死区为 500ns,若 PWM 频率设到 100kHz(周期 10μs),则死区占 5% 时间,再扣掉导通损耗,有效调制范围大幅缩水。
- 常见搭配:FOC 控制常用 16–20kHz;方波换相常用 8–16kHz;低于 5kHz 人耳可闻啸叫,高于 30kHz 开关损耗剧增
- HAL 中启用死区需调用
HAL_TIMEx_ConfigCommutEvent()(高级定时器)或手动配 BDTR 寄存器(通用定时器不支持硬件死区) - 示波器实测发现某路 PWM 边沿模糊?大概率是 GPIO 输出速度没设为
GPIO_SPEED_FREQ_VERY_HIGH,或 PCB 走线过长未加阻尼电阻
真正麻烦的是三相中心对齐模式下,如何让 U/V/W 三路占空比严格满足 120° 相移且不因中断延迟失步——这已经超出纯软件范畴,得看定时器是否支持重复计数模式(RCR)和事件联动(TRGO)。细节太多,先跑通基本波形再说。


















