Linux串口读取与解析
串口协议包的接收及解析处理对于串口接收问题前面之前有文章介绍过串口缓存机制的应用。当然这里不应用缓存机制也是完全可行的。这里我们讲解基于不带串口缓存机制的处理。对于串口接收我们最常用的方式就是在串口中断中接收数据。利用串口接收数据包信息大致分为下面三种情况:接收一帧数据,对帧数据进行处理(可以利用串口接收非空中断和串口空闲中断实现)中断中边接收边处理存储,并将有效数据存储起来,再对有效数据进行解析
对于串口接收问题前面之前有文章介绍过串口缓存机制的应用。当然这里不应用缓存机制也是完全可行的。这里我们讲解基于不带串口缓存机制的处理。对于串口接收我们最常用的方式就是在串口中断中接收数据。
利用串口接收数据包信息大致分为下面三种情况:
- 接收一帧数据,对帧数据进行处理(可以利用串口接收非空中断和串口空闲中断实现)
- 中断中边接收边处理存储,并将有效数据存储起来,再对有效数据进行解析。
- 将接收到的数据全部存入缓存,从缓存中提取数据并做处理。
1.UART连线图
S3C2440有3个独立通道的UART
2.数据传输流程
1.平时数据线处于“空闲”状态(1状态) 2.当要发送数据时,UART改变TxD数据线的状态(变为0状态),并维持1位的时间,这样接收方检测到开始位后,在等待1.5位的时间就开始一位一位的检测数据线的状态得到所传输的数据 3.UART一帧中可以有5,6,7或8位的数据,发送方一位一位的改变数据线的状态将它们发送出去。首先发送最低位 4.如果使用校验功能,UART在发送完数据位后,还要发送1个校验位。有两种校验方法:奇校验,偶校验——数据位连同校验位,“1”的数目等于奇数或偶数 5.最后,发送停止位。数据线恢复到“空闲”状态(1状态)。停止位的长度有3种:1位,1.5位,2位
正是由于这种机制,没有干扰的情况下,发送每个字节都能读到。
问题背景
大致为:有一个发送端周期性的往本机串口上发送数据,本机需要定时读取串口数据,解析,获取自己想要的信息。实际描述为:由于是做智能驾驶的,需要读取车辆速度,通过OBD设备读取并解析车辆速度,然后通过蓝牙发送给PC串口(也是通过一个蓝牙模块接收),PC端串口定时接收串口数据并解析。
在上述过程中,有一个问题需要注意:发送方是周期性的不停的发送数据,也就是说PC机串口一直有数据进来,最常见的是发送端频率比接收端频率高,即准备读取串口数据时总可以读取的数据,但也也导致了另一个问题,那就是怎么处理接收端串口缓冲,因为你每次的读取操作都必须要把当前串口缓冲区中数据全部读取出来,不能只读一部分,不然发送端一直有数据进来,而你每次都不读玩,就会造成缓冲区溢出。
串口的实质是什么
但凡接触过Linux系统知识或者了解计算机系统原理,那你一定通过一句话“在任何操作系统下,一切都是文件”,Linux系统就是这句话的最完美的实现,即在Linux系统下,你完全可以把所有东西当成是一个文件、即所有东西都可以按照“打开——设置——读写——关闭”的模式进行,同样,在Linux下串口也可以看成是一种文件(其实任何操作系统下都可以这样认为),你要读写串口数据,就必须先打开、设置串口,然后读写,读写完毕,就必须要关闭串口。
从串口缓冲区里读数据,其实和打开txt文件读数据一样,可以一次读几个字节,也可以全读出来。
(1)打开串口:
在ReadCarSpeed.cpp文件中,OpenCom()函数负责打开和设置串口,这里有一点需要啰嗦一下:myCom->setTimeout(50);延时设置函数,我这里设置的是50ms,对于这个延时,我的理解是本机串口的接收频率,注意这个接收频率是不同于你读取的频率的,这里的接收频率是本机串口缓冲区接收数据的延时,即没50ms就有一个数据进去接收缓冲区队列(要理解数据缓冲区实际就是一个队列,先进先出),而你读取的频率是你调用readAll()函数的频率,如我的读取频率就是主控程序的频率(大约为500ms),所以每次大约读取10个速度信息。
一、什么是缓冲区
缓冲区(buffer),它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区,显然缓冲区是具有一定大小的。
缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。
二、为什么要引入缓冲区
我们为什么要引入缓冲区呢?
高速设备与低速设备的不匹配,势必会让高速设备花时间等待低速设备,我们可以在这两者之间设立一个缓冲区。
缓冲区的作用:
1.可以解除两者的制约关系,数据可以直接送往缓冲区,高速设备不用再等待低速设备,提高了计算机的效率。例如:我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情。
2.可以减少数据的读写次数,如果每次数据只传输一点数据,就需要传送很多次,这样会浪费很多时间,因为开始读写与终止读写所需要的时间很长,如果将数据送往缓冲区,待缓冲区满后再进行传送会大大减少读写次数,这样就可以节省很多时间。例如:我们想将数据写入到磁盘中,不是立马将数据写到磁盘中,而是先输入缓冲区中,当缓冲区满了以后,再将数据写入到磁盘中,这样就可以减少磁盘的读写次数,不然磁盘很容易坏掉。
简单来说,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来存储数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。
小草手把手教你 LabVIEW 串口仪器控制——VISA 串口配置
串口有个缓冲区,存在计算机内存里,VISA 读取,就是从缓冲区读取数据,读完之后,读取的就不存在缓冲区里了。如果你没读取,那就一直在缓冲区里,直到缓冲区溢出。其实就好比一个水桶,写 VISA 是往水桶进水,读 VISA 是出水。你也可以想想队列的原理,差不多的。
UART (Universal Asynchronous Receiver/Transmitter,即通用异步收发器)串行通信是单片机最常用的一种通信技术,通常用于单片机和电脑之间以及单片机和单片机之间的通信。
11.1 串行通信的初步认识
当单片机 1 想给单片机 2 发送数据时,比如发送一个 0xE4 这个数据,用二进制形式表 示就是 0b11100100,在 UART 通信过程中,是低位先发,高位后发的原则,那么就让 TXD 首先拉低电平,持续一段时间,发送一位 0,然后继续拉低,再持续一段时间,又发送了一 位 0,然后拉高电平,持续一段时间,发了一位 1……一直到把 8 位二进制数字 0b11100100 全部发送完毕。这里就涉及到了一个问题,就是持续的这“一段时间”到底是多久?由此便引入了通信中的一个重要概念——波特率,也叫做比特率。
波特率就是发送二进制数据位的速率,习惯上用 baud 表示,即我们发送一位二进制数据 的持续时间=1/baud。在通信之前,单片机 1 和单片机 2 首先都要明确的约定好它们之间的通 信波特率,必须保持一致,收发双方才能正常实现通信,这一点大家一定要记清楚。
约定好速度后,我们还要考虑第二个问题,数据什么时候是起始,什么时候是结束呢? 不管是提前接收还是延迟接收,数据都会接收错误。在 UART 通信的时候,一个字节是 8 位, 规定当没有通信信号发生时,通信线路保持高电平,当要发送数据之前,先发一位 0 表示起 始位,然后发送 8 位数据位,数据位是先低后高的顺序,数据位发完后再发一位 1 表示停止 位。这样本来要发送一个字节的 8 位数据,而实际上我们一共发送了 10 位,多出来的两位 其中一位起始位,一位停止位。而接收方呢,原本一直保持的高电平,一旦检测到了一位低 电平,那就知道了要开始准备接收数据了,接收到 8 位数据位后,然后检测到停止位,再准 备下一个数据的接收。我们图示看一下,如图 11-2 所示。
图 11-2 串口数据发送示意图,实际上是一个时域示意图,就是信号随着时间变化的对应 关系。比如在单片机的发送引脚上,左边的是先发生的,右边的是后发生的,数据位的切换 时间就是波特率分之一秒,如果能够理解时域的概念,后边很多通信的时序图就很容易理解 了。
11.4 IO 口模拟 UART 串口通信
这一节对理解串口的高低电平发送与接收特别有帮助,具体看 第11章 UART 串口通信(手把手教你学51单片机pdf部分)
11.5.2 UART 模块介绍IO 口模拟串口通信,让大家了解了串口通信的本质,但是我们的单片机程序却需要不停 的检测扫描单片机 IO 口收到的数据,大量占用了单片机的运行时间。这时候就会有聪明人 想了,其实我们并不是很关心通信的过程,我们只需要一个通信的结果,最终得到接收到的 数据就行了。这样我们可以在单片机内部做一个硬件模块,让它自动接收数据,接收完了, 通知我们一下就可以了,我们的 51 单片机内部就存在这样一个 UART 模块,要正确使用它, 当然还得先把对应的特殊功能寄存器配置好。
更多推荐
所有评论(0)