5.6 DMA 使用说明

本章说明 N32G41x 标准外设库中 DMA 驱动的文件组成与 12 个公开函数,内容包括通道的复位与初始化、外设与存储器地址及数据宽度配置、通道使能与中断使能、传输数量读写、标志与中断管理、以及请求重映射;并说明 FLASH_RAM 示例如何用存储器到存储器模式在 FLASH 与 RAM 之间搬运数据。DMA 请求映射表与各寄存器位定义请配合用户手册的“DMA 控制器”章节阅读,芯片已知问题以勘误手册为准。

5.6.1 相关文件

相对路径 作用
firmware/n32g41x_std_periph_driver/inc/n32g41x_dma.h 定义 DMA_InitType 结构体与传输方向、数据宽度、优先级、循环模式、存储器到存储器、请求重映射等宏,并按复位与初始化、通道使能、配置、读写、中断与标志管理、请求重映射六个区段声明 12 个公开函数
firmware/n32g41x_std_periph_driver/src/n32g41x_dma.c 实现上述 12 个函数:通道寄存器复位与配置,传输数量与外设、存储器地址读写,标志与中断状态的读取与清除,请求重映射
projects/n32g41x_EVAL/examples/DMA/ DMA 示例根目录,含 FLASH_RAM 1 个示例
projects/n32g41x_EVAL/examples/DMA/FLASH_RAM/ 该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt
projects/n32g41x_EVAL/bsp/ 示例引用的板级支持文件:串口日志初始化与打印接口、毫秒延时函数

5.6.2 API 参考

搜索 API共 12 个函数

以下 12 个公开函数按 n32g41x_dma.h 的声明顺序分为 6 组;每个条目给出功能摘要与 n32g41x_dma.c 中该函数正上方的注释原文。

复位与初始化

DMA_DeInit、DMA_Init、DMA_StructInit

通道使能

DMA_EnableChannel

配置

DMA_ConfigInt

读写

DMA_SetCurrDataCounter、DMA_GetCurrDataCounter

中断与标志管理

DMA_GetFlagStatus、DMA_ClearFlag、DMA_GetIntStatus、DMA_ClrIntPendingBit

请求重映射

DMA_RequestRemap

void DMA_DeInit(DMA_ChannelType *DMAChx)将 DMA 通道 x 的 CHCFG、TXNUM、PADDR、MADDR、INTCLR 寄存器复位为默认复位值。
源码注释
name    DMA_DeInit.
fun     Reset CHCFG, TXNUM, PADDR, MADDR, INTCLR registers of DMA Channel x
        to their default reset values.
param   DMAChx (The input parameters must be the following values):
          - DMA_CH1
          - DMA_CH2
          - DMA_CH3
          - DMA_CH4
          - DMA_CH5
          - DMA_CH6
          - DMA_CH7
return  none

使用提示: 实现先清除 DMA_CHCFGx 的通道使能位,再把 CHCFG、TXNUM、PADDR、MADDR 清零,并按 DMAChx 对应的通道向 DMA_INTCLR 写入该通道的中断掩码,清除全部中断标志。

void DMA_Init(DMA_ChannelType *DMAChx, const DMA_InitType *DMA_InitParam)用 DMA_InitType 类型的结构体参数 DMA_InitParam 初始化 DMA 通道 x,包括配置外设/存储器地址、传输方向、地址递增模式、数据位宽、优先级等。
源码注释
name    DMA_Init.
fun     Initializes the DMA Channel x by the structure parameter
        DMA_InitParam of type DMA_InitType. Includes configuration
        peripheral/memory address, transmission direction, address
        increment mode, data bit width, priority, etc.
param   DMAChx (The input parameters must be the following values):
          - DMA_CH1
          - DMA_CH2
          - DMA_CH3
          - DMA_CH4
          - DMA_CH5
          - DMA_CH6
          - DMA_CH7
