STM32 DMA基础
介绍
DMA(Direct Memory Access,直接内存访问)是STM32微控制器中一个强大的功能,它允许外设与内存之间直接传输数据,而无需CPU的干预。通过使用DMA,可以显著提高系统的效率,尤其是在处理大量数据传输时,例如音频流、图像处理或通信协议(如UART、SPI、I2C等)。
DMA的核心思想是减少CPU的负担,使其能够专注于其他任务,同时外设和内存之间的数据传输由DMA控制器自动完成。
DMA的工作原理
DMA控制器是STM32中的一个独立模块,它可以在外设和内存之间传输数据。DMA传输的基本流程如下:
- 初始化DMA:配置DMA通道、传输方向、数据大小等参数。
- 触发DMA请求:当外设准备好数据或需要数据时,会向DMA控制器发出请求。
- 数据传输:DMA控制器根据配置,自动将数据从源地址传输到目标地址。
- 传输完成:DMA传输完成后,可以触发中断通知CPU。
备注
DMA传输可以是内存到外设、外设到内存或内存到内存。
配置DMA
以下是一个简单的DMA配置示例,假设我们使用STM32的UART外设进行数据传输。
1. 启用DMA时钟
首先,需要启用DMA的时钟:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
2. 配置DMA通道
接下来,配置DMA通道。假设我们使用DMA2的Stream7进行UART传输:
DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.DMA_Channel = DMA_Channel_4;
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)buffer;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStruct.DMA_BufferSize = bufferSize;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream7, &DMA_InitStruct);
3. 启用DMA
配置完成后,启用DMA:
DMA_Cmd(DMA2_Stream7, ENABLE);
4. 启用UART的DMA请求
最后,启用UART的DMA请求:
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
实际应用场景
场景1:UART数据接收
假设我们需要通过UART接收大量数据,例如传感器数据。使用DMA可以避免CPU频繁中断,从而提高系统效率。
uint8_t rxBuffer[100];
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)rxBuffer;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStruct.DMA_BufferSize = sizeof(rxBuffer);
DMA_Init(DMA2_Stream7, &DMA_InitStruct);
场景2:内存到内存传输
在某些情况下,我们可能需要将数据从一个内存区域复制到另一个内存区域。DMA也可以用于这种场景。
uint8_t srcBuffer[100];
uint8_t destBuffer[100];
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)srcBuffer;
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)destBuffer;
DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToMemory;
DMA_InitStruct.DMA_BufferSize = sizeof(srcBuffer);
DMA_Init(DMA2_Stream7, &DMA_InitStruct);
总结
DMA是STM32微控制器中一个非常有用的功能,它可以显著提高系统的效率,尤其是在处理大量数据传输时。通过合理配置DMA,可以减少CPU的负担,使其能够专注于其他任务。
提示
在实际项目中,建议根据具体需求选择合适的DMA模式和配置,以确保系统的最佳性能。
附加资源
练习
- 尝试配置DMA以实现UART的数据发送功能。
- 使用DMA实现内存到内存的数据传输,并测量传输时间。
- 探索DMA的中断功能,并在传输完成后触发中断。
通过以上练习,您将更深入地理解DMA的工作原理和应用场景。