你是不是也遇到过:同样的 TIM+DMA PWM 代码,TIM3 正常,TIM2 波形就乱了?从 F1 移植到 F4,明明配置一模一样,就是出问题?
ST 官方 LAT1259 这篇笔记直接点破真相:TIM2 是 32 位定时器,DMA 位宽不匹配会直接导致 CCR 值异常。这篇文章用最接地气的工程视角,把问题、原因、解决方法一次性讲透,以后遇到 32 位 TIM 用 DMA 再也不踩坑。
资料获取:【应用笔记】LAT1259 STM32使用DMA产生PWM时波形异常分析
1. 典型故障现象(一模一样就是同款问题)
- STM32F4 系列,TIM2 + DMA 输出 PWM 波形异常
- TIM3 + DMA 完全正常
- 代码从 F1 移植过来,F1 没问题,F4 就异常
- PWM 占空比错乱、波形失真、CCR 值超出 ARR
- 检查配置:时钟、通道、DMA、PWM 模式全一样
2. 根因:TIM2 是 32 位计数器,DMA 位宽不配
LAT1259 给出最核心结论:
- TIM2 / TIM5 是 32 位定时器
- TIM1 / TIM3 / TIM4 等是 16 位定时器
客户的错误:
给32 位 TIM2配置了 DMA HalfWord(16 位) 传输。
而 STM32 的 AHB 总线规则:
32 位外设不支持 byte/halfword 写操作,总线会强制扩展成 32 位,导致数据错乱。
结果就是:
CCR 寄存器高 16 位 = 低 16 位,值直接翻倍甚至乱跳,PWM 直接畸形。
3. 为什么 TIM3 就没问题?
因为 TIM3 是 16 位定时器,DMA 配置 HalfWord(16 位)刚好匹配,所以正常。
F1 为什么没问题?
因为 F1 根本没有 32 位定时器,所以不会触发这个问题。
4. 10 秒解决方法(一步到位)
4.1 DMA 配置必须改
TIM2(32 位)DMA 设置:
- 外设位宽:Word(32bit)
- 内存位宽:Word(32bit)
4.2 存放 CCR 的数组必须是 32 位
// 正确:32位数组
uint32_t ccr_value_32[] = {10,20,30,40,50,60,70,80,90};
// 错误:16位数组会导致数据异常
uint16_t ccr_value_16[] = {10,20,30,...};
4.3 启动 DMA 函数保持不变
HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_1, ccr_value_32, 9);
改完这两处,TIM2 PWM 立刻恢复正常。
5. 工程师一句话总结(记这个就够)
- 16 位定时器 ←→ DMA HalfWord(16 位)
- 32 位定时器(TIM2/TIM5) ←→ DMA Word(32 位)
位宽必须匹配,否则波形必乱!
6. LAT1259 最终结论
- TIM2、TIM5 是32 位计数器,DMA 必须用Word(32bit)
- 16 位定时器用HalfWord(16bit)
- AHB 总线不支持 32 位外设的窄位宽写入,会导致数据异常
- F1 无 32 位 TIM,所以不会出现该问题
- 数组类型必须与位宽一致:32 位 TIM → uint32_t 数组
174