【嵌入式系统开发14】采用串口DMA方式向上位机连续发送数据的实例解析

本文目的是主要介绍通过STM32F103C8T6采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据。


前言

※ 在stm32CubeMX环境配置下,去实现串口中断通信,可参考博主的博客:https://blog.csdn.net/qq_52199251/article/details/127469666
本文主要讲解采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据。


(一)需求分析

采用STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据。
所需工具:

1、芯片: STM32F407ZET6/ STM32F103ZET6
2、STM32CubeMx软件
3、IDE: MDK-Keil软件
4、STM32F1xx/STM32F4xxHAL库


(二)DMA详解

1.什么是DMA?

DMA,全称Direct Memory Access,即直接存储器访问。
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
● 我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,
● CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,是不是能够更好的利用CPU的资源呢?
● 因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理。
在这里插入图片描述
DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。

2.DMA定义?

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

3.DMA传输方式

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

外设到内存
内存到外设
内存到内存
外设到外设

4.DMA传输参数

● 我们知道,数据传输,首先需要的是1 数据的源地址 2 数据传输位置的目标地址 ,3 传递数据多少的数据传输量 ,4 进行多少次传输的传输模式 DMA所需要的核心参数,便是这四个。
● 当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,当剩余传输数据量为0时 达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式当到达传输终点时会重新启动DMA传输。 
● 也就是说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。  
在这里插入图片描述

5.DMA的主要特征

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

序号特征
A在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推)
B独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐;支持循环的缓冲器管理
C每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求
D存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输
E闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标
F可编程的数据传输数目:最大为65535

6.STM32少个DMA资源?

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

6.1DMA1 controller

● 从外设(TIMx[x=1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x=1、2]和USARTx[x=1、2、3])产生的7个DMA请求,通过逻辑或输入到DMA1控制器 其中每个通道都对应着具体的外设:
在这里插入图片描述
在这里插入图片描述

6.2DMA2 controller

● 从外设(TIMx[5、6、7、8]、ADC3、SPI/I2S3、UART4、DAC通道1、2和SDIO)产生的5个请求,经逻辑或输入到DMA2控制器,其中每个通道都对应着具体的外设:
在这里插入图片描述
在这里插入图片描述

6.3DMA工作系统

在这里插入图片描述
● 上方的框图,我们可以看到STM32内核,存储器,外设及DMA的连接,这些硬件最终通过各种各样的线连接到总线矩阵中,硬件结构之间的数据转移都经过总线矩阵的协调,使各个外设和谐的使用总线来传输数据。
※ 总之,每次DMA传送由3个操作组成:

A.从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元;
B.存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元;
C.执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目。

7.DMA传输方式

方法1:DMA_Mode_Normal,正常模式,
当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次
方法2:DMA_Mode_Circular ,循环传输模式
当传输结束时,硬件自动会将传输数据量寄存器进行重装,进行下一轮的数据传输。 也就是多次传输模式
仲裁器
在这里插入图片描述
仲裁器的作用是确定各个DMA传输的优先级
仲裁器根据通道请求的优先级来启动外设/存储器的访问。
优先权管理分2个阶段:
软件:每个通道的优先权可以在DMA_CCRx寄存器中设置,有4个等级:

最高优先级
高优先级
中等优先级
低优先级;

7.1指针递增模式

根据 DMA_SxCR 寄存器中 PINC 和 MINC 位的状态,外设和存储器指针在每次传输后可以自动向后递增或保持常量。当设置为增量模式时,下一个要传输的地址将是前一个地址加上增量值。
● 通过单个寄存器访问外设源或目标数据时,禁止递增模式十分有用。
● 如果使能了递增模式,则根据在 DMA_SxCR 寄存器 PSIZE 或 MSIZE 位中编程的数据宽度,下一次传输的地址将是前一次传输的地址递增 1个数据宽度、2个数据宽度或 4个数据宽度。

7.2存储器到存储器模式

DMA通道的操作可以在没有外设请求的情况下进行,这种操作就是存储器到存储器模式。
● 当设置了DMA_CCRx寄存器中的MEM2MEM位之后,在软件设置了DMA_CCRx寄存器中的EN位启动DMA通道时,DMA传输将马上开始。当DMA_CNDTRx寄存器变为0时,DMA传输结束。存储器到存储器模式不能与循环模式同时使用。
● 这里要注意仅 DMA2 的外设接口可以访问存储器,所以仅 DMA2 控制器支持存储器到存储器的传输,DMA1 不支持。
存储器到存储器模式不能与循环模式同时使用。

8.DMA中断

● 每个DMA通道都可以在DMA传输过半、传输完成和传输错误时产生中断。为应用的灵活性考虑,通过设置寄存器的不同位来打开这些中断。
在这里插入图片描述
● 使没开启,我们也可以通过查询这些位来获得当前 DMA 传输的状态。这里我们常用的是 TCIFx位,即数据流 x 的 DMA 传输完成与否标志。

9.DMA库函数配置过程

1、使能DMA时钟:RCC_AHBPeriphClockCmd();
2、初始化DMA通道:DMA_Init();
//设置通道;传输地址;传输方向;传输数据的数目;传输数据宽度;传输模式;优先级;是否开启存储器到存储器。
3、使能外设DMA;
4、使能DMA通道传输;
5、查询DMA传输状态。

※ 下面我们将介绍CubeMx 如何创建DMA。
在这里插入图片描述


(三)工程创建

1.DMA工程新创

● 点击ACCESS TO MCU SELECTOR在这里插入图片描述
● 找到自己所用的芯片型号,并进行建立。
在这里插入图片描述

2.RCC配置

在这里插入图片描述
● 发现此时芯片高亮。
在这里插入图片描述

3.USART1设置

●设置串口USART1,同时可查看波特率等设置是否正确:
在这里插入图片描述
在这里插入图片描述
● 点击确定
在这里插入图片描述
在这里插入图片描述

4.DMA设置

在这里插入图片描述
● 分别点击两个通道,查看模式设置是否为Normal,右侧Memory是否选中:
在这里插入图片描述
在这里插入图片描述

5.时钟设置

在这里插入图片描述

6.最后生成项目即可

在这里插入图片描述
在这里插入图片描述


(四)Keil编译程序

1.代码编写

● 用keil打开刚刚在CubeMX生成的项目文件。
在这里插入图片描述

2.代码编写

● 在main.c文件中补充代码。

	uint8_t Senbuff[] = "Hello world!";  //定义数据发送数组

在这里插入图片描述
● 在while循环中添加代码。

  HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
  HAL_Delay(1000);

在这里插入图片描述

3.编译文件

在这里插入图片描述
● 发现没有报错


(五)烧录实现

1.打开FlyMcu

在这里插入图片描述

2.串口助手实现

● 最终实现效果如下(添加换行符,便于观看):

视频


(六)总结

本文介绍了如何在嵌入式系中通过STM32F103C8T6采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据。前路漫漫亦灿灿,关关难过关关过!
寄语:鲜花与爱围绕在身旁
   无需在意闲言碎语
   去追求远方、玫瑰与诗!
   去做想做的事,去爱该爱的人,去清澈自己那一刀不剪的灵魂!!!!


(七)参考文献

[1]https://blog.csdn.net/as480133937/article/details/104827639/
[2]https://blog.csdn.net/qq_46467126/article/details/121076618

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值