Rust Embassy SimplePwm波形函数工作异常:高频占空比异常问题
高频PWM占空比异常的原因排查与解决方法
核心原因分析
1. 定时器时钟与PWM频率的非整数分频导致量化误差
根据你的时钟配置计算:
- HSE 25MHz → 经PLL预分频DIV12后得到约2.083MHz → PLL倍频96得到200MHz → 经DIV2后系统时钟为100MHz
- APB1预分频DIV2,因此APB1总线时钟为50MHz;由于APB1预分频系数>1,STM32F1的TIM3定时器时钟为APB1时钟×2,即100MHz
- 当配置6MHz PWM时,定时器自动重装载值(ARR)计算为:
TIM_CLK / PWM_FREQ = 100e6 / 6e6 ≈ 16.666,但ARR必须为整数,实际只能取16或17,这会导致:- 实际PWM频率与目标存在偏差
- 占空比计算时,
max_duty / 3这类非整数运算会进一步放大量化误差,在高频下(周期仅约166ns),这种误差会直接体现在波形上
2. 非整数占空比的取整误差
你的波形数组中max_duty / 3 * 2、max_duty / 3的计算依赖整数除法,当max_duty不是3的整数倍时,会自动舍去小数部分,导致实际输出的高/低电平宽度与理论值不符,高频下这种偏差的视觉效果会更明显
解决方法
1. 调整时钟配置,使定时器时钟为PWM频率的整数倍
重新配置PLL与总线预分频,让TIM3时钟是6MHz的整数倍,确保ARR为整数,同时让max_duty是3的倍数,消除占空比计算的取整误差。推荐配置示例:
{ use embassy_stm32::rcc::*; use embassy_stm32::time::*; device_config.enable_debug_during_sleep = true; device_config.rcc.hse = Some(Hse { freq: mhz(25), mode: HseMode::Oscillator, }); device_config.rcc.hsi = true; device_config.rcc.pll_src = PllSource::HSE; device_config.rcc.pll = Some(Pll { prediv: PllPreDiv::DIV25, // 25MHz → 1MHz mul: PllMul::MUL24, // 1MHz ×24 →24MHz divp: None, divq: None, divr: None, }); device_config.rcc.sys = Sysclk::PLL1; // 系统时钟24MHz device_config.rcc.ahb_pre = AHBPrescaler::DIV1; device_config.rcc.apb1_pre = APBPrescaler::DIV2; // APB1时钟12MHz → TIM3时钟=12MHz×2=24MHz device_config.rcc.apb2_pre = APBPrescaler::DIV1; }
此时TIM3时钟为24MHz,配置6MHz PWM时:
- ARR = (24e6 / 6e6) -1 =3 →
max_duty=3 - 波形数组计算:
3/3*2=2、3/3=1,均为整数,占空比完全符合理论值
2. 优化占空比计算逻辑
若无法调整时钟,需确保max_duty为3的整数倍,可通过修改PWM频率实现:例如将6MHz调整为6.25MHz(100e6/16=6.25e6),此时max_duty=15(ARR=15),15/3*2=10、15/3=5,占空比计算无误差
3. 确认定时器与DMA的同步机制
检查waveform_up方法的DMA触发时机,确保DMA在定时器更新事件时传输比较寄存器值,避免高频下的时序错位。embassy-stm32的SimplePwm组件已默认处理该逻辑,但可尝试提升DMA通道的优先级:
// 在初始化DMA时设置更高优先级(如VeryHigh) dp.DMA1_CH2.set_priority(DmaPriority::VeryHigh);
内容的提问来源于stack exchange,提问作者Raul Alimbekov
相关产品推荐
相关产品推荐

