本篇主要实现的是用UART的接收中断接收数据,用DMA接收不定长的数据并发送回给电脑,接收信息控制LED灯的亮灭,成为点灯大师。
什么是中断(EXIT)
EXIT 外部中断/事件控制器,管理了控制器的20个中断/事件线。 每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI可以实现对每个中断/事件线进行单独配置, 可以单独配置为中断或者事件,以及触发事件的属性。
中断在单片机的运行是很常见的运用,至于什么是中断呢?
举个栗子,在我们认真学习的时候,好兄弟突然发信息来叫你打游戏,因为是好兄弟,你又不好意思拒绝,只好放下手中的学习,跑去和好兄弟打起了游戏。这就是中断事件,在单片机的正常运行中,会以微小的时间来查看中断是否被置标志位,这就像你时刻盯着女神是否发送有发信息给你,看到了信息就秒回,而单片机检查到了中断标志位的触发就会检查中断响应的优先级,来看先处理哪个,随后跑到对应的CallBack函数里面实现指定的内容,再跳出中断回归刚才的工作。
中断的应用
有很多,比如在串口接收数据时,单片机不知道串口什么时候有数据能接收,一直在while死循环里面查询就会影响到其他内容的正常运行,设置了串口接收数据的中断就可以完美解决工作的协作问题,在接收到数据就产生中断标志位,叫单片机到CallBack函数内部处理接收到的数据。
中断的嵌套
我们常常在大的项目中用到了多个中断函数,这时我们可以通过配置NVIC来配置中断事件的优先级来把一些中断进行嵌套,这样能够优先处理一些特定的事情,比如在串口接收到数据触发到中断时,正在回调函数内部处理着数据,突然有个更重要的中断事件触发,其中断优先级高于串口的接收,这时串口接收的中断正在处理的数据将会存储在一个寄存器中,然后跳到中断优先级高的回调函数内部来处理,处理完后返回刚刚在串口接收回调函数,在那个暂存寄存器中读回刚刚的值,再继续处理。
中断向量表
借用大佬画的中断流程图
首先是在输入线检测到特定事件,1,2,3,随后请求挂起寄存器,进入到中断控制器(NVIC)中查看中断的优先级来响应中断函数的实现顺序
什么是串口(UART)
串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,在单片机中,我们常用串口通信来调试一些功能是否正常,比如我们在使用Timer定时器计时时,我们要测试定时器是否准确可以使得定时器到达阈值产生中断通过串口发送出去,也可以每隔一段时间读取counter的值,利用串口发送给电脑检测。
串口的协议
功能引脚
TX: 发送数据输出引脚。
当USART_CR1寄存器的发送使能位TE置1时,启动数据发送,发送移位寄存器的数据会在TX引脚输出, 低位在前,高位在后。如果是同步模式SCLK也输出时钟信号。
一个字符帧发送需要三个部分:起始位+数据帧+停止位。起始位是一个位周期的低电平,位周期就是每一位占用的时间; 数据帧就是我们要发送的8位或9位数据,数据是从最低位开始传输的;停止位是一定时间周期的高电平。
RX: 接收数据输入引脚。
如果将USART_CR1寄存器的RE位置1,使能USART接收,使得接收器在RX线开始搜索起始位。 在确定到起始位后就根据RX线电平状态把数据存放在接收移位寄存器内。接收完成后就把接收移位寄存器数据移到RDR内, 并把USART_SR寄存器的RXNE位置1,同时如果USART_CR2寄存器的RXNEIE置1的话可以产生中断。
串口通讯的数据包由发送设备通过自身的TXD接口传输到接收设备的RXD接口。在串口通讯的协议层中, 规定了数据包的内容,它由启始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据
波特率
波特率(bandrate),指的是串口通信的速率,也就是串口通信时每秒钟可以传输多少个二进制位。所以两个通讯设备之间需要约定好波特率,即每个码元的长度,以便对信号进行解码。
通讯的起始和停止信号
串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一个逻辑0的数据位表示, 而数据包的停止信号可由0.5、1、1.5或2个逻辑1的数据位表示,只要双方约定一致即可。
数据校验
在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差, 可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、0校验(space)、1校验(mark)以及无校验(noparity)。
奇校验要求有效数据和校验位中“1”的个数为奇数,比如一个8位长的有效数据为:01101001,此时总共有4个“1”, 为达到奇校验效果,校验位为“1”,最后传输的数据将是8位的有效数据加上1位的校验位总共9位。
偶校验与奇校验要求刚好相反,要求帧数据和校验位中“1”的个数为偶数, 比如数据帧:11001010,此时数据帧“1”的个数为4个,所以偶校验位为“0”。
0校验是不管有效数据中的内容是什么,校验位总为“0”,1校验是校验位总为“1”。
串口的功能框图
有关串口所可能用到的中断
什么是DMA
DMA(Direct Memory Access)—直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用CPU, 即在传输数据的时候,CPU可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器。
在需要频繁搬运数据数据时,频繁地搬运会大量占用CPU导致CPU无法或执行其他任务效率低下,而且干的只是简单的搬运工作,这时CPU可以召唤自己的小弟DMA出来干活搬运,把数据搬运完后再叫CPU来处理数据(可以从外设搬运到内存中(ADC通道,DMA用在多通道的连续扫描可以极大地减轻CPU的压力),或者是把内存搬运到外设(数据的传输),亦或是存储器到存储器,在想要在FLASH上存储一些变量时可以用到)
如果外设要想通过DMA来传输数据,必须先给DMA控制器发送DMA请求,DMA收到请求信号之后,控制器会给外设一个应答信号, 当外设应答后且DMA控制器收到应答信号之后,就会启动DMA的传输,直到传输完毕。可以在传输完毕产生DMA的传输完毕中断,让CPU及时处理数据。
在使用DMA进行传输时需要注意 要传多少,单位是什么 以串口向电脑发送数据为例,要发送的数据很多, 每发送完一个,那么存储器的地址指针就应该加1,而串口数据寄存器只有一个, 那么外设的地址指针就固定不变。具体的数据指针的增量模式由实际情况决定。
DMA的结构框图
DMA有DMA1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道,不同的DMA控制器的通道对应着不同的外设请求
DMA请求映像表
代码实战配置
Cubemx配置流程图
首先配置GPIO来连接LED灯来看实验的现象
两个LED都配置成这个样子
在connectivity中串口1的配制,配置成异步模式,比特率用默认的115200即可,在修改比特率的同时记得把串口助手发送和接收的比特率修改一下,这里还配置了字长,有无校验位以及停止位长度
找到DMA的配制,运用默认的配置即可
这里是配置成DMA在RX接收引脚接收数据时,数据从外设转运到内存,在TX发送引脚,数据从内存转运到外设。数据大小都是八位(bit)
到NVIC的配置中允许DMA产生中断,目的是让DMA传输完成产生中断让单片机处理 接收到的数据
点到时钟树的配制 Clock Configuration
配置成最大速率即可,这里并没有要求
随后生成代码即可,这里我用的keil软件
首先我们在main函数中定义两个全局变量,一个用来接收,一个用来发送
随后我们找到UART接收的中断函数
这个是接收到数据的回调函数
在main函数中重新定义一遍,目的是在接收到数据时响应,并且启动DMA的转运
这里实现的是接收数据时点灯和灭灯的操作
进入函数内部发现它是一个弱定义函数(__weak)
我们直接把函数名复制到main.c文件中再定义一遍,在弱定义的概念中,如果有重复定义,则在新的没有若定义的函数才算实现,这个就是我们接收到数据的接收中断的回调函数
在传输完成的回调函数中实现功能
实现接收不定长数据并发送回电脑的任务
在UART接收完成回调函数中用DMA把数据转运回来
这里找到UART完全接收完成的函数(这个是判断接受标志位是否长期处于空状态)
在main函数中不用实现什么功能,如果需要加上别的功能可以添加,这里的实现已经在接收数据的回调函数中实现,并且在接受数据时,把接收到的数据发送回给计算机。
本篇主要实现的是用UART的接收中断接收数据,用DMA接收不定长的数据并发送回给电脑,接收信息控制LED灯的亮灭,成为点灯大师。谢谢你的观看,求点赞收藏转发。
标签:DMA,校验位,中断,收发,串口,接收,数据 From: https://blog.csdn.net/2301_80230872/article/details/139835413