使用串口进行数据的收发在嵌入式产品中是很常用的一种通信方式,因为串口的简单使用,很容易就被选为产品中数据交互的通信手段。基于串口进行开发的功能有很多,比如同类/不同类产品之间的通信,RS485通信,RS232通信方式,实现串口命令行终端用于调试等等的。虽然应用的场景有所不同,但是都会涉及到一个共同的问题:怎么确保收到一帧完整的数据?使用过串口的朋友都会知道,串口收发数据都是按照串行的方式进行的,数据是按照bit的方式一位一位进行发送的。而且发送数据方想要发送的数据长度不一定是固定的,有可能长有可能短,这就会涉及到怎么识别一帧数据已经被接收完了的问题。1. 串口数据的发送和接收方式串口的接收和发送在两个设备之间是按照bit的方式进行通信的,参见下面的示意图: forum.jpg 数据从一方按照bit的方式1bit进行传输,另外一方也是按照1bit的方式进行接收,直到接收完1Byte数据为止,然后再接收下一个1Byte的数据。这里还需要考虑另外一个问题,就是一个字节数据之间的时间间隔。简单而言就是接收第一个字节和第二个字节之间的时间间隔,这个时间间隔在大数据量的情况下是要考虑的,数据量少的情况下可以忽略不计。参见下面的示意图: forum.jpg   2. 串口接收不定长数据的实现方式对于串口接收数据,最需要考虑的是怎么确保收到一帧完整的数据。因为在很多场景下都会遇到的一个问题,就是串口发送的数据是长度不固定的,有时候长有时候短,这就给接收数据和识别数据是有效的带来了一些难度。下面根据我个人在项目中使用串口进行数据接收的时候,针对不定长数据的处理方式进行简单的分享。2.1、固定格式帧的不定长数据接收这种数据一般都是应用在某些产品之间的通信协议,有固定的数据帧格式,比如有固定的帧头和帧尾用于确定数据帧,如下的固定帧头尾的各式:#defineCMD_HEAD 0XAA5A//帧头#defineCMD_TAIL 0XFDFCFF//帧尾这种方式接收数据的时候就比较简单,可以在接收数据的时候进行判断,遇到帧头的时候就开始保存数据,在识别到帧尾之后完成一帧数据的接收,再用其他的手段将这帧数据进行解析。或者也可以先将所有的数据先接收起来,比如用一个数据缓冲区先保存所有的数据,然后再由应用程序去解析。因为这种数据是有固定格式的,所以解析的时候也很方便,只要按照数据帧的格式进行判别,如果符合格式的定义,就可以认为是一帧完整的数据,否者就丢弃。 2.2、格式不固定长度也不固定的数据的接收这种数据的接收就相对比较麻烦一点,因为格式不是固定的,没有明确的标识数据帧开头和结尾的特征数据,所以这种方式的数据接收往往考虑的是数据帧之间的间隔,根据两帧数据之间的间隔进行判断,设置一个时间间隔,如果符合这个时间间隔就认为数据的接收是有效的,否者认为无效。这种方式需要用到一个计时,并设定一个帧之间的时间间隔,从接收到数据就开始计时,然后每收一个数据就重置这个计时,直到计时到达设置的帧间隔时间没有再接收到数据则认为数据已经接收完成。这个帧的时间间隔可以任意设置,一般我们考虑是3.5个字符的时间。如果3.5个字符的时间没有再收到数据,就认为数据的传输已经完成,接收端已经完成了数据的接收。操作的步骤大致如下:1)使用一个计时功能2)接收到数据时启动计时,然后之后每收到一个数据重置一次这个计时3)在没有收到数据之后,计时达到了设定的值,接收就算结束了,处理接收到数据,并关闭计时功能。4)下一帧的数据接收,重复上面的步骤。 2.3、串口的空闲中断这种方式是使用的串口的空闲中断功能,大概原理是在串口配置开启了空闲中断时,如果接收到数据之后就会启动这个串口的空闲状态检测,在一段时间串口不在收到数据就会触发串口的空闲中断,告知完成一次数据的接收。这种方式显然更好,不用额外再实现空闲检测功能,只要在串口触发中断并是空闲中断的时候,就知道数据完成了接收。但是,这个功能不是所有的MCU都具备,一般都是在一些高端一点的MCU中才有,低端一些的MCU估计都是没有空闲中断的。 当然,方式还有很多中,这里只是简单的列举了本人使用过的几种方式,具体使用什么样的方式还要根据实际的项目情况需要而定吧!