stm32 DMA配置

Posted zengsf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm32 DMA配置相关的知识,希望对你有一定的参考价值。

  DMA就是将一个地址空间复制到另外一个地址空间。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备直接传送数据,使CPU的效率大大的提高了。

  stm一般有两个DMA控制器,DMA1有7通道。DMA2有5个通道。

  STM32 的 DMA 有以下一些特性:   

  ●每个通道都直接连接专用的硬件 DMA 请求,每个通道都同样支持软件触发。 

这些功能通过软件来配置。

  ●在七个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低), 

假如在相等优先权时由硬件决定(请求 0 优先于请求 1,依此类推)

  ●独立的源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。

源和目标地址必须按数据传输宽度对齐。

  ●支持循环的缓冲器管理

  ●每个通道都有 3 个事件标志(DMA 半传输, DMA 传输完成和 DMA 传输出错)

这3个事件标志逻辑或成为一个单独的中断请求。 

  ●存储器和存储器间的传输

  ●外设和存储器,存储器和外设的传输

  ●闪存、 SRAM、外设的 SRAMAPB1 APB2 AHB 外设均可作为访问的源和目标。

  ●可编程的数据传输数目:最大为 65536

 

  我们可以通过DMA中断状态寄存器(DMA_ISR)来获取当前DMA传输的状态。通过

DMA中断标志清除寄存器(CMA_IFCR)清除中断状态寄存器对应的位。

 

1)使能 DMA 时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 时钟
2)初始化 DMA 通道 4 参数

 

 1 DMA_InitTypeDef DMA_InitStructure;
 2 DMA_InitStructure.DMA_PeripheralBaseAddr = &USART1->DR; //DMA 外设 ADC 基地址
 3 DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA 内存基地址
 4 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //从内存读取发送到外设
 5 DMA_InitStructure.DMA_BufferSize = 64; //DMA 通道的 DMA 缓存的大小
 6 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变
 7 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址递增
 8 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //8 位
 9 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 8 位
10 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
11 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA 通道 x 拥有中优先级
12 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存传输
13 DMA_Init(DMA_CHx, &DMA_InitStructure); //根据指定的参数初始化

3) 使能串口 DMA 发送

进行 DMA 配置之后,我们就要开启串口的 DMA 发送功能,使用的函数是:
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
如果是要使能串口 DMA 接受,那么第二个参数修改为 USART_DMAReq_Rx 即可。

 

4) 使能 DMA1 通道 4,启动传输。

使能串口 DMA 发送之后,我们接着就要使能 DMA 传输通道:
DMA_Cmd(DMA_CHx, ENABLE);

 

5) 查询 DMA 传输状态
在 DMA 传输过程中,我们要查询 DMA 传输通道的状态,使用的函数是:
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)
比如我们要查询 DMA 通道 4 传输是否完成,方法是:
DMA_GetFlagStatus(DMA2_FLAG_TC4);
这里还有一个比较重要的函数就是获取当前剩余数据量大小的函数:
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx)
比如我们要获取 DMA 通道 4 还有多少个数据没有传输,方法是:
DMA_GetCurrDataCounter(DMA1_Channel4);

 

 

 

 1 void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
 2 {
 3      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);    //使能DMA传输
 4     
 5   DMA_DeInit(DMA_CHx);   //将DMA的通道1寄存器重设为缺省值
 6 
 7     DMA1_MEM_LEN=cndtr;
 8     DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;  //DMA外设基地址
 9     DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMA内存基地址
10     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //数据传输方向,从内存读取发送到外设
11     DMA_InitStructure.DMA_BufferSize = cndtr;  //DMA通道的DMA缓存的大小
12     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
13     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
14     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //数据宽度为8位
15     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
16     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //工作在正常模式
17     DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级 
18     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
19     DMA_Init(DMA_CHx, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
20           
21 } 
22 //开启一次DMA传输
23 void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
24 { 
25     DMA_Cmd(DMA_CHx, DISABLE );  //关闭USART1 TX DMA1 所指示的通道      
26      DMA_SetCurrDataCounter(DMA_CHx,DMA1_MEM_LEN);//DMA通道的DMA缓存的大小
27      DMA_Cmd(DMA_CHx, ENABLE);  //使能USART1 TX DMA1 所指示的通道 
28 }      

 

知识来源:STM32F1 开发指南

以上是关于stm32 DMA配置的主要内容,如果未能解决你的问题,请参考以下文章

STM32HAL ADC+TIM+DMA采集交流信号 基于cubemx

STM32F103VET6基于STM32CubeMX 配置DMA方式获取内部温度

STM32cubemx教程 DAC+TIM+DMA

stm32 DMA配置

STM32 DMA问题

STM32F10x 串口使用DMA