DMA 即 Direct Memory Access. DMA传输方式无须CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,能使CPU的效率大为提高。
1. DMA基础知识
STM32 最多有2个DMA控制器(DMA2仅存在大容量产品中),DMA有7个通道,DMA2有5个通道。每个通道专门用来管理来自一个或多个外设对存储器访问的请求。还有一个仲裁器协调各个DMA请求的优先权。
STM32的DMA有以下一些特性:
- 每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置。
- 在7个请求间的优先权可以通过软件编程来配置,假如在优先权相等时,由硬件决定。
- 独立的源和目标数据区的传输宽度(字节,半字,全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
- 支持循环的缓冲器管理。
- 每个通道都有3个事件标志(DMA半传输,DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求。
- 存储器和存储器间的传输。
- 外设和存储器,存储器和外设的传输。
- 闪存,SRAM, 外设的SRAM,APB1,APB2,和AHB外设均可作为访问的源和目标。
- 可编程的数据传输数目,最大为65536.
外设通过逻辑或输入到DMA通道,意味着每个通道只能同时接收一个请求。
2. 用寄存器方式操作DMA
假设为DMA1的通道4,配置步骤如下:
- 设置外设地址。 外设地址通过DMA1_CPAR4设置,只要在这个寄存器里面写入&USART1_DR的值就可以。该地址将作为DMA传输的目标地址。
- 设置存储器地址。存储器地址通过DMA1_CMAR4来设置,假设要把数组SendBuf作为存储器,那么在该寄存器内写入&SendBuf就可以。该地址将作为DMA传输的源地址。
- 设置传输数据量。通过DMA_CNDTR4寄存器,这里面写入此次要传输的数据量,即SendBuf的大小。该寄存器的数值将在DMA启动后自减,每次新的DMA传输,都重新向该寄存器写入要传输的数据量。
- 设置通道4的配置信息。设置存储器和外设的数据位宽为8,存储器增量模式。优先级可以随便设置,因为只有一个通道开启。
- 使能DMA1通道4,启动传输。以上配置都完成后,就使能DMA1_CCR4的最低位开启DMA传输,注意要设置USART1的使能DMA传输位,通过USART1->CR3的第7位设置。
3. 用库函数的方式操作DMA
总共5步去配置DMA.
- 使能DMA时钟。
- 初始化DMA通道4的参数。
- 使能串口DMA发送。
- 使能DMA1通道4,启动传输。
- 查询DMA传输状态。
1. 使能DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
2. 初始化DMA通道4的参数
DMA的初始化是通过配置函数:
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)
第1个参数指定通道,第二个参数用来初始化DMA。
设置具体如下:
DMA_InitTypeDef DMA_InitStructure;
//DMA外设ADC基地址
DMA_InitStructure.DMA_PeriperalBaseAddr = &USART->DR;
//DMA内存基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar;
//从内存读取发送到外设
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripherialDST;
//DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_BufferSize = 64;
//外设地址不变
DMA_InitStructure.DMA_PeripherialInc = DMA_PeripherialInc_Disable;
//内存地址递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//8位
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
//8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
//工作在正常缓存模式
DMA_InitStructure.DMA_Mode =</