param   DMA_InitParam (The input parameters must be the following values):
          - PeriphAddr
            -0x00000000~0xFFFFFFFF
          - MemAddr
            -0x00000000~0xFFFFFFFF
          - Direction
            - DMA_DIR_PERIPH_DST
            - DMA_DIR_PERIPH_SRC
          - BufSize
            -0x0000~0xFFFF
          - PeriphInc
            - DMA_PERIPH_INC_ENABLE
            - DMA_PERIPH_INC_DISABLE
          - DMA_MemoryInc
            - DMA_MEM_INC_ENABLE
            - DMA_MEM_INC_DISABLE
          - PeriphDataSize
            - DMA_PERIPH_DATA_SIZE_BYTE
            - DMA_PERIPH_DATA_SIZE_HALFWORD
            - DMA_PERIPH_DATA_SIZE_WORD
          - MemDataSize
            - DMA_MemoryDataSize_Byte
            - DMA_MemoryDataSize_HalfWord
            - DMA_MemoryDataSize_Word
          - CircularMode
            - DMA_MODE_CIRCULAR
            - DMA_MODE_NORMAL
          - Priority
            - DMA_PRIORITY_VERY_HIGH
            - DMA_PRIORITY_HIGH
            - DMA_PRIORITY_MEDIUM
            - DMA_PRIORITY_LOW
          - Mem2Mem
            - DMA_M2M_ENABLE
            - DMA_M2M_DISABLE
return  none

使用提示: 实现先读出 DMA_CHCFGx 并按 CCR_CLEAR_Mask(0xFFFF800F)清位,再写入配置位,随后写 DMA_TXNUMx、DMA_PADDRx、DMA_MADDRx;除被屏蔽的位外,通道使能位与中断使能位不受影响。

void DMA_StructInit(DMA_InitType *DMA_InitParam)初始化用于初始化 DMA 的 DMA_InitType 类型结构体参数,通常在初始化 DMA_InitType 参数之前调用。
源码注释
name    DMA_StructInit.
fun     Initializes the structure parameter of type DMA_InitType used to
        initialize DMA. This function is usually called before initializing
        a parameter of type DMA_InitType.
param   DMA_InitParam :
          - Pointer to the DMA_InitType structure which will be initialized.
return  none

使用提示: 实现把 PeriphAddr、MemAddr、BufSize 置 0,Direction 置为 DMA_DIR_PERIPH_SRC,地址递增、数据宽度与循环模式取关闭或最小配置,Priority 取 DMA_PRIORITY_LOW,Mem2Mem 取 DMA_M2M_DISABLE。

void DMA_EnableChannel(DMA_ChannelType *DMAChx, FunctionalState Cmd)使能 DMA 通道 x;该函数在 DMA 初始化成功后调用,以开始搬运数据。
源码注释
name    DMA_EnableChannel.
fun     DMA Channel x Channel enable. This function is called after DMA
        initialization is successful to start moving data.
param   DMAChx (The input parameters must be the following values):
          - DMA_CH1
          - DMA_CH2
          - DMA_CH3
          - DMA_CH4
          - DMA_CH5
          - DMA_CH6
          - DMA_CH7
param   Cmd (The input parameters must be the following values):
          - ENABLE
          - DISABLE
return  none
void DMA_ConfigInt(DMA_ChannelType *DMAChx, uint32_t DMAInt, FunctionalState Cmd)使能 DMA 通道 x 的中断;在使能通道之前使能传输完成中断、半传输中断或传输错误中断后,对应事件发生时会触发中断。
源码注释
name    DMA_ConfigInt.
fun     DMA Channel x interrupts enable. Before enabling a DMA channel,
        enabling transfer completion interrupt, half-transfer interrupt
        or transfer error interrupt will cause an interrupt when the
        corresponding event occurs.
param   DMAChx (The input parameters must be the following values):
          - DMA_CH1
          - DMA_CH2
          - DMA_CH3
          - DMA_CH4
          - DMA_CH5
          - DMA_CH6
          - DMA_CH7
param   DMAInt (The input parameters must be the following values):
          - DMA_INT_TXC
          - DMA_INT_HTX
          - DMA_INT_ERR
param   Cmd (The input parameters must be the following values):
          - ENABLE
          - DISABLE
return  none
void DMA_SetCurrDataCounter(DMA_ChannelType *DMAChx, uint16_t DataNumber)设置 DMA 通道 x 当前的数据传输次数。
源码注释
name    DMA_SetCurrDataCounter.
fun     Set the current number of data transfers for DMA Channel x.
param   DMAChx (The input parameters must be the following values):
          - DMA_CH1
          - DMA_CH2
          - DMA_CH3
          - DMA_CH4
          - DMA_CH5
          - DMA_CH6
          - DMA_CH7
param   DataNumber(The input parameters must be the following values) :
          - 0~0xFFFF
return  none
note    This function can only be used when the DMAChx is disabled.

使用提示: 实现直接把 DataNumber 写入 DMA_TXNUMx;源码注释说明该函数只能在通道禁用时调用。

uint16_t DMA_GetCurrDataCounter(const DMA_ChannelType *DMAChx)获取 DMA 通道 x 当前剩余的数据数量。
源码注释
name    DMA_GetCurrDataCounter.
fun     Get the current number of remaining data for DMA Channel x.
param   DMAChx (The input parameters must be the following values):
          - DMA_CH1
          - DMA_CH2
          - DMA_CH3
          - DMA_CH4
          - DMA_CH5
          - DMA_CH6
          - DMA_CH7
return  Returns the number of data units remaining to be transferred.
FlagStatus DMA_GetFlagStatus(uint32_t DMAFlag, const DMA_Module *DMAy)获取 DMA 通道 x 的标志状态,包含对应通道的全局标志、传输完成标志、半传输标志与传输错误标志。
源码注释
name    DMA_GetFlagStatus.
fun     Get DMA Channel x flag status. Contains the global flag, transfer
        completion flag, half-transfer flag, and transfer error flag for
        the corresponding channel.
param   DMAFlag (The input parameters must be the following values):
          - DMA_FLAG_GL1
          - DMA_FLAG_TC1
          - DMA_FLAG_HT1
          - DMA_FLAG_TE1
          - DMA_FLAG_GL2
          - DMA_FLAG_TC2
          - DMA_FLAG_HT2
          - DMA_FLAG_TE2
          - DMA_FLAG_GL3
          - DMA_FLAG_TC3
          - DMA_FLAG_HT3
          - DMA_FLAG_TE3
          - DMA_FLAG_GL4
          - DMA_FLAG_TC4
          - DMA_FLAG_HT4
          - DMA_FLAG_TE4
          - DMA_FLAG_GL5
          - DMA_FLAG_TC5
          - DMA_FLAG_HT5
          - DMA_FLAG_TE5
          - DMA_FLAG_GL6
          - DMA_FLAG_TC6
          - DMA_FLAG_HT6
          - DMA_FLAG_TE6
          - DMA_FLAG_GL7
          - DMA_FLAG_TC7
          - DMA_FLAG_HT7
          - DMA_FLAG_TE7
param   DMAy (The input parameters must be the following values):
          - DMA
return  SET or RESET.

使用提示: 实现读取 DMA_INTSTS 并与 DMAFlag 相与;DMA_FLAG_* 宏在头文件中定义为 DMA_INTCLR 的清除位,与 DMA_INTSTS 的状态位同一位序。

void DMA_ClearFlag(uint32_t DMAFlag, DMA_Module *DMAy)清除 DMA 通道 x 的标志状态,包含对应通道的全局标志、传输完成标志、半传输标志与传输错误标志。
源码注释
name    DMA_ClearFlag.
fun     Clear DMA Channel x flag status. Contains the global flag, transfer
        completion flag, half-transfer flag, and transfer error flag for the
        corresponding channel.
param   DMAFlag (The input parameters must be the following values):
          - DMA_FLAG_GL1
          - DMA_FLAG_TC1
          - DMA_FLAG_HT1
          - DMA_FLAG_TE1
          - DMA_FLAG_GL2
          - DMA_FLAG_TC2
          - DMA_FLAG_HT2
          - DMA_FLAG_TE2
          - DMA_FLAG_GL3
          - DMA_FLAG_TC3
          - DMA_FLAG_HT3
          - DMA_FLAG_TE3
          - DMA_FLAG_GL4
          - DMA_FLAG_TC4
          - DMA_FLAG_HT4
          - DMA_FLAG_TE4
          - DMA_FLAG_GL5
          - DMA_FLAG_TC5
          - DMA_FLAG_HT5
          - DMA_FLAG_TE5
          - DMA_FLAG_GL6
          - DMA_FLAG_TC6
          - DMA_FLAG_HT6
          - DMA_FLAG_TE6
          - DMA_FLAG_GL7
          - DMA_FLAG_TC7
          - DMA_FLAG_HT7
          - DMA_FLAG_TE7
param   DMAy (The input parameters must be the following values):
          - DMA
return  none.
INTStatus DMA_GetIntStatus(uint32_t DMA_IT, const DMA_Module *DMAy)获取 DMA 通道 x 的中断状态,包含对应通道的全局中断、传输完成中断、半传输中断与传输错误中断。
源码注释
name    DMA_GetIntStatus.
fun     Get DMA Channel x interrupt status. Contains the global interrupt,
        transfer completion interrupt, half-transfer interrupt, and transfer
        error interrupt for the corresponding channel.
param   DMA_IT (The input parameters must be the following values):
          - DMA_INT_GLB1
          - DMA_INT_TXC1
          - DMA_INT_HTX1
          - DMA_INT_ERR1
          - DMA_INT_GLB2
          - DMA_INT_TXC2
          - DMA_INT_HTX2
          - DMA_INT_ERR2
          - DMA_INT_GLB3
          - DMA_INT_TXC3
          - DMA_INT_HTX3
          - DMA_INT_ERR3
          - DMA_INT_GLB4
          - DMA_INT_TXC4
          - DMA_INT_HTX4
          - DMA_INT_ERR4
          - DMA_INT_GLB5
          - DMA_INT_TXC5
          - DMA_INT_HTX5
          - DMA_INT_ERR5
          - DMA_INT_GLB6
          - DMA_INT_TXC6
          - DMA_INT_HTX6
          - DMA_INT_ERR6
          - DMA_INT_GLB7
          - DMA_INT_TXC7
          - DMA_INT_HTX7
          - DMA_INT_ERR7
param   DMAy (The input parameters must be the following values):
          - DMA
return  SET or RESET.
note    Global interrupt status is the logic or generation of transfer completion
        interrupt, half-transfer interrupt, transfer error interrupt.
void DMA_ClrIntPendingBit(uint32_t DMA_IT, DMA_Module *DMAy)清除 DMA 通道 x 的中断状态位,包含对应通道的全局中断、传输完成中断、半传输中断与传输错误中断。
源码注释
name    DMA_ClrIntPendingBit.
fun     Clear DMA Channel x interrupt status bits. Contains the global interrupt,
        transfer completion interrupt, half-transfer interrupt, and transfer
        error interrupt for the corresponding channel.
param   DMA_IT (The input parameters must be the following values):
          - DMA_INT_GLB1
          - DMA_INT_TXC1
          - DMA_INT_HTX1
          - DMA_INT_ERR1
          - DMA_INT_GLB2
          - DMA_INT_TXC2
          - DMA_INT_HTX2
          - DMA_INT_ERR2
          - DMA_INT_GLB3
          - DMA_INT_TXC3
          - DMA_INT_HTX3
          - DMA_INT_ERR3
          - DMA_INT_GLB4
          - DMA_INT_TXC4
          - DMA_INT_HTX4
          - DMA_INT_ERR4
          - DMA_INT_GLB5
          - DMA_INT_TXC5
          - DMA_INT_HTX5
          - DMA_INT_ERR5
          - DMA_INT_GLB6
          - DMA_INT_TXC6
          - DMA_INT_HTX6
          - DMA_INT_ERR6
          - DMA_INT_GLB7
          - DMA_INT_TXC7
          - DMA_INT_HTX7
          - DMA_INT_ERR7
param   DMAy (The input parameters must be the following values):
          - DMA
return  none.
note    Global interrupt state is the logic or generation of transfer completion
        interrupt, half-transfer interrupt, transfer error interrupt. In fact,
        after clearing the three interrupt states, the global interrupt state
        will also be cleared.
void DMA_RequestRemap(uint32_t DMA_REMAP, const DMA_Module *DMAy, DMA_ChannelType *DMAChx, FunctionalState Cmd)设置 DMA 通道 x 的重映射请求;通道请求映射灵活,用户可按需把任意 DMA 请求映射到任意 DMA 通道。需要注意,一个 DMA 通道同一时刻只能有一个 DMA 请求。
源码注释
name    DMA_RequestRemap.
fun     Set DMA Channel x's remap request. Channel request mapping is flexible,
        allowing users to map any DMA request to any DMA channel as needed. It
        is important to note that there can be only one DMA request per DMA
        channel at a time.
param   DMA_REMAP (The input parameters must be the following values):
          - DMA_REMAP_ADC1
          - DMA_REMAP_ADC2
          - DMA_REMAP_USART1_TX
          - DMA_REMAP_USART1_RX
          - DMA_REMAP_USART2_TX
          - DMA_REMAP_USART2_RX
          - DMA_REMAP_USART3_TX
          - DMA_REMAP_USART3_RX
          - DMA_REMAP_USART4_TX
          - DMA_REMAP_USART4_RX
          - DMA_REMAP_SPI1_TX
          - DMA_REMAP_SPI1_RX
          - DMA_REMAP_SPI2_TX
          - DMA_REMAP_SPI2_RX
          - DMA_REMAP_I2C1_TX
          - DMA_REMAP_I2C1_RX
          - DMA_REMAP_I2C2_TX
          - DMA_REMAP_I2C2_RX
          - DMA_REMAP_ATIM1_CH1
          - DMA_REMAP_ATIM1_CH2
          - DMA_REMAP_ATIM1_CH3
          - DMA_REMAP_ATIM1_CH4
          - DMA_REMAP_ATIM1_COM
          - DMA_REMAP_ATIM1_UP
          - DMA_REMAP_ATIM1_TRIG
          - DMA_REMAP_ATIM2_CH1
          - DMA_REMAP_ATIM2_CH2
          - DMA_REMAP_ATIM2_CH3
          - DMA_REMAP_ATIM2_CH4
          - DMA_REMAP_ATIM2_COM
          - DMA_REMAP_ATIM2_UP
          - DMA_REMAP_ATIM2_TRIG
          - DMA_REMAP_GTIM1_CH1
          - DMA_REMAP_GTIM1_CH2
          - DMA_REMAP_GTIM1_CH3
          - DMA_REMAP_GTIM1_CH4
          - DMA_REMAP_GTIM1_UP
          - DMA_REMAP_GTIM1_TRIG
          - DMA_REMAP_GTIM2_CH1
          - DMA_REMAP_GTIM2_CH2
          - DMA_REMAP_GTIM2_CH3
          - DMA_REMAP_GTIM2_CH4
          - DMA_REMAP_GTIM2_UP
          - DMA_REMAP_GTIM2_TRIG
          - DMA_REMAP_GTIM3_CH1
          - DMA_REMAP_GTIM3_CH2
          - DMA_REMAP_GTIM3_CH3
          - DMA_REMAP_GTIM3_CH4
          - DMA_REMAP_GTIM3_COM
          - DMA_REMAP_GTIM3_UP
          - DMA_REMAP_GTIM3_TRIG
          - DMA_REMAP_GTIM4_CH1
          - DMA_REMAP_GTIM4_CH2
          - DMA_REMAP_GTIM4_CH3
          - DMA_REMAP_GTIM4_CH4
          - DMA_REMAP_GTIM4_COM
          - DMA_REMAP_GTIM4_UP
          - DMA_REMAP_GTIM4_TRIG
          - DMA_REMAP_BIM1_UP
          - DMA_REMAP_BIM2_UP
param   DMAy (The input parameters must be the following values):
          - DMA
param   DMAChx (The input parameters must be the following values):
          - DMA_CH1
          - DMA_CH2
          - DMA_CH3
          - DMA_CH4
          - DMA_CH5
          - DMA_CH6
          - DMA_CH7
param   Cmd (The input parameters must be the following values):
          - ENABLE
          - DISABLE
return  none.

使用提示: 实现忽略 DMAy 参数,按 Cmd 把 DMA_REMAP 写入 DMAChx 的 CHSEL,Cmd 为 DISABLE 时写入保留值 DMA_REMAP_NONE(0x3F);该保留值已由头文件定义,但不在注释的参数清单中。

5.6.3 Demo 示例说明

本节说明 DMA 的 1 个示例:FLASH_RAM 用存储器到存储器模式把 FLASH 中的一个常量数组搬移到 RAM 缓冲区,并在传输完成后比较两个缓冲区。

5.6.3.1 FLASH_RAM 存储器到存储器传输

工程目录: projects/n32g41x_EVAL/examples/DMA/FLASH_RAM/

使能 DMA 时钟并初始化串口日志→配置 DMA 通道 1 为存储器到存储器传输→把通道请求映射到保留源→使能传输完成中断并启动通道→传输完成中断置位完成标志→比较源与目的缓冲区并打印结果

项目 源码解读
功能 用 DMA 的存储器到存储器模式把 FLASH 中一个 32 字的常量数组搬到 RAM 缓冲区,传输完成后用 memcmp 比较源与目的缓冲区,一致时串口打印通过信息。
源码组成 src/main.c:main、RCC_Configuration、NVIC_Configuration、DMA_IRQ_HANDLER 与常量数组;
inc/main.h:通道、时钟、中断与缓冲区尺寸宏;
src/n32g41x_it.c、inc/n32g41x_it.h:异常与 SysTick 处理函数;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
日志接口 log_init、log_info、log_error 来自 bsp/inc/log.h。
关键配置 通道 DMA_CH1,时钟为 RCC_AHB_PERIPH_DMA;
PeriphAddr 指向 FLASH 中的 SRC_Const_Buffer,MemAddr 指向 RAM 中的 DST_Buffer,方向 DMA_DIR_PERIPH_SRC,BufSize 为 BUFFER_SIZE(32);
外设与存储器地址均递增,数据宽度均为字,正常模式,优先级高,Mem2Mem 使能;
请求重映射到保留源;
中断为 DMA_INT_TXC1,NVIC 抢占与子优先级均为 0,中断号为 DMA_CH1_IRQn。
系统时钟为 HSI+PLL,N32G412 为 80 MHz,N32G415 为 96 MHz。
程序与数据路径 main 调用 log_init,RCC_Configuration 打开 DMA 时钟,NVIC_Configuration 使能 DMA 中断;
memset 清零 DST_Buffer 后 DMA_StructInit 取默认值,再由 DMA_Init 写入通道寄存器;
DMA_RequestRemap 把请求映射到保留源,DMA_ConfigInt 使能传输完成中断,DMA_EnableChannel 启动通道;
main 轮询等待中断置位 TransferCompleteFlag,随后比较两个缓冲区并打印结果。
主要 API DMA_DeInit、DMA_StructInit、DMA_Init、DMA_RequestRemap、DMA_ConfigInt、DMA_EnableChannel、DMA_GetIntStatus、DMA_ClrIntPendingBit
验证方法 编译下载、复位运行后串口先打印 DMA Flash to RAM demo go...;
传输完成且校验一致时打印 DMA Flash to RAM passed,不一致时打印 DMA Flash to RAM failed。
使用提示 时钟源为 HSI+PLL,N32G412 为 80 MHz、N32G415 为 96 MHz;
串口 TX 为 PA9、RX 为 PA10,波特率 115200;
开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。
核心代码解读与移植

示例通过一组宏选定 DMA 通道与缓冲区尺寸,填好 DMA_InitType 后启动存储器到存储器传输,再由传输完成中断通知主程序校验结果。

数据路径: SRC_Const_Buffer(FLASH)→ DMA_InitStructure 的 PeriphAddr 与 MemAddr → DMA_Init 写入 DMA_CH1 的 PADDR、MADDR、TXNUM → 传输完成中断置位 TransferCompleteFlag → memcmp 比较 DST_Buffer → 串口打印结果

1. 用宏集中定义通道与缓冲区尺寸。 inc/main.h 把通道、时钟、中断与缓冲区长度集中定义为一组宏,后续代码只引用宏名。

inc/main.hinc/main.h
#define DMA_USED           DMA
#define DMA_CLK            RCC_AHB_PERIPH_DMA
#define DMA_CHANNEL_USED   DMA_CH1
#define DMA_IRQ_HANDLER    DMA_CH1_IRQHandler
#define DMA_IT_FLAG_TC     DMA_INT_TXC1
#define DMA_IT_FLAG_GL     DMA_INT_GLB1
#define DMA_IRQN           DMA_CH1_IRQn

#define BUFFER_SIZE (sizeof(SRC_Const_Buffer) / sizeof(SRC_Const_Buffer[0]))

extern const uint32_t SRC_Const_Buffer[];

换用其它通道或改变搬运长度时,只需修改这组宏,main 中的配置与中断处理不用改动。

2. 填好 DMA_InitType 并写入通道寄存器。 main 先用 DMA_DeInit 复位通道、DMA_StructInit 取默认值,再逐项填写源与目的地址、方向、缓冲区长度、地址递增、数据宽度、循环模式、优先级与存储器到存储器位,最后由 DMA_Init 写入。

src/main.csrc/main.c · main
    DMA_DeInit(DMA_CHANNEL_USED);
    DMA_StructInit(&DMA_InitStructure);
    DMA_InitStructure.PeriphAddr     = (uint32_t)SRC_Const_Buffer;
    DMA_InitStructure.MemAddr        = (uint32_t)DST_Buffer;
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_SRC;
    DMA_InitStructure.BufSize        = BUFFER_SIZE;
    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_ENABLE;
    DMA_InitStructure.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_WORD;
    DMA_InitStructure.MemDataSize    = DMA_MemoryDataSize_Word;
    DMA_InitStructure.CircularMode   = DMA_MODE_NORMAL;
    DMA_InitStructure.Priority       = DMA_PRIORITY_HIGH;
    DMA_InitStructure.Mem2Mem        = DMA_M2M_ENABLE;
    DMA_Init(DMA_CHANNEL_USED, &DMA_InitStructure);

方向为 DMA_DIR_PERIPH_SRC,即 PeriphAddr 一侧是源;外设与存储器数据宽度都设为字,二者一致时不做宽度对齐。

3. 先映射请求,再使能中断与通道。 存储器到存储器模式下,示例把通道请求映射到保留源,再使能传输完成中断,最后使能通道启动传输。

src/main.csrc/main.c · main
    DMA_RequestRemap(DMA_REMAP_NONE, DMA, DMA_CHANNEL_USED, ENABLE);

    DMA_ConfigInt(DMA_CHANNEL_USED, DMA_INT_TXC, ENABLE);
    DMA_EnableChannel(DMA_CHANNEL_USED, ENABLE);

DMA_RequestRemap 传入的 DMA_REMAP_NONE 是头文件定义的保留请求值;换用外设触发的传输时,这里要改成对应的 DMA_REMAP_* 源。

4. 中断置位完成标志,主程序比较缓冲区。 传输完成中断里读取并清除通道 1 的完成标志,再置位 TransferCompleteFlag;主程序退出等待循环后用 memcmp 比较源与目的缓冲区。

src/main.csrc/main.c · DMA_IRQ_HANDLER
void DMA_IRQ_HANDLER(void)
{
    if (DMA_GetIntStatus(DMA_IT_FLAG_TC, DMA_USED))
    {
        DMA_ClrIntPendingBit(DMA_IT_FLAG_TC, DMA_USED);
        TransferCompleteFlag = 1;
    }
}
src/main.csrc/main.c · main
    while (TransferCompleteFlag == 0) {}

    if (memcmp(SRC_Const_Buffer, DST_Buffer, sizeof(SRC_Const_Buffer)) == 0)
    {
        log_info("DMA Flash to RAM passed\n");
    }
    else
    {
        log_error("DMA Flash to RAM failed\n");
    }

DMA_INT_TXC1 与 DMA_IT_FLAG_TC 对应通道 1 的传输完成中断;换通道时,DMA_IT_FLAG_TC、DMA_IRQN 与中断服务函数名要一并改成该通道的宏与处理函数。

对应源码: src/main.c、inc/main.h

5.6.4 注意与排障

场景 检查与建议 来源
用 DMA 搬运到 FLASH 用户手册第 7 章写明不可以使用 DMA 对 FLASH 进行编程,以避免时序错误;
涉及 FLASH 的存储器到存储器传输只用读方向,写入 FLASH 由其它方式完成。
用户手册
存储器到存储器模式的请求映射 用户手册说明配置通道工作在存储器到存储器模式时,需要把该通道的请求选择值设为保留值(例如 63);
通道配置流程要求先配置 MEM2MEM 位,最后使能通道。
用户手册
使能通道前的中断状态 用户手册的中断说明要求在使能通道之前清除该通道对应的所有中断;
中断状态位通过向清除寄存器的相应位写 1 清除。
用户手册
通道使能后的寄存器写入 DMA_TXNUMx 在通道使能后为只读,DMA_PADDRx 与 DMA_MADDRx 只能在通道禁用(DMA_CHCFGx.CHEN 为 0)时写入;
修改这些寄存器前须先禁用通道。
用户手册
关闭循环模式 用户手册说明关闭循环模式须先向 DMA_CHCFGx.CHEN 写 0 禁用通道,再向 CIRC 写 0;
通道使能时 DMA_CHCFGx 的其它位不能被改写。
用户手册
多个通道使用同一请求源 用户手册的请求映射说明指出不同通道不能使用同一请求源,否则在多个通道都使能的情况下只有高优先级通道会被触发。 用户手册
数据宽度不一致时的对齐 DMA_CHCFGx.PSIZE 与 DMA_CHCFGx.MSIZE 不同时,DMA 按用户手册的可编程数据宽度表对齐数据;
如需把 8 位寄存器写到 32 位地址边界,应把外设大小设为 8 位、存储器大小设为 32 位。
用户手册

N32G412、N32G415 系列勘误手册 V1.0.0(2026.6.30)的勘误列表只列出一行 A 版芯片条目,勘误链接列为空,未列出 DMA 相关条目。

国民技术开发套件文档中心

按芯片系列在线查阅国民技术 MCU 开发套件的芯片资料、SDK、驱动 API 与 Demo 示例说明。

© 2026 国民技术股份有限公司 版权所有粤ICP备11069485号本站使用不含 Cookie 的匿名访问统计