STM32 上精确 PWM 相位控制:无损硬件方法
STM32 微控制器缺少直接调整硬件 PWM 信号相位的寄存器。此问题在需要严格时序偏移的多通道同步任务中至关重要。我们将展示如何实现精确相位控制,同时对性能影响最小,且无需软件仿真。
为什么需要调整 PWM 相位?
STM32 上的硬件 PWM 可以轻松设置频率和占空比,但标准库并不提供直接相位偏移的方法。此限制在以下场景中变得关键:
- 使用两个带有固定偏移的 PWM 信号模拟正交编码器
- 为正交混频器生成 sin/cos 对(90° 偏移)
- 控制三相 BLDC 电机(通道间 120° 偏移)
- 同步内燃机中的汽油喷射器或点火线圈
- 在 SDR 接收机中生成 LO 信号
- 通过在电源电路中人为错开相位来降低 EMI
没有硬件同步的情况下,信号相位由随机因素决定:定时器初始化时间、代码执行速度、总线频率。这使得可预测的同步变得不可能。
理论基础:主从架构
核心思路是使用一个定时器(主定时器)作为另一个定时器(从定时器)的参考同步源。通过主定时器的比较器值来调整从定时器的相位。当此值达到时,从定时器的计数器将被复位,从而产生所需的时序偏移。

重要的是,相位以相对单位度量:
- 0° — 同相信号
- 180° — 反相
- 360° — 完整周期(等同于 0°)
偏移精度由定时器分辨率决定。对于 1 ms 周期和 84 MHz 总线时钟,误差可低至 11.9 ns(1/84e6)。
实际实现方法
方法 0:极性反转(180° 偏移)
最简单的方法是切换 TIMx_CCER 寄存器中的 CCxP 位。这是一个原子操作,无需额外资源。缺点是仅有两个固定状态(0° 和 180°)。适用于 BPSK 调制,但无法满足平滑调整的需求。
方法 1:软件计数器调整
朴素方法是直接写入从定时器的 CNT 寄存器:
bool pwm_phase_set_counter_adjust(uint8_t num, int32_t phase_us) {
bool res = false;
PwmHandle_t *Node = PwmGetNode(num);
if(Node) {
int32_t compare_value = TimerPhaseUsToCompareValue(Node->PhaseComparator.timer, phase_us);
int32_t counter_base = (int32_t) timer_counter_get(Node->PhaseComparator.timer);
int32_t value = counter_base + compare_value;
res = timer_counter_set(Node->TimChan.timer, (uint32_t) value);
}
return res;
}
此方法在 1 kHz 时误差高达 3 µs(0.29%),原因是代码执行时间。主要缺点:
- 写入期间需要停止定时器
- 校正时刻破坏信号完整性
- 增加 CPU 的中断负担
方法 2:通过主从硬件同步
最佳方案利用内置定时器同步机制。设置包括:
- 将主定时器(TIM8)配置为在 OC1 比较器匹配时触发生成模式(TIM_TRGO_OC1)
- 将从定时器(TIM4)设置为在内部触发(TIM_TS_ITR3)上复位
- 设置从模式为复位(TIM_SLAVEMODE_RESET)
HAL 配置如下:
const TimerConfig_t TimerConfig[] = {
{
.num = TIMER_NUM_LO_BASE,
.role = TIMER_ROLE_MASTER,
.master_out_trigger = TIMER_MASTER_OUT_TRG_OC1,
},
{
.num = TIMER_NUM_LO,
.role = TIMER_ROLE_SLAVE,
.slave_input_trigger = TIMER_SLAVE_IN_TRIG_INTERNAL_TRIGGER_3,
.slave_mode = TIMER_SLAVE_MODE_RESET,
},
};
方法优势:
- 完全硬件实现,无需中断
- 偏移精度达总线时钟周期(84 MHz 时为 11.9 ns)
- 动态调整期间输出信号无毛刺
- CPU 负载最小(仅写入主定时器比较器寄存器)
限制:
- 需要支持主从连接的定时器对
- 每个主定时器最多 4 个从定时器(受比较器数量限制)
- 某些定时器(6、7、10、11、13、14)不支持从模式
使用逻辑分析仪诊断相位
正确设置的验证使用示波器或逻辑分析仪进行。测试步骤:
- 将主定时器(TIM8_CH1)设置为 1 kHz、50% 占空比
- 将从定时器(TIM4_CH2)设置为 90° 相位偏移
- 将探头连接到对应引脚
预期结果:
- 零偏移时,主信号上升沿与从周期起始对齐
- 对于 1 ms 周期的 90° 偏移,从信号偏移 250 µs

关键点:误差以总线时钟周期度量。对于 STM32F407 的 84 MHz 总线,最小步进为 11.9 ns。在 1 kHz 实际应用中,精度达 0.012%。
关键要点
- 方法选择取决于精度要求:0.01% 误差使用硬件同步;0.3% 误差可接受软件调整
- 检查定时器兼容性:并非所有对都支持主从连接(参见 RM0090 中的表格)
- 避免停止定时器:硬件方法在相位变化期间不中断信号生成
- 考虑从设备限制:一个主定时器最多连接 4 个从定时器
- 使用示波器诊断相位:关键系统必须进行视觉验证
— Editorial Team
暂无评论。