You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用DMAMUX生成事件触发另一DMA请求?STM32L4配置排查

STM32L4 DMAMUX配置排查:UART DMA触发定时器CNT传输失效

需求说明

通过DMA向LPUART发送数据,每完成3次传输后,无需CPU参与,自动触发另一DMA请求,将TIM15的CNT寄存器数据传输至内存。

问题描述

LPUART的DMA数据传输正常,但DMAMUX通道1未接收到触发事件,无法启动定时器CNT到内存的DMA传输。

代码示例(原配置)

DMA1_Channel2 -> CNDTR = 10;
DMA1_Channel2 -> CPAR = (uint32_t)&TIM15 -> CNT;
DMA1_Channel2 -> CMAR = (uint32_t)data16;

DMA1_Channel1 -> CNDTR = 6;
DMA1_Channel1 -> CMAR = (uint32_t)data;
DMA1_Channel1 -> CPAR = (uint32_t)&LPUART1 -> TDR;

DMAMUX1_Channel0 -> CCR = DMA_REQUEST_LPUART1_TX | DMAMUX_CxCR_EGE | (2 << DMAMUX_CxCR_NBREQ_Pos);

DMAMUX1_Channel1 -> CCR = DMA_REQUEST_GENERATOR0;

DMAMUX1_RequestGenerator0 -> RGCR = DMAMUX_RGxCR_GPOL_Msk  | (0 << DMAMUX_RGxCR_GNBREQ_Pos);
DMAMUX1_RequestGenerator0 -> RGCR |= DMAMUX_RGxCR_GE;

DMA1_Channel1 -> CCR |= DMA_CCR_EN;
DMA1_Channel2 -> CCR |= DMA_CCR_EN;
LPUART1 -> CR3 |= USART_CR3_DMAT;

方案可行性确认

该方案完全可行。STM32L4的DMAMUX支持通道事件触发请求发生器的功能:当UART的DMA通道完成指定次数传输后,DMAMUX通道生成事件,触发请求发生器输出DMA请求,进而启动定时器CNT到内存的DMA传输,全程无需CPU介入,符合需求。

配置错误排查与修正

1. 请求发生器未关联通道0的触发事件

原代码中,DMAMUX通道0已开启事件生成(DMAMUX_CxCR_EGE),但未配置请求发生器0的触发源为通道0的事件。需在DMAMUX1_RequestGenerator0->RGCR中添加GSEL字段配置,指定触发源为DMAMUX通道0的事件(GSEL=0x0对应通道0事件)。

2. DMA通道2传输方向错误

定时器CNT到内存的传输属于外设到内存,但DMA通道2的DIR位默认是0(内存到外设),需手动置位DMA_CCR_DIR修正方向。

3. 缺失必要的DMA地址递增与数据宽度配置

若需要连续存储TIM15_CNT数据到内存,需开启DMA通道2的内存地址递增(DMA_CCR_MINC);同时TIM_CNT为16位寄存器,需匹配DMA的外设/内存数据宽度。UART_TX的DMA通道1也需开启内存地址递增,确保每次传输下一个字节。

修正后的代码

// 配置DMA通道2:TIM15_CNT -> 内存(外设到内存)
DMA1_Channel2->CNDTR = 10;
DMA1_Channel2->CPAR = (uint32_t)&TIM15->CNT;
DMA1_Channel2->CMAR = (uint32_t)data16;
DMA1_Channel2->CCR |= DMA_CCR_DIR;       // 设置外设到内存方向
DMA1_Channel2->CCR |= DMA_CCR_MINC;      // 内存地址递增(连续存储时启用)
DMA1_Channel2->CCR |= DMA_CCR_PSIZE_0;   // 外设数据宽度16位(匹配TIM_CNT)
DMA1_Channel2->CCR |= DMA_CCR_MSIZE_0;   // 内存数据宽度16位

// 配置DMA通道1:内存 -> LPUART1_TDR(内存到外设)
DMA1_Channel1->CNDTR = 6;
DMA1_Channel1->CMAR = (uint32_t)data;
DMA1_Channel1->CPAR = (uint32_t)&LPUART1->TDR;
DMA1_Channel1->CCR |= DMA_CCR_DIR;       // 设置内存到外设方向
DMA1_Channel1->CCR |= DMA_CCR_MINC;      // 内存地址递增

// 配置DMAMUX通道0:LPUART1_TX请求,完成3次传输后生成事件
DMAMUX1_Channel0->CCR = DMA_REQUEST_LPUART1_TX 
                        | DMAMUX_CxCR_EGE 
                        | (2 << DMAMUX_CxCR_NBREQ_Pos); // NBREQ=2 → 3次请求后生成事件

// 配置DMAMUX请求发生器0:触发源为通道0事件,每次触发生成1次DMA请求
DMAMUX1_RequestGenerator0->RGCR = (0x0 << DMAMUX_RGxCR_GSEL_Pos) // 选择通道0事件为触发源
                                 | DMAMUX_RGxCR_GPOL_Msk        // 事件极性(根据需求调整)
                                 | (0 << DMAMUX_RGxCR_GNBREQ_Pos) // 每次触发生成1次请求
                                 | DMAMUX_RGxCR_GE;              // 使能请求发生器

// 配置DMAMUX通道1:请求源为请求发生器0
DMAMUX1_Channel1->CCR = DMA_REQUEST_GENERATOR0;

// 使能DMA通道与UART DMA功能
DMA1_Channel1->CCR |= DMA_CCR_EN;
DMA1_Channel2->CCR |= DMA_CCR_EN;
LPUART1->CR3 |= USART_CR3_DMAT;

参考手册核心要点(RM0432第396页起)

DMAMUX(DMA多路复用器)负责将外设/软件请求路由到DMA通道,同时提供请求发生器模块,支持通过内部/外部事件触发生成DMA请求:

  • 通道事件生成:当通道的EGE位置1时,每完成NBREQ+1次DMA请求后,通道会生成一个事件信号。
  • 请求发生器配置:通过RGCR寄存器选择触发源(如DMAMUX通道事件)、设置触发极性(GPOL)、指定单次触发生成的请求次数(GNBREQ+1),并通过GE位使能。
  • DMA通道请求源:DMAMUX通道的CCR寄存器通过DMA_REQUEST_x字段选择请求源,可指定外设请求或请求发生器输出。

内容的提问来源于stack exchange,提问作者gulpr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 14:47:07