stm32DMA

2023-12-21 22:17:24

DMA

DMA简介

DMA(Direct Memory Access)—直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候,CPU 可以干其他的事情,DMA 控制器独立于内核,属于一个单独的外设。

数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。DMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道,DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量产品和互联型产品中。

DMA功能框图

在这里插入图片描述

DMA请求

如果外设要想通过 DMA 来传输数据,必须先给 DMA 控制器发送 DMA 请求,DMA 收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且 DMA 控制器收到应答信号之后,就会启动 DMA 的传输,直到传输完毕

DMA请求通道

在这里插入图片描述

虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个,不能同时接收多个

仲裁器

多个 DMA 通道请求时,就意味着有先后响应处理的顺序问题,分为两个阶段。

第一阶段属于软件阶段,可以在 DMA_CCRx 寄存器中设置,有 4 个等级:非常高、高、中和低四个优先级。

第二阶段属于硬件阶段,如果两个或以上的 DMA 通道请求设置的优先级一样,则他们优先级取决于通道编号,编号越低优先权越高。0>1.

DMA 数据配置

  1. 最核心就是配置要传输的数据,包括数据从哪里来,要到哪里去------------------------------传哪去
  2. 传输的数据的单位是什么,要传多少数据,是一次传输还是循环传输等等。--------------怎么传

从哪里来到哪里去

外设到存储器

以 ADC 采集为例。DMA 外设寄存器的地址对应的就是 ADC数据寄存器的地址,DMA 存储器的地址就是我们自定义的变量(用来接收存储 AD 采集的数据)的地址。方向我们设置外设为源地址。

存储器到外设

以串口向电脑端发送数据为例。DMA 外设寄存器的地址对应的就是串口数据寄存器的地址,DMA 存储器的地址就是我们自定义的变**量(相当于一个缓冲区,用来存储通过串口发送到电脑的数据)**的地址。方向我们设置外设为目标地址

存储器到存储器

以内部 FLASH 向内部 SRAM 复制数据为例。DMA 外设寄存器的地址对应的就是内部 FLASH(我们这里把内部 FALSH 当作一个外设来看)的地址,DMA存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储来自内部 FLASH 的数据)的地址。方向我们设置外设(即内部 FLASH)为源地址。跟上面两个不一样的是,这里需要把DMA_CCR 位 14:MEM2MEM:存储器到存储器模式配置为 1,启动 M2M 模式。

DMA初始化结构体讲解

typedef struct
{
uint32_t DMA_PeripheralBaseAddr; // 外设地址
uint32_t DMA_MemoryBaseAddr; // 存储器地址
uint32_t DMA_DIR; // 传输方向
uint32_t DMA_BufferSize; // 传输数目
uint32_t DMA_PeripheralInc; // 外设地址增量模式
uint32_t DMA_MemoryInc; // 存储器地址增量模式
uint32_t DMA_PeripheralDataSize; // 外设数据宽度
uint32_t DMA_MemoryDataSize; // 存储器数据宽度
uint32_t DMA_Mode; // 模式选择
uint32_t DMA_Priority; // 通道优先级
uint32_t DMA_M2M; // 存储器到存储器模式
} DMA_InitTypeDef;
结构体成员功能选项
DMA_PeripheralBaseAddr设定 DMA_CPAR 寄存器的值
DMA_MemoryBaseAddr设定 DMA_CMAR 寄存器值
DMA_DIR传输方向选择,可选外设到存储器、存储器到外设。它设定 DMA_CCR 寄存器的DIR[1:0] 位的值。
DMA_BufferSize设定待传输数据数目,初始化设定 DMA_CNDTR 寄存器的值
DMA_PeripheralInc如果配置为 DMA_PeripheralInc_Enable,使能外设地址自动递增功能,它设定 DMA_CCR 寄存器的 PINC 位的值
DMA_MemoryInc如果配置为 DMA_MemoryInc_Enable,使能存储器地址自动递增功能,它 设定 DMA_CCR 寄存器的 MINC 位的值
DMA_PeripheralDataSize外设数据宽度,可选字节 (8 位)、半字 (16 位) 和字 (32 位)DMA_CCR 寄存器的 PSIZE[1:0] 位的值。
DMA_MemoryDataSize存储器数据宽度,可选字节 (8 位)、半字 (16 位) 和字 (32 位),DMA_CCR 寄存器的 MSIZE[1:0] 位的值。
DMA_ModeDMA 传输模式选择,可选一次传输或者循环传输,它设定 DMA_CCR 寄存器的CIRC 位的值。
DMA_Priority软件设置通道的优先级,有 4 个可选优先级分别为非常高、高、中和低,DMA_CCR 寄存器的 PL[1:0] 位的值。
DMA_M2M存储器到存储器模式,使用存储器到存储器时用到设定 DMA_CCR 的位 14MEN2MEN 即可启动存储器到存储器模式。

配置DMA TO P(外设)代码例子

void USARTx_DMA_Config(void)
{
  DMA_InitTypeDef DMA_InitStructure;
  
  // 启用 DMA1 时钟
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  
  // 设置 DMA_InitStructure 结构体的各项参数
  DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS; // USART 数据寄存器地址
  
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuff; // 发送缓冲区的内存地址
  
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // 数据传输方向为从外设到存储器
  
  DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE; // 发送缓冲区大小
  
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 禁止外设地址增量
  
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 允许存储器地址增量
  
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据大小为字节
  
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 存储器数据大小为字节
  
  DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 设置 DMA 优先级为高
  
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // DMA 模式为正常模式
  
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 禁止存储器到存储器传输
  
  // 使用配置好的 DMA_InitStructure 结构体初始化 USART 的 DMA 通道
  DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);
  
  // 启动 USART 的 DMA 传输
  DMA_Cmd(USART_TX_DMA_CHANNEL, ENABLE);
}






文章来源:https://blog.csdn.net/elderingezez/article/details/135139917
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。