STM32数据搬运工-DMA讲解以及实例分析

STM32-DMA工作原理

DMA简介

DMA的概念

DMA,全称为:Direct Memory Access,即直接存储器访问。DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。

STM32F4-DMA功能框图分析

  • ①外设通道
  • ②数据流仲裁
  • ③数据FIFO
  • ④存储器端口
  • ⑤外设端口

1-外设通道

DMA外设通道

        STM32F4xx 系列资源丰富,具有两个 DMA 控制器,同时外设繁多,为实现正常传输,DMA需要通道选择控制。每个 DMA控制器具有 8个数据流,每个数据流对应 8个外设请求。

        外设通道选择要解决的主要问题是决定哪一个外设作为该数据流的源地址或者目标地址。

注:DMA控制器会通过 DMA数据流 x 配置寄存器 DMA_SxCR的CHSEL[2:0]位选择对应的通道作为该数据流的目标外设。

2-数据流仲裁

DMA外设通道

        一个 DMA控制器对应 8个数据流,数据流包含要传输数据的源地址、目标地址、数据长度等等信息。如果我们需要同时使用同一个 DMA 控制器(DMA1 或 DMA2)多个外设请求时,那必然需要同时使用多个数据流,那究竟哪一个数据流具有优先传输的权利呢?这就需要仲裁器来管理判断了

数据流传输优先级配置

1.配置 DMA_SxCR寄存器 PL[1:0]位,可以设置为非常高、高、中和低四个级别

2.如果两个或以上数据流软件设置优先级一样,则他们优先级取决于数据流编号,编号越低越具有优先权

3-数据FIFO

每个数据流都有一个独立的 4 字 FIFO(先进先出存储器缓冲区)。DMA传输具有 FIFO模式和直接模式。

直接模式

        每个 DMA 请求会立即启动对存储器的传输。当在直接模式(禁止FIFO)下将DMA请求配置为以存储器到外设模式传输数据时,DMA仅会将一个数据从存储器预加载到内部FIFO,从而确保一旦外设触发 DMA 请求时则立即传输数据。

FIFO模式

        可通过控制寄存器 DMA_SxFCR 的 FTH[1:0]位来设置FIFO阈值级别为 FIFO 大小的 1/4、1/2 或 3/4。如果数据存储量达到阈值级别时,FIFO 内容将传输到目标中。

4、5-存储器端口和外设端口

DMA 控制器提供两个 AHB主端口:AHB存储器端口(用于连接存储器)和 AHB外设端口(用于连接外设)。

但是,要执行存储器到存储器的传输,AHB外设端口 必须也能访问存储器。

所以 DMA1不能实现存储器到存储器传输。

STM32F4-DMA传输

DMA传输模式

        DMA1只有外设到存储器和存储器到外设两种模式,DMA2除前面两种外还支持存储器到存储器的传输模式。模式选择可以通过DMA_SxCR 寄存器的 DIR[1:0]位控制

DMA传输的源、目的、长度

DMA_SxPAR寄存器: 设置外设寄存器地址

DMA_SxM0AR寄存器:设置存储器地址

DMA_SxCR 寄存器:DIR[1:0]位配置数据的传输方向

DMA_CNDTRx 寄存器:写入需要传输的数据量,(0到65535)

DMA_SxCR 寄存器中的 PSIZE和 MSIZE位:设置源和目的的数据宽度,两边的位宽尽量保持一致

 

DMA增量设置

 根据设置 DMA_SxCR 寄存器中 PINC 和 MINC 位的状态,外设和存储器指针在每次传输后可以自动向后递增或保持常量。

当设置为增量模式时,下一个要传输的地址将是前一个地址加上增量值,增量值取决与所选的数据宽度为 1 、2 或 4 。

DMA循环模式

 循环模式用于处理循环缓冲区和连续的数据传输 ( 如 ADC 的扫描模式 ) 。可以使用 DMA_SxCR寄存器中的 CIRC 位使能此特性。

当启动了循环模式,一组的数据传输完成时,计数寄存器将会自动地被恢复成配置该通道时设置的初值,DMA操作将会继续进行。

DMA单次传输和突发传输

DMA传输类型有单次(Single)传输和突发(Burst)传输。DMA 控制器可以产生单次传输或 4 个、8 个和 16个节拍的增量突发传输。

突发大小通过软件针对两个 AHB端口独立配置,配置时使用DMA_SxCR 寄存器中的MBURST[1:0] 和 PBURST[1:0] 位。

为确保数据一致性,形成突发的每一组传输都不可分割:在突发传输序列期间,AHB传输会锁定,并且AHB总线矩阵的仲裁器不解除对 DMA 主总线的授权。

STM32F4-DMA中断

对于每个 DMA 数据流,可在发生以下事件时产生中断:

●达到半传输

●传输完成

●传输错误

●FIFO错误(上溢、下溢或 FIFO 级别错误)

●直接模式错误

注:这些标志位都在中断状态寄存器DMA_xISR中设置

ADC_DMA多路采集实例

实验要求:

利用ADC采集电位器以及芯片内部温度传感器的数据,在main函数中启动ADC转换以及DMA传输,最后在DMA完成中断中打印采集到的数据

cubemx配置

ADC配置

定义要用到的变量

uint16_t i;
#define ADC1_CHANNEL_CNT 2 	//采样通道数
#define ADC1_CHANNEL_FRE 3	//单个通道采样次数,用来取平均值
uint16_t adc1_val_buf[ADC1_CHANNEL_CNT*ADC1_CHANNEL_FRE]; //传递给DMA存放多通道采样值的数组
uint32_t adc1_aver_val[ADC1_CHANNEL_CNT] = {0}; //计算多通道的平均采样值的过程数组
uint16_t value[ADC1_CHANNEL_CNT] = {0};//多通道的平均采样值的数组

主函数中代码

	if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adc1_val_buf, (ADC1_CHANNEL_CNT*ADC1_CHANNEL_FRE)) != HAL_OK)
  {
    /* Start Conversation Error */
    Error_Handler(); 
  }

  while (1)
  {
		
		for(i = 0; i < ADC1_CHANNEL_CNT; i++)
		{
			adc1_aver_val[i] = 0;
		}
		/* 在采样值数组中分别取出每个通道的采样值并求和 */
		for(i = 0; i < ADC1_CHANNEL_FRE; i++)
		{
			adc1_aver_val[0] +=  adc1_val_buf[i*ADC1_CHANNEL_CNT+0];
			adc1_aver_val[1] +=  adc1_val_buf[i*ADC1_CHANNEL_CNT+1];
		}
		/* 依次对每个通道采样值求平均值 */
		for(i = 0; i < ADC1_CHANNEL_CNT; i++)
		{
			value[i] = adc1_aver_val[i] / ADC1_CHANNEL_FRE;
		}
		printf("adc_value:%d, tem_value:%d\n",value[0], value[1]);
		
		HAL_Delay(1000);
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

实验现象

想要转换电压值和温度数值的可以自己加入公式进行转化

  • 30
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值