在电机控制、电源调节、模拟信号生成等嵌入式场景中,经常需要 MCU 输出多频率、指定脉冲数的交替 PWM 波形。传统通过 CPU 实时修改 TIM 寄存器的方式,不仅占用核心资源,还容易出现时序抖动;而 STM32U5 系列的TIM DMA Burst配合GPDMA 链表 / 2D 寻址功能,可在无 CPU 干预下,硬件自动批量更新 TIM 寄存器,精准输出变频、定脉冲数的 PWM,稳定性与效率大幅提升。
本文基于 ST 官方 LAT1202 应用笔记,以 STM32U575 为平台,从零讲解两种适配方案 ——带 RCR 高级定时器方案、无 RCR 通用定时器方案,覆盖配置、代码、调试全流程,直接落地项目使用。
资料获取:【应用笔记】LAT1202 TIM DMA burst 输出变频 PWM 波形
1. 核心需求与技术方案
1.1 典型需求
输出两组参数不同的 PWM 交替运行:
- PWM1:频率对应 ARR=1000,脉冲数 = 2,占空比对应 CCR1=500
- PWM2:频率对应 ARR=5000,脉冲数 = 1,占空比对应 CCR1=2500要求硬件自动切换,全程不占用 CPU。
1.2 核心技术原理
(1)TIM DMA Burst 批量更新
STM32 部分定时器支持DMA Burst功能:单个更新事件(UEV)触发一次 DMA 批量传输,同时改写 ARR、RCR、CCR1 等多个寄存器,完美匹配变频 + 变占空比 + 定脉冲数需求。关键寄存器:
- TIMx_DCR:配置 DMA burst 传输长度、触发事件、目标寄存器基索引
- TIMx_DMAR:DMA 访问的目标端口,批量数据通过该寄存器写入 TIM 寄存器组
(2)GPDMA 链表 + 2D 寻址
STM32U5 的 GPDMA 12~15 通道支持:
- Linked List:多节点循环执行,对应多组 PWM 参数自动切换
- 2D Addressing+Repeat:无 RCR 定时器也能实现指定脉冲数输出
- 循环模式:两组 PWM 参数无限交替运行
(3)RCR 重复计数寄存器
高级定时器(TIM1/8/15/16/17)独有,用于直接设定 PWM 输出脉冲个数,计数完成后触发下一次 DMA 更新。
2. 方案一:带 RCR 高级定时器(TIM1)实现
适用于 TIM1/TIM8/TIM15~17,依托 RCR 直接控脉冲数,配置最简单。
2.1 CubeMX 图形化配置
(1)TIM1 基础配置
- 时钟源:内部时钟,通道 1 设为 PWM 生成模式
- 开启寄存器预装载,保证参数更新同步
- 主频 100MHz,通过 ARR 控制 PWM 周期,CCR1 控制占空比
(2)GPDMA 通道 12 链表配置
- 通道:GPDMA1 Channel12(支持链表 + 2D)
- 模式:Linked List + Circular 循环
- 创建队列 TQ1,添加两个节点 TN1(PWM1)、TN2(PWM2)
- 触发源:TIM1 Update 事件
- 传输方向:内存→外设,目的地址 & TIM1->DMAR
- 节点 TN1:源地址 pulse1,长度 3(ARR/RCR/CCR1)
- 节点 TN2:源地址 pulse2,长度 3
2.2 关键代码实现
// 两组PWM参数:{ARR, RCR, CCR1}
uint32_t pulse1[3] = {1000, 2, 500};
uint32_t pulse2[3] = {5000, 1, 2500};
// 链表初始化并绑定通道
MX_TQ1_Config();
if(HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel12, &TQ1) != HAL_OK) {
Error_Handler();
}
// 启动DMA链表
HAL_DMAEx_List_Start_IT(&handle_GPDMA1_Channel12);
// TIM与DMA关联
__HAL_LINKDMA(&htim1, hdma[TIM_DMA_ID_CC1], handle_GPDMA1_Channel12);
__HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_UPDATE);
// 配置TIM1 DMA Burst:3次传输,基地址指向ARR
htim1.Instance->DCR = (1<<16) | ((3-1)<<8) | (11<<0);
// 启动PWM输出
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
2.3 波形效果
TIM1 先输出 2 个 PWM1 脉冲,再输出 1 个 PWM2 脉冲,循环交替,频率、脉冲数完全符合配置,无 CPU 干预、无抖动。
3. 方案二:无 RCR 通用定时器(TIM2)实现
通用定时器(TIM2/3/4/5)无 RCR,借助GPDMA 2D 寻址 + Repeat 计数器实现指定脉冲数。
3.1 核心改动
- 取消 RCR 参数,pulse 数组第二位填 0
- GPDMA 通道开启2D Addressing
- 配置 Repeat Counter:TN1=3、TN2=1,替代 RCR 控脉冲数
- Block 源地址偏移设为 - 12,实现单组参数重复传输
3.2 参数与代码修改
// 无RCR,第二位填0
uint32_t pulse1[3] = {1000, 0, 500};
uint32_t pulse2[3] = {5000, 0, 2500};
// 关联TIM2与DMA,其余链表启动代码同方案一
__HAL_LINKDMA(&htim2, hdma[TIM_DMA_ID_CC1], handle_GPDMA1_Channel12);
__HAL_TIM_ENABLE_DMA(&htim2, TIM_DMA_UPDATE);
// DCR配置与TIM1一致:3次传输,基地址ARR
htim2.Instance->DCR = (1<<16) | ((3-1)<<8) | (11<<0);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
3.3 实现效果
与方案一完全一致,依靠 GPDMA 硬件重复功能,完美替代 RCR,通用性更强。
4. 关键寄存器与参数说明
4.1 TIMx_DCR 寄存器详解
htimx.Instance->DCR = (DBSS <<16) | (DBL <<8) | (DBA <<0)
- DBSS[16]:DMA burst 触发事件,1 = 更新事件触发
- DBL[8:10]:传输次数 - 1,本例 3 次传输→填 2
- DBA[0:4]:TIM 寄存器基地址索引,ARR 索引为 11
4.2 GPDMA 关键配置
- 内存地址自增、外设地址固定
- 数据宽度:Word(32 位),匹配 TIM 寄存器位宽
- 循环链表:两组节点自动切换,持续输出
5. 开发避坑要点
- 必须开启 TIM 预装载:否则寄存器更新不同步,PWM 波形异常
- DMA 通道选型:只有 GPDMA 12~15 支持链表与 2D 功能
- 数据长度匹配:DMA 传输长度必须与 pulse 数组长度一致
- 2D 偏移正确:无 RCR 方案中,Block 源地址偏移设为 - 12,保证参数重复写入
- 时钟稳定:TIM 时钟需配置准确,避免 PWM 频率偏差
STM32U5 的TIM DMA Burst + GPDMA 链表 / 2D 寻址,是实现硬件自动变频 PWM的最优方案:
- 全硬件执行:CPU 零占用,专注核心业务
- 适配全系列 TIM:高级 TIM 用 RCR、通用 TIM 用 GPDMA Repeat
- 配置灵活:可扩展 3 组及以上 PWM 参数,满足复杂波形需求
- 时序精准:批量更新 + 硬件触发,无软件延时与抖动
110