5.7 DMA 使用说明
本章说明 N32H49x 标准外设库中 DMA 驱动的文件组成与 12 个公开函数,以及 BURST 与 FLASH_RAM 2 个示例。DMA 在外设与存储器之间或存储器与存储器之间搬移数据,通道的优先级、数据宽度、突发长度与请求重映射请配合用户手册的“DMA 控制器”章节阅读。
5.7.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32h49x_std_periph_driver/inc/n32h49x_dma.h |
定义通道、数据宽度、突发与中断选择等宏与 DMA_InitType 结构,声明 12 个公开函数 |
firmware/n32h49x_std_periph_driver/src/n32h49x_dma.c |
实现上述 12 个函数:通道复位与初始化、结构体默认值、通道使能、中断与数据计数设置、标志与中断状态读写、请求重映射 |
projects/n32h49x_EVAL/examples/DMA/ |
DMA 示例根目录,含 BURST、FLASH_RAM 2 个示例 |
projects/n32h49x_EVAL/examples/DMA/BURST/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32h49x_EVAL/bsp/ |
该示例引用的公共板级文件:串口日志函数 |
5.7.2 API 参考
以下 12 个公开函数按 n32h49x_dma.h 的声明顺序分为 4 组;每个条目给出功能摘要与 n32h49x_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)把 DMA1/DMA2 通道 x 的 CHCFG、TXNUM、PADDR、MADDR、INTCLR 寄存器复位为默认值。
name DMA_DeInit.
fun Reset CHCFG, TXNUM, PADDR, MADDR, INTCLR registers of DMA1/DMA2 Channel x
to their default reset values.
param DMAChx (The input parameters must be the following values):
- DMA1_CH1
- DMA1_CH2
- DMA1_CH3
- DMA1_CH4
- DMA1_CH5
- DMA1_CH6
- DMA1_CH7
- DMA1_CH8
- DMA2_CH1
- DMA2_CH2
- DMA2_CH3
- DMA2_CH4
- DMA2_CH5
- DMA2_CH6
- DMA2_CH7
- DMA2_CH8
return none
void DMA_Init(DMA_ChannelType* DMAChx, DMA_InitType* DMA_InitParam)用 DMA_InitType 结构体参数初始化 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):
- DMA1_CH1
- DMA1_CH2
- DMA1_CH3
- DMA1_CH4
- DMA1_CH5
- DMA1_CH6
- DMA1_CH7
- DMA1_CH8
- DMA2_CH1
- DMA2_CH2
- DMA2_CH3
- DMA2_CH4
- DMA2_CH5
- DMA2_CH6
- DMA2_CH7
- DMA2_CH8
param DMA_InitParam (The input parameters must be the following values):
- PeriphAddr
- MemAddr
- Direction
- DMA_DIR_PERIPH_DST
- DMA_DIR_PERIPH_SRC
- BufSize
- PeriphInc
- DMA_PERIPH_INC_ENABLE
- DMA_PERIPH_INC_DISABLE
- MemoryInc
- DMA_MEM_INC_ENABLE
- DMA_MEM_INC_DISABLE
- PeriphDataSize
- DMA_PERIPH_DATA_WIDTH_BYTE
- DMA_PERIPH_DATA_WIDTH_HALFWORD
- DMA_PERIPH_DATA_WIDTH_WORD
- MemDataSize
- DMA_MEM_DATA_WIDTH_BYTE
- DMA_MEM_DATA_WIDTH_HALFWORD
- DMA_MEM_DATA_WIDTH_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
- BurstCmd
- DMA_BURST_ENABLE
- DMA_BURST_DISABLE
- BURST_MODE
- DMA_BURST_MODE_Almost
- DMA_BURST_MODE_Dynamic
- BURST_LEN
- DMA_BURST_LEN_single
- DMA_BURST_LEN_1
- DMA_BURST_LEN_2
- DMA_BURST_LEN_3
- DMA_BURST_LEN_4
- DMA_BURST_LEN_5
- DMA_BURST_LEN_6
- DMA_BURST_LEN_7
- DMA_BURST_LEN_8
return none
void DMA_StructInit(DMA_InitType* DMA_InitParam)把 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
void DMA_EnableChannel(DMA_ChannelType* DMAChx, FunctionalState Cmd)使能 DMA 通道 x;初始化成功后调用以开始搬移数据。
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):
- DMA1_CH1
- DMA1_CH2
- DMA1_CH3
- DMA1_CH4
- DMA1_CH5
- DMA1_CH6
- DMA1_CH7
- DMA1_CH8
- DMA2_CH1
- DMA2_CH2
- DMA2_CH3
- DMA2_CH4
- DMA2_CH5
- DMA2_CH6
- DMA2_CH7
- DMA2_CH8
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):
- DMA1_CH1
- DMA1_CH2
- DMA1_CH3
- DMA1_CH4
- DMA1_CH5
- DMA1_CH6
- DMA1_CH7
- DMA1_CH8
- DMA2_CH1
- DMA2_CH2
- DMA2_CH3
- DMA2_CH4
- DMA2_CH5
- DMA2_CH6
- DMA2_CH7
- DMA2_CH8
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):
- DMA1_CH1
- DMA1_CH2
- DMA1_CH3
- DMA1_CH4
- DMA1_CH5
- DMA1_CH6
- DMA1_CH7
- DMA1_CH8
- DMA2_CH1
- DMA2_CH2
- DMA2_CH3
- DMA2_CH4
- DMA2_CH5
- DMA2_CH6
- DMA2_CH7
- DMA2_CH8
param DataNumber (The input parameters must be the following values):
- 1~0xFFFF
return none
note This function can only be used when the DMAChx is disabled.
uint16_t DMA_GetCurrDataCounter(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):
- DMA1_CH1
- DMA1_CH2
- DMA1_CH3
- DMA1_CH4
- DMA1_CH5
- DMA1_CH6
- DMA1_CH7
- DMA1_CH8
- DMA2_CH1
- DMA2_CH2
- DMA2_CH3
- DMA2_CH4
- DMA2_CH5
- DMA2_CH6
- DMA2_CH7
- DMA2_CH8
return Returns the number of bytes remaining to be transferred.
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_Flag, 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
- DMA_FLAG_GL8
- DMA_FLAG_TC8
- DMA_FLAG_HT8
- DMA_FLAG_TE8
param DMAy (The input parameters must be the following values):
- DMA1
- DMA2
return SET or RESET.
void DMA_ClearFlag(uint32_t DMAy_FLAG, 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
- DMA_FLAG_GL8
- DMA_FLAG_TC8
- DMA_FLAG_HT8
- DMA_FLAG_TE8
param DMAy (The input parameters must be the following values):
- DMA1
- DMA2
return none.
INTStatus DMA_GetIntStatus(uint32_t DMAy_Int, 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 DMAy_Int (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
- DMA_INT_GLB8
- DMA_INT_TXC8
- DMA_INT_HTX8
- DMA_INT_ERR8
param DMAy (The input parameters must be the following values):
- DMA1
- DMA2
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 DMAy_Int, 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 DMAy_Int (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
- DMA_INT_GLB8
- DMA_INT_TXC8
- DMA_INT_HTX8
- DMA_INT_ERR8
param DMAy (The input parameters must be the following values):
- DMA1
- DMA2
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, DMA_ChannelType* DMAChx, FunctionalState Cmd)设置 DMA 通道 x 的请求重映射;请求映射灵活,可把任意 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_ADC3
- DMA_REMAP_DSMU_FILT0
- 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_UART5_TX
- DMA_REMAP_UART5_RX
- DMA_REMAP_UART6_TX
- DMA_REMAP_UART6_RX
- DMA_REMAP_UART7_TX
- DMA_REMAP_UART7_RX
- DMA_REMAP_UART8_TX
- DMA_REMAP_UART8_RX
- DMA_REMAP_SPI1_TX
- DMA_REMAP_SPI1_RX
- DMA_REMAP_SPI2_I2S2_TX
- DMA_REMAP_SPI2_I2S2_RX
- DMA_REMAP_SPI3_I2S3_TX
- DMA_REMAP_SPI3_I2S3_RX
- DMA_REMAP_RES
- DMA_REMAP_DSMU_FILT1
- DMA_REMAP_SPI4_TX
- DMA_REMAP_SPI4_RX
- DMA_REMAP_SPI5_TX
- DMA_REMAP_SPI5_RX
- DMA_REMAP_SPI6_TX
- DMA_REMAP_SPI6_RX
- DMA_REMAP_XSPI_TX
- DMA_REMAP_XSPI_RX
- DMA_REMAP_I2C1_TX
- DMA_REMAP_I2C1_RX
- DMA_REMAP_I2C2_TX
- DMA_REMAP_I2C2_RX
- DMA_REMAP_I2C3_TX
- DMA_REMAP_I2C3_RX
- DMA_REMAP_I2C4_TX
- DMA_REMAP_I2C4_RX
- DMA_REMAP_SDIO
- DMA_REMAP_DAC1
- DMA_REMAP_DAC2
- DMA_REMAP_DSMU_FILT2
- DMA_REMAP_DSMU_FILT3
- DMA_REMAP_USART9_TX
- DMA_REMAP_USART9_RX
- DMA_REMAP_UART10_TX
- DMA_REMAP_UART10_RX
- DMA_REMAP_CORDIC_WR
- DMA_REMAP_CORDIC_RD
- DMA_REMAP_BTIM1_UP
- DMA_REMAP_BTIM2_UP
- 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_UP
- DMA_REMAP_GTIM3_TRIG
- DMA_REMAP_GTIM4_CH1
- DMA_REMAP_GTIM4_CH2
- DMA_REMAP_GTIM4_CH3
- DMA_REMAP_GTIM4_CH4
- DMA_REMAP_GTIM4_UP
- DMA_REMAP_GTIM4_TRIG
- DMA_REMAP_GTIM5_CH1
- DMA_REMAP_GTIM5_CH2
- DMA_REMAP_GTIM5_CH3
- DMA_REMAP_GTIM5_CH4
- DMA_REMAP_GTIM5_UP
- DMA_REMAP_GTIM5_TRIG
- DMA_REMAP_GTIM6_CH1
- DMA_REMAP_GTIM6_CH2
- DMA_REMAP_GTIM6_CH3
- DMA_REMAP_GTIM6_CH4
- DMA_REMAP_GTIM6_UP
- DMA_REMAP_GTIM6_TRIG
- DMA_REMAP_GTIM7_CH1
- DMA_REMAP_GTIM7_CH2
- DMA_REMAP_GTIM7_CH3
- DMA_REMAP_GTIM7_CH4
- DMA_REMAP_GTIM7_UP
- DMA_REMAP_GTIM7_TRIG
- DMA_REMAP_GTIM8_CH1
- DMA_REMAP_GTIM8_CH2
- DMA_REMAP_GTIM8_CH3
- DMA_REMAP_GTIM8_CH4
- DMA_REMAP_GTIM8_COM
- DMA_REMAP_GTIM8_UP
- DMA_REMAP_GTIM8_TRIG
- DMA_REMAP_GTIM9_CH1
- DMA_REMAP_GTIM9_CH2
- DMA_REMAP_GTIM9_CH3
- DMA_REMAP_GTIM9_CH4
- DMA_REMAP_GTIM9_COM
- DMA_REMAP_GTIM9_UP
- DMA_REMAP_GTIM9_TRIG
- DMA_REMAP_GTIM10_CH1
- DMA_REMAP_GTIM10_CH2
- DMA_REMAP_GTIM10_CH3
- DMA_REMAP_GTIM10_CH4
- DMA_REMAP_GTIM10_COM
- DMA_REMAP_GTIM10_UP
- DMA_REMAP_GTIM10_TRIG
- 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_ATIM3_CH1
- DMA_REMAP_ATIM3_CH2
- DMA_REMAP_ATIM3_CH3
- DMA_REMAP_ATIM3_CH4
- DMA_REMAP_ATIM3_COM
- DMA_REMAP_ATIM3_UP
- DMA_REMAP_ATIM3_TRIG
param DMAChx (The input parameters must be the following values):
- DMA1_CH1
- DMA1_CH2
- DMA1_CH3
- DMA1_CH4
- DMA1_CH5
- DMA1_CH6
- DMA1_CH7
- DMA1_CH8
- DMA2_CH1
- DMA2_CH2
- DMA2_CH3
- DMA2_CH4
- DMA2_CH5
- DMA2_CH6
- DMA2_CH7
- DMA2_CH8
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none.
5.7.3 Demo 示例说明
本节说明 DMA 的 2 个示例:BURST 用突发模式把常量数组从存储器搬移到存储器,FLASH_RAM 用普通模式完成同样的存储到存储搬移。
5.7.3.1 BURST 突发搬运存储器到存储器
工程目录: projects/n32h49x_EVAL/examples/DMA/BURST/
初始化日志与 DMA1 时钟→配置 DMA1_CH1 为存储到存储并启用突发搬移→配置保留请求映射并开启传输完成中断→使能通道并等待中断置位完成标志→比较源与目的缓冲区并打印结果
| 项目 | 源码解读 |
|---|---|
| 功能 | 用 DMA1_CH1 以存储器到存储器方式把常量数组 SRC_Const_Buffer 搬到 DST_Buffer,并启用突发传输(近似模式、长度 8);传输完成后中断置位标志, main 比较两个缓冲区并打印通过或失败。 |
| 源码组成 | src/main.c:main、RCC_Configuration、NVIC_Configuration、DMA_IRQ_HANDLER;inc/main.h:定义 DMA_USED(DMA1)、DMA_CHANNEL_USED(DMA1_CH1)、BUFFER_SIZE 等宏;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程。 |
| 关键配置 | 时钟:RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_DMA1, ENABLE);通道:DMA1_CH1, Direction 为 DMA_DIR_PERIPH_SRC,Mem2Mem 使能,WORD 宽度,PeriphInc 与 MemoryInc 均使能;突发: BurstCmd 使能、BurstMode 为 DMA_BURST_MODE_ALMOST、BurstLen 为 DMA_BURST_LEN_8;中断: DMA_INT_TXC1。 |
| 程序与数据路径 | main 先经 RCC_Configuration 使能 DMA1 时钟、NVIC_Configuration 使能通道中断;清空 DST_Buffer 后依次 DMA_DeInit、DMA_StructInit 并填 DMA_InitStructure,用 DMA_Init 写入 DMA1_CH1;DMA_RequestRemap 配置保留请求映射、DMA_ConfigInt 开启传输完成中断、DMA_EnableChannel 启动传输;main 等待 TransferCompleteFlag 后用 memcmp 比较缓冲区并打印结论。 |
| 主要 API | DMA_DeInit、DMA_StructInit、DMA_Init、DMA_RequestRemap、DMA_ConfigInt、DMA_EnableChannel |
| 验证方法 | 串口打印 “DMA Burst transfer passed” 表示源与目的缓冲区内容一致; 否则打印 “DMA Burst transfer failed”。 |
| 使用提示 | 存储器到存储器传输必须配置保留的请求映射号 DMA_REMAP_RES;TransferCompleteFlag 在中断服务函数中置位,主循环据此判断搬运结束;突发长度取 8、突发方式取近似模式,移植时按目标通道能力调整。 |
核心代码解读与移植
示例用 DMA1_CH1 在突发模式下把常量数组从存储器搬到存储器,传输完成后用中断置位标志并比较缓冲区内容。
数据路径: RCC_Configuration 使能 DMA1 时钟 → NVIC_Configuration 打开通道中断 → DMA_StructInit 与 DMA_Init 配置 DMA1_CH1 突发搬移 → DMA_RequestRemap 配置保留请求映射、DMA_ConfigInt 开启传输完成中断 → DMA_EnableChannel 启动传输,中断置位 TransferCompleteFlag → memcmp 比较缓冲区
1. 初始化通道并填入结构体。 main 先复位通道并把结构体填为默认值,再设置外设地址、存储器地址、传输方向与突发参数,最后写入 DMA1_CH1。
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.MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_WORD;
DMA_InitStructure.MemDataSize = DMA_MEM_DATA_WIDTH_WORD;
DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_ENABLE;
/* DMA BURST enable */
DMA_InitStructure.BurstCmd = DMA_BURST_ENABLE;
/* BURST mode is almost */
DMA_InitStructure.BurstMode = DMA_BURST_MODE_ALMOST;
/* BURST length */
DMA_InitStructure.BurstLen = DMA_BURST_LEN_8;
DMA_Init(DMA_CHANNEL_USED, &DMA_InitStructure);
存储到存储传输用 DMA_M2M_ENABLE 加 DMA_DIR_PERIPH_SRC,把源数组放在外设地址一侧,两端地址都使能递增。
2. 配置保留请求映射并开启中断。 存储器到存储器模式需要使用保留的请求映射号 DMA_REMAP_RES,随后打开传输完成中断并启动通道。
/* When operating in memory-to-memory mode, a reserved channel
request mapping number must be configured */
DMA_RequestRemap(DMA_REMAP_RES, DMA_CHANNEL_USED, ENABLE);
/* Enable DMA x Channel y Transfer Complete interrupt */
DMA_ConfigInt(DMA_CHANNEL_USED, DMA_IT_FLAG_TC, ENABLE);
/* Enable DMA x Channel y transfer */
DMA_EnableChannel(DMA_CHANNEL_USED, ENABLE);
中断在使能通道之前打开,保证首次传输完成就能被捕获;DMA_IT_FLAG_TC 在本示例中定义为 DMA_INT_TXC1。
3. 等待完成并比较缓冲区。 主循环轮询 TransferCompleteFlag,中断置位后用 memcmp 比较源与目的缓冲区。
/* Wait the end of transmission */
while (TransferCompleteFlag == 0)
{
}
/* Check if the transmitted and received data are equal */
if (memcmp(SRC_Const_Buffer, DST_Buffer, BUFFER_SIZE) == 0)
{
log_info("DMA Burst transfer passed\n");
}
else
{
log_error("DMA Burst transfer failed\n");
}
TransferCompleteFlag 用 __IO 修饰,避免编译器优化掉轮询读取;比较长度用 BUFFER_SIZE 与实际搬运量保持一致。
4. 中断服务函数置位完成标志。 DMA_IRQ_HANDLER 检查传输完成中断状态,清除挂起位并置位 TransferCompleteFlag。
void DMA_IRQ_HANDLER(void)
{
/* Test on DMA channel Transfer Complete interrupt */
if (DMA_GetIntStatus(DMA_IT_FLAG_TC, DMA_USED))
{
/* Clear DMA channel Transfer Complete interrupt pending bits */
DMA_ClrIntPendingBit(DMA_IT_FLAG_TC, DMA_USED);
/* Set DMA transfer completion flag */
TransferCompleteFlag = 1;
}
}
中断里必须先判断再清除对应通道的挂起位;DMA_IRQ_HANDLER 与 DMA_USED 由 main.h 的宏映射到实际通道。
对应源码: src/main.c
5.7.3.2 FLASH_RAM 普通搬运存储器到存储器
工程目录: projects/n32h49x_EVAL/examples/DMA/FLASH_RAM/
初始化日志与 DMA2 时钟→配置 DMA2_CH8 为存储到存储普通搬移→配置保留请求映射并开启传输完成中断→使能通道并等待中断置位完成标志→比较源与目的缓冲区并打印结果
| 项目 | 源码解读 |
|---|---|
| 功能 | 用 DMA2_CH8 以存储器到存储器方式把常量数组 SRC_Const_Buffer 搬到 DST_Buffer,不启用突发;传输完成后中断置位标志, main 比较两个缓冲区并打印通过或失败。 |
| 源码组成 | src/main.c:main、RCC_Configuration、NVIC_Configuration、DMA_IRQ_HANDLER;inc/main.h:定义 DMA_USED(DMA2)、DMA_CHANNEL_USED(DMA2_CH8)、BUFFER_SIZE 等宏;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程。 |
| 关键配置 | 时钟:RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_DMA2, ENABLE);通道:DMA2_CH8, Direction 为 DMA_DIR_PERIPH_SRC,Mem2Mem 使能,WORD 宽度,PeriphInc 与 MemoryInc 均使能;中断: DMA_INT_TXC,非突发普通模式。 |
| 程序与数据路径 | main 使能 DMA2 时钟并配置 DMA2_Channel8 中断;清空 DST_Buffer 后依次 DMA_DeInit、DMA_StructInit 并填普通模式结构体,用 DMA_Init 写入 DMA2_CH8;DMA_RequestRemap 配置保留请求映射、DMA_ConfigInt 开启传输完成中断、DMA_EnableChannel 启动传输;等待 TransferCompleteFlag 后用 memcmp 比较并打印结论。 |
| 主要 API | DMA_DeInit、DMA_StructInit、DMA_Init、DMA_RequestRemap、DMA_ConfigInt、DMA_EnableChannel |
| 验证方法 | 串口打印 “DMA Flash to RAM passed” 表示源与目的缓冲区内容一致; 否则打印 “DMA Flash to RAM failed”。 |
| 使用提示 | 与 BURST 示例相比不开启突发,其余流程一致; 存储器到存储器传输同样需要保留请求映射 DMA_REMAP_RES;通道与中断编号由 main.h 的宏决定,移植时改为目标通道的编号。 |
核心代码解读与移植
示例用 DMA2_CH8 在普通模式下把常量数组从存储器搬到存储器,传输完成后用中断置位标志并比较缓冲区内容。
数据路径: RCC_Configuration 使能 DMA2 时钟 → NVIC_Configuration 打开 DMA2_Channel8 中断 → DMA_StructInit 与 DMA_Init 配置 DMA2_CH8 普通搬移 → DMA_RequestRemap 配置保留请求映射、DMA_ConfigInt 开启传输完成中断 → DMA_EnableChannel 启动传输,中断置位 TransferCompleteFlag → memcmp 比较缓冲区
1. 配置通道搬运参数。 main 用与 BURST 示例相同的字段配置 DMA2_CH8,但不设置突发参数,保持默认的非突发模式。
/* DMA x channel y configuration */
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.MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_WORD;
DMA_InitStructure.MemDataSize = DMA_MEM_DATA_WIDTH_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_StructInit 先把突发功能置为默认关闭,因此这里无需再写突发字段。
2. 配置请求映射、中断与启动。 与 BURST 示例相同,先配置 DMA_REMAP_RES 保留映射,再开启传输完成中断并启动通道。
/* When operating in memory-to-memory mode, a reserved channel
request mapping number must be configured */
DMA_RequestRemap(DMA_REMAP_RES, DMA_CHANNEL_USED, ENABLE);
/* Enable DMA x Channel y Transfer Complete interrupt */
DMA_ConfigInt(DMA_CHANNEL_USED, DMA_INT_TXC, ENABLE);
/* Enable DMA x Channel y transfer */
DMA_EnableChannel(DMA_CHANNEL_USED, ENABLE);
这里直接使用通道无关的中断选择宏 DMA_INT_TXC,由 DMA_Init 写入的通道决定具体通道。
3. 等待完成并比较缓冲区。 主循环轮询 TransferCompleteFlag,中断置位后用 memcmp 比较源与目的缓冲区。
/* Wait the end of transmission */
while (TransferCompleteFlag == 0)
{
}
/* Check if the transmitted and received data are equal */
if (memcmp(SRC_Const_Buffer, DST_Buffer, BUFFER_SIZE) == 0)
{
log_info("DMA Flash to RAM passed\n");
}
else
{
log_error("DMA Flash to RAM failed\n");
}
比较长度同样取 BUFFER_SIZE,与结构体中的 BufSize 对应,才能验证整段数据搬移正确。
4. 中断服务函数置位完成标志。 DMA_IRQ_HANDLER 检查传输完成中断状态,清除挂起位并置位 TransferCompleteFlag。
void DMA_IRQ_HANDLER(void)
{
/* Test on DMA channel Transfer Complete interrupt */
if (DMA_GetIntStatus(DMA_IT_FLAG_TC, DMA_USED))
{
/* Clear DMA channel Transfer Complete interrupt pending bits */
DMA_ClrIntPendingBit(DMA_IT_FLAG_TC, DMA_USED);
/* Set DMA transfer completion flag */
TransferCompleteFlag = 1;
}
}
该函数与 BURST 示例一致,通道号同样来自 main.h 中的宏,移植时随通道一起改。
对应源码: src/main.c
5.7.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| FLASH 编程 | 不建议使用 DMA 对 FLASH 进行编程,以避免时序错误。 | 用户手册 |
| FLASH 读取 | 使用 DMA 读取 FLASH 时,需要关闭 DCache,读取完成后再打开。 | 用户手册 |
| 请求源唯一 | 不同通道不能使用同一请求源,否则多个通道都使能时只有高优先级通道会被触发。 | 用户手册 |
| 存储器到存储器映射 | 工作在存储器到存储器模式时,DMA 请求映射需要设置为保留值。 | 用户手册 |
| 寄存器写入条件 | 只有在通道禁用时才能写地址与数据数量寄存器,通道使能后 DMA_TXNUMx 变为只读。 |
用户手册 |
| 配置顺序 | 必须在使能通道前配置好该通道的寄存器,否则可能产生权限错误事件; 配置顺序须按用户手册的流程执行。 |
用户手册 |
| 使能前清中断 | 使用软件中断服务时,应在使能通道之前清除该通道对应的所有中断。 | 用户手册 |
| 关闭循环模式 | 关闭循环模式需先向 CHEN 写 0 禁用通道,再向 CIRC 写 0,因为 CHEN 为 1 时其它位不能被改写。 |
用户手册 |
| 地址对齐 | PSIZE、MSIZE 决定地址递增步长与忽略的低位,例如 16 位忽略第 0 位、32 位忽略第 0 位和第 1 位。 |
用户手册 |
| 传输数量 | 传输数量范围为 0~65535; 当该寄存器为 0 时,无论通道是否开启都不会发生数据传输。 |
用户手册 |
| 传输错误 | 对保留地址区域的访问会导致传输错误,硬件自动清除通道使能位并停止通道操作。 | 用户手册 |