从软件的角度来看,所有的通信都是一串字节(叫做数据帧)的连续传输。软件需要采用适当的机制来保证接收端能够正确识别出一个完整的数据帧、能够检查接收到的数据帧是正确的、在传输发生错误时有合适的恢复机制。为此就需要定义一个合适的数据帧格式。
数据帧的提取
为了识别出一个完整的数据帧,基本上有两个机制:一是在软件上规定字节之间的间隔最大值,一旦两个字节间的间隔超过某个阈值,就认为一个数据帧结束;另一种机制不对字节间的间隔作规定,而是用特殊的字节来定义数据报的开始和结束,当收到该特殊字节时,就认为一个数据帧的传输已完成。采用第一种机制的,比如Modbus-RTU。就是规定了同一个数据帧的字节间隔不能大于1.5个字节的传输时间,一旦大于该间隔,则认为前一个帧的传输已经结束,或者出错。同时为了保证不同数据帧之间有足够的间隔,还规定了两个数据帧之间最少插入3.5个字节的空闲位。下图摘自Modbus协议,表示了一个正确的数据帧、错误的数据帧以及数据帧之间的间隔。同时在数据报中引入了CRC,用于检出数据帧层面的传输错误。
第二种机制需要选用一个特殊字节作为帧头帧尾(也可以给帧头帧尾选用不同的字节),比如说,选用0xFF作为帧头帧尾字节,也即发送端在每个数据帧的头尾都插入至少一个0xFF,接收端收到该字节就结束上一个帧的接收,同时从下一个非0xFF字节开始一个新的数据帧的接收。但该机制有一个问题,那就是所选的特殊字节(此处是0xFF)也可能是数据帧中的一个有效字节,如果不作特殊处理,接收端就可能把这个数据帧中的字节误认为是数据帧的结束标识,从而导致接收错误。因此,此处采取字节替换的特殊处理,以消除在数据帧的中间出现的特殊字节,以下是一个例子。
在此处,选0xFE作为字节替换的标识字节,将0xFF替换成0xFE 0x0F。由于0xFE是字节替换的标志,也成了一个特殊字符,同样需要进行替换。在上图中,将0xFE替换成0xFE 0x0E。
采用该机制时,发送端对数据帧中的所有0xFF,0xFE进行替换。在接收端则进行反向替换。如果在接收端的0xFE后面的字节收到非0x0F,0x0E的字符,说明发生了传输错误,丢弃已经接收的内容,重新搜索帧头字符开始一个新数据帧的接收。
数据帧的校验
考虑到串口通信有一定的误码率,无论是采用那种传输方式,必须有错误帧检出机制。通常选用的是CRC。一般用2个字节或4个字节。
串口驱动的实现
在嵌入式系统中,串口驱动的实现一般有两个途径:一个是通过串口的收发中断与串口控制器的Buffer直接交换数据;另一种是通过DMA,利用DMA与串口Buffer交互自动收发数据。
与串口控制器直接交互的方式,实现简单,既可以实时进行字节替换以节省内存,也可以方便设置字节间的定时器。但频繁打断CPU,对有一定BUFFER大小的串口,还可以利用BUFFER进行性能优化,而对一些只有一个字节或两个字节BUFFER的串口,就需要一个字节起一次中断,如果CPU负荷较重,很容易由于中断处理不及时而导致字节丢失,特别是在高波特率的情况。
利用DMA与串口控制器交互的方式,由于不能实时进行字节替换,需要在放入DMA之前完成字节替换,导致占用较大内存空间。另外对于字节间间隔敏感的传输策略,需要用另外的机制,比如PRS,去操作定时器。用DMA的另一个问题是在接收时无法实时确定帧尾(采用帧头帧尾模式时),一般只能采用定时器与DMA配合,用字节流的方式处理接收。
-
嵌入式系统
+关注
关注
41文章
3570浏览量
129250 -
异步串口通信
+关注
关注
0文章
1浏览量
1323
原文标题:嵌入式系统上的异步串口通信的实现
文章出处:【微信号:mcugeek,微信公众号:MCU开发加油站】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论