**前言:**
最近在接手一个安排的时候,需要修改之前的一些代码的外设接口,然后发现之前有部分关于USART通过DMA收发数据的部分功能,修改移植的时候发现有些需要注意的事项,以及解释的,做一篇小笔记吧,博主使用的单片机是STM32f071。
USART有三种模式进行传输:轮询、中断、以及DMA。
轮询模式
CPU不断查询IO设备,如设备有请求则加以处理。例如CPU不断查询串口是否传输完成,如传输超过则返回超时错误。轮询方式会占用CPU处理时间,效率较低。
中断控制方式
当I/O操作完成时,输入输出设备控制器通过中断请求线向处理器发出中断信号,处理器收到中断信号之后,转到中断处理程序,对数据传送工作进行相应的处理。
直接内存存取技术(DMA)方式
所谓直接传送,即在内存与IO设备间传送一个数据块的过程中,不需要CPU的任何中间干涉,只需要CPU在过程开始时向设备发出“传送块数据”的命令,然后通过中断来得知过程是否结束和下次操作是否准备就绪。
· 如果没有多操作过,可以用STM32CubeMX进行快速配置哈,这是之前学习CubeMX时候看到教程,很精简,点击进入链接。
串口的基本配置大家可以看哈野火老哥的教程,很扎实很细致。
首先配置好需要用的usartx:
时钟配置,开启gpio、usart、dma时钟.
IO配置为需要的模式.**注意:**f0系类的MCU配置复用功能的时候需要配置GPIOx_AFR寄存器,此在数据手册查询到PD5 PD6引脚默认复用功能引脚便是USART2,所以此处便可以省略配置,但是其他时候大家配置的时候记得进行查询在进行配置.
数据手册查询位置
此处为stm32f0开发手册GPIO寄存器配置查询
usart2外设配置
利用DMA通道发送接收串口时候,收发是分离的。
DMA的发送有几个步骤.
1.在数据发送缓冲区内放好要发送的数据,说明:此数据缓冲区的首地址必须要在DMA初始化的时候写入到DMA配置中去。
2. 将数据缓冲区内要发送的数据字节数赋值给发送DMA通道,(串口发送DMA和串口接收DAM不是同一个DMA通道)
3.开启DMA,一旦开启,则DMA开始发送数据,说明一下:在KEIL调试好的时候,DMA和调试是不同步的,即不管Keil 是什么状态,DMA总是发送数据。
3. 等待发送完成标志位,即下面的终端服务函数中的第3点设置的标志位。或者根据自己的实际情况来定,是否要一直等待这个标志位,也可以通过状态机的方式来循环查询也可以。或者其他方式判断数据发送完成.
DMA的接收步骤
串口接收DMA在初始化的时候就处于开启状态,一直等待数据的到来,在软件上无需做任何事情,只要在初始化配置的时候设置好配置就可以了。
判断数据数据接收完成:
这里判断接收完成是通过串口空闲中断的方式实现,即当串口数据流停止后,就会产生IDLE中断。这个中断里面做如下几件事:
1.关闭串口接收DMA通道,2点原因:1>.防止后面又有数据接收到,产生干扰。2>.便于DMA的重新配置赋值,下面第4点。
2. 清除DMA 所有标志位
3. 从DMA寄存器中获取接收到的数据字节数
4. 重新设置DMA下次要接收的数据字节数,注意,这里是给DMA寄存器重新设置接收的计数值,这个数量只能大于或者等于可能接收的字节数,否则当DMA接收计数器递减到0的时候,又会重载这个计数值,重新循环递减计数,所以接收缓冲区的数据则会被覆盖丢失。
5. 开启DMA通道,等待下一次的数据接收,注意,对DMA的相关寄存器配置写入,如第4条的写入计数值,必须要在关闭DMA的条件进行,否则操作无效。
说明一下,STM32的IDLE的中断在串口无数据接收的情况下,是不会一直产生的,产生的条件是这样的,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一断接收的数据断流,没有接收到数据,即产生IDLE中断。
此处文字是摘录别人的文字,大家可以看哈别人的文章,可以更好的学习一哈.附上链接.
虽然其他人写的很详细,但是博主用的使用是DMA移植发送形式,并没有在DMA通道的专用中断函数发送.
MCU中DMA有5个通道的,有7个通道的,博主使用的MCU是七个通道的,我们需要从stm32开发手册进行查询并配置对应的通道,这个很重要,记得,因为其他的配置都很常规,在这里配置的时候需要注意,因为配置一旦出错,就很容易出现hardfault.
串口接收DMA在初始化的时候就处于开启状态,一直等待数据的到来,在软件上无需做任何事情,只要在初始化配置的时候设置好配置就可以了。
判断数据数据接收完成:
这里判断接收完成是通过串口空闲中断的方式实现,即当串口数据流停止后,就会产生IDLE中断。这个中断里面做如下几件事:
关闭串口接收DMA通道,2点原因:1.防止后面又有数据接收到,产生干扰。2.便于DMA的重新配置赋值,下面第4点。
清除DMA 所有标志位
从DMA寄存器中获取接收到的数据字节数
重新设置DMA下次要接收的数据字节数,注意,这里是给DMA寄存器重新设置接收的计数值,这个数量只能大于或者等于可能接收的字节数,否则当DMA接收计数器递减到0的时候,又会重载这个计数值,重新循环递减计数,所以接收缓冲区的数据则会被覆盖丢失。
开启DMA通道,等待下一次的数据接收,注意,对DMA的相关寄存器配置写入,如第4条的写入计数值,必须要在关闭DMA的条件进行,否则操作无效。
说明一下,STM32的IDLE的中断在串口无数据接收的情况下,是不会一直产生的,产生的条件是这样的,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一断接收的数据断流,没有接收到数据,即产生IDLE中断。
DMA处查询usart2_通道为ch4,或者可以通过Remap到ch7进行发送数据.
由于数据发送的时候,尚未发送完成就执行完函数,所以加上发送完成标志完成判断,然后再清除掉标志.
DMA通道配置函数,配置之后就可以使用此函数了.
主函数调用
串口打印显示
但是Remap请慎用,有些MCU是没有此项功能的.博主最早之前就是想用Remap,没有主要此处,所以造成了发送一直显示只能发送第一个byte.
示范一个错误案例:没有查询是否可以DMA Remap就直接进行Remap
**结语:**大家写的时候一定多多注意,希望可以帮到大家,写的比较匆忙,好多知识点就不写了,CSDN等等大家都总结的很详细.