STM32采用串口DMA方式实现发送数据

  • Post author:
  • Post category:其他




一、实验工具

软件:STM32CubeMX:6.6.1

Keil 5.31

mcuisp

硬件:STM32F103C8T6



二、DMA介绍

DMA,全称Direct Memory Access,即直接存储器访问。

DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。

我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据。因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理。

在这里插入图片描述

DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。


DMA定义:


DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。


DMA传输方式:


DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:

—-外设到内存

—-内存到外设

—-内存到内存

—-外设到外设


DMA传输参数:


我们知道,数据传输,首先需要的是:1.数据的源地址 2 .数据传输位置的目标地址 3 .传递数据多少的数据传输量 4 .进行多少次传输的传输模式 DMA所需要的核心参数,便是这四个。

当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,当剩余传输数据量为0时 达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式 当到达传输终点时会重新启动DMA传输。

也就是说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。


DMA的主要特征:


每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置。

—-在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推)

—-独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐;

—-支持循环的缓冲器管理;

—-每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求;

—-存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输;

—-闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标;

—-可编程的数据传输数目:最大为65535。


STM32的DMA资源:


对于大容量的STM32芯片有2个DMA控制器 两个DMA控制器,DMA1有7个通道,DMA2有5个通道。每个通道都可以配置一些外设的地址。


DMA工作系统框图:


在这里插入图片描述

上方的框图,我们可以看到STM32内核,存储器,外设及DMA的连接,这些硬件最终通过各种各样的线连接到总线矩阵中,硬件结构之间的数据转移都经过总线矩阵的协调,使各个外设和谐的使用总线来传输数据。


DMA传输步骤:


—-从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元;

—-存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元;

—-执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目。


DMA传输方式:


方法1:DMA_Mode_Normal,正常模式,

当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次

方法2:DMA_Mode_Circular ,循环传输模式

当传输结束时,硬件自动会将传输数据量寄存器进行重装,进行下一轮的数据传输。 也就是多次传输模式

在这里插入图片描述

仲裁器的作用是确定各个DMA传输的优先级

仲裁器根据通道请求的优先级来启动外设/存储器的访问。

优先权管理分2个阶段:

软件:每个通道的优先权可以在DMA_CCRx寄存器中设置,有4个等级:最高优先级、高优先级、中等优先级、低优先级

硬件:如果2个请求有相同的软件优先级,则较低编号的通道比较高编号的通道有较高的优先权。比如:如果软件优先级相同,通道2优先于通道4。


指针递增模式:


根据 DMA_SxCR 寄存器中 PINC 和 MINC 位的状态,外设和存储器指针在每次传输后可以自动向后递增或保持常量。当设置为增量模式时,下一个要传输的地址将是前一个地址加上增量值

通过单个寄存器访问外设源或目标数据时,禁止递增模式十分有用。

如果使能了递增模式,则根据在 DMA_SxCR 寄存器 PSIZE 或 MSIZE 位中编程的数据宽度,下一次传输的地址将是前一次传输的地址递增 1个数据宽度、2个数据宽度或 4个数据宽度。


存储器到存储器模式:


DMA通道的操作可以在没有外设请求的情况下进行,这种操作就是存储器到存储器模式。

当设置了DMA_CCRx寄存器中的MEM2MEM位之后,在软件设置了DMA_CCRx寄存器中的EN位启动DMA通道时,DMA传输将马上开始。当DMA_CNDTRx寄存器变为0时,DMA传输结束。存储器到存储器模式不能与循环模式同时使用。

这里要注意仅 DMA2 的外设接口可以访问存储器,所以仅 DMA2 控制器支持存储器到存储器的传输,DMA1 不支持。

存储器到存储器模式不能与循环模式同时使用。


DMA库函数配置过程:


1.使能DMA时钟:RCC_AHBPeriphClockCmd();

2.初始化DMA通道:DMA_Init();

//设置通道;传输地址;传输方向;传输数据的数目;传输数据宽度;传输模式;优先级;是否开启存储器到存储器。

3.使能外设DMA;

4.使能DMA通道传输;

5.查询DMA传输状态。



三、配置工程



1.新建工程

在这里插入图片描述



2.引脚配置

在这里插入图片描述



3.设置RCC

在这里插入图片描述



4.设置串口

在这里插入图片描述

  • 点击USATR1
  • 设置MODE为异步通信(Asynchronous)
  • 基础参数:波特率为115200 Bits/s。传输数据长度为8 Bit。奇偶检验无,停止位1 接收和发送都使能
  • GPIO引脚自动设置 USART1_RX/USART_TX
  • NVIC Settings 一栏使能接收中断

    在这里插入图片描述



5.DMA设置

在这里插入图片描述

  • 点击DMASettings 点击 Add 添加通道
  • 选择USART_RX USART_TX 传输速率设置为中速
  • DMA传输模式为正常模式
  • DMA内存地址自增,每次增加一个Byte(字节)


    DMA基础设置


    右侧点击System Core 点击DMA

    在这里插入图片描述

    DMA Request : DMA传输的对应外设

    注意: 如果你是在DMA设置界面添加DMA 而没有开启对应外设的话 ,默认为MENTOMEN

    Channel DMA传输通道设置:

    DMA1 : DMA1 Channel 0~DMA1 Channel 7

    DMA2: DMA2 Channel 1~DMA1 Channel 5

    Dirction : DMA传输方向

    四种传输方向:
  • 外设到内存 Peripheral To Memory
  • 内存到外设 Memory To Peripheral
  • 内存到内存 Memory To Memory
  • 外设到外设 Peripheral To Peripheral

    Priority: 传输速度
  • 最高优先级 Very Hight
  • 高优先级 Hight
  • 中等优先级 Medium
  • 低优先级 Low

    2DMA传输模式

    在这里插入图片描述

    Normal:正常模式

    当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次

    Circular: 循环模式

    传输完成后又重新开始继续传输,不断循环永不停止

    3DMA指针递增设置

    在这里插入图片描述

    Increment Address:地址指针递增

    左侧Src Memory 表示外设地址寄存器

    功能:设置传输数据的时候外设地址是不变还是递增。如果设置 为递增,那么下一次传输的时候地址加 Data Width个字节。

    右侧Dst Memory 表示内存地址寄存器

    功能:设置传输数据时候内存地址是否递增。如果设置 为递增,那么下一次传输的时候地址加 Data Width个字节。

    这个Src Memory一样,只不过针对的是内存。



6.时钟源设置

在这里插入图片描述



7.项目文件设置

在这里插入图片描述

在这里插入图片描述



8.创建代码

在这里插入图片描述



四、Keil中修改代码



1.在main.c中添加:

 /* USER CODE BEGIN Init */
	uint8_t Senbuff[] = "\r\n**** Serial Output Message by DMA ***\r\n   UART DMA Test \r\n   Zxiaoxuan";  //定义数据发送数组
  /* USER CODE END Init */



2.将main.c 的while修改为:

  while (1)
  {
    /* USER CODE END WHILE */
			HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
	        HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }



五、烧录程序

在这里插入图片描述



六、实验结果

VID_20221018_204905



七、总结

介绍关于DMA的基础知识,实现了串口DMA发送数据。



八、参考资料


【STM32】HAL库 STM32CubeMX教程十一—DMA (串口DMA发送接收)



STM32 HAL CubeMX 串口IDLE接收空闲中断+DMA



【STM32】系统时钟RCC详解(超详细,超全面)



版权声明:本文为m0_59066136原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。