关于串口通信协议的解析,该怎么解决

关于串口通信协议的解析,该怎么解决

串口通信协议
    由于本系统采用非规范式输入,导致一帧数据可能分成几次接收。为了能够判断一帧数据是否接收完整,本系统制定了一套特殊的串口通信协议,如附图所示。

(转)嵌入式Linux下的串口通信程序设计

附图  通信协议定义

    在本系统的串口通信协议中,一帧数据包括了帧头、数据长度、数据内容和数据校验这四部分。数据长度、数据内容和数据校验为有效数据区。帧头长度为两个字节,为0xaa、0xbb。当接收到相邻的两个字节为0xaa和0xbb数据时,认为一帧数据开始。数据长度为两个字节,是数据内容的字节数和数据校验的字节数之和。数据校验采用crc16的校验方式,对数据长度和数据内容进行校验,占两个字节。数据内容的最大字节数为65533,即一帧数据最多可以传送65533个字节的数据。
    待发送的数据不可避免地会出现相邻的两个字节为0xaa和0xbb的情况,如不对此中情况进行处理即发送数据,则一帧数据会被误判为两帧。针对这一问题,本系统提出了一种行之有效的解决方法。数据长度、数据内容以及数据校验这三部分数据中一旦出现0xaa,则重复一次0xaa。重复的0xaa不计入数据长度也不进行数据校验。
    接收数据时进行逆向操作。首先根据接收到的两个字节判断是否为帧头,如果是则代表一帧数据开始,继续接收余下的数据,否则循环检测。在接收数据时根据数据长度判断一帧数据是否接收完毕,接收完一帧数据后进行crc校验,校验正确则进行数据处理,否则丢弃这帧数据。在有效数据区内如果出现两个相邻字节为0xaa的数据,则只取其中的一个字节。


通常是这样处理的:
1.设置一个循环缓冲区.
2.串口接收的数据先存入循环缓冲区中,修改写指针位置.
3.设置协议对象,扫描循环缓冲区中的特征字节(一般是报头).找到了然后看循环缓冲区读写指针的距离是否够一帧数据.
4.如果够一帧长度,则从报头按照报文长度进行数据校验和解析.
5.修改读指针位置.
注意,你可以通过单独的线程处理串口数据写入循环缓冲区.


www.MyException.Cn   发布于:2012-01-22 22:38:43   浏览:184次
0
关于串口通信协议的解析
帧头标志 版本号 类别 帧头校验和 帧号
数据总长度 保留
数据CRC校验 数据区
  数据区

以上是一个帧的大致结构,在该协议中有以下七类帧,数据帧、压缩数据帧数据应答帧、检测帧、检测应答帧、系统错误帧、ABORT帧,这里面还有接受和发送的之间的同步,异步的问题。帧与帧之间的状态转化等等!

1.实现串口通信三种方式:串口控件 ,串口类,api函数。用那种实现 要好点?

2.我的问题的 怎么将数据组织成一帧,接受怎么将帧解析出来?

------解决方案--------------------
1、API,灵活
2、定义结构,C字符串操作,#program pack(1)即可 
------解决方案--------------------
不用控件,自己用api来实现 
------解决方案--------------------
1.建议使用API或串口类都可以,控件的发布太麻烦
2.定义两个函数一个封装成帧一个拆帧,串口接受数据的时候判断,当发现接受完一帧就去拆帧解析数据就OK了 
------解决方案--------------------
可以用帧尾或帧的结束符判断是否接收完一帧的,接收完一帧,就进入拆帧函数,根据你的帧的类别进行拆帧 
------解决方案--------------------
在网上找一个串口类吧。很多的。
至少怎么解释数据,那是基础知识,你应该随便去找本C的基础书看,而不是跑这来问。

------解决方案--------------------
最终发往串口的是字节流。结构体定义与帧格式一致。发送时将结构体转成byte直接往串口发。收的时候策略时根据帧头来,读到帧头后,根据帧格式来得到帧长度。不足长度时,暂存起来等待下次接收(你不可能每次恰好接收一帧吧),下次接收时和暂存区域合并,再次判断帧长度直到足够完整一帧了(若超过完整一帧长,将下一个帧头后内容暂存),完整后开始解析。若数据量较大,建议另开一线程专门解析。线程同步用加锁的方式,取得完整帧加到解析线程缓冲区,解析线程从缓冲区读帧解析,注意线程同步,避免同时操作缓冲区引起异常。。。。。说了一大堆,明白? 
------解决方案--------------------
API和串口类都可以,
解析的话可以先读取了固定长度的部分,也就是数据区前面........然后校验帧头,读取数据区长度,把数据区读入。然后校验数据区............ 
------解决方案--------------------
重要的是接受处理!

每次接受的数据都存到buffer里,
然后根据串口协议从头开始找, 找到第一完整的帧, 解析, 清理buffer中这个帧的数据.

至于解析过程:
首先判断帧头, 不对扔, 找到帧头后根据长度和校验位取出一个完整的包, 如果长度不够, 等待下次数据来后重新解析.

如何处理不定长数据的接收

在处理串口通讯时,经常会遇到不定长数据的接收。由于通讯任务不同及编程要求的差异所以采用的方法也有所不同。本文就此问题进行探讨。不定长数据从数据格式上分,可分为有格式和无格式。

一、无格式不定长数据的接收
这种格式在实际串口通讯中用得不多,一般只用传送字符串数据。问题在于怎么判断接收结束。一般用时间延迟的方法解决。
A、对于非握手式通讯,可用一个定时器定时轮循接收,并假定每个轮循接收完成。用ONCOMM事件接收也可,只是不如定时器定时轮循接收简便。
B、对于握手方式通讯,可用直接轮循法提高接收的准确性。下面是实现此法的函数:

Function sComm(sCommand As String, comReceive As MSComm) As String
Dim nReceiveCount As Integer
If comReceive.PortOpen = False Then
comReceive.PortOpen = True
End If

comReceive.Output = sCommand

Do
nReceiveCount = comReceive.InBufferCount
sleep (2) 'API 函数,挂起当前进程一段时间
Loop Until comReceive.InBufferCount = nReceiveCount
If comReceive.PortOpen = True Then
sComm = comReceive.Input
End If
End Function
注:此函数参照了xth一文。
此法一般是能确保数据接收的正确,但由于WINDOWS是多任务操作系统,当有耗时的进程运行时会丢失数据。如果系统会出现这种情况,可增大函数sleep()的参数值。

二、不定长格式数据的接收
对于不定长数据接收最好的方法是制定通讯协议,比如定义开始字符和结束字符。由于单片机系统通讯一般不太复杂,没必要去制定一套象通用计算机间通讯的协议,而根据单片机系统的大小和性能要求制定通讯协议。实际上为便于交流、维护以及一致性,可制定一套可伸缩的通讯协议。定义了开始字符和结束字符就容易实现不定长格式数据通讯,但在实际通讯编程还是容易出现一些比较隐蔽的通讯错误。下面就常用方法分别进行分析。
A、定时器轮循法。
假定每个轮循期数据接收完毕,并在每个轮循期处理数据,由于有开始字符和结束字符很容易确定接收数据的完整性。好象合理设定轮循时间值就万无一失了,但被动接收数据时无论如何也找不合适的轮循时间值,因为启动定时器和数据到来基本不同步,这就会出现一次发送的数据被分在两个轮循期接收,所以被动接收数据时不能假定每个轮循期数据接收完毕。在接收到结束字符后才确定一次数据接收完毕就可解决此问题。
B、OnComm事件法。
方法和定时器轮循法基本相同,因为每次OnCommg事件也只能接收到一部分数据。在VB的在线帮助中这样注解“设置 Rthreshold 为 1,接收缓冲区收到每一个字符都会使 MSComm 控件产生 OnComm 事件。”。但实际上OnComm事件并不是每收到一个字符便触发一次 OnComm 事件。OnComm事件是在缓冲区收到几个甚至几十个字节数据后才被触发的。版主认为这是WINDOWS多任务使操作系统不能实时响应造成的。如果要在每次OnComm事件接收一个字符似乎可设INPUTLEN属性为1,但实际行不通。VB在线帮助中“有该属性在从输出格式为定长数据的机器读取数据时非常有用”的注解,好象在说对定长字符有效,但版主发现INPUTLEN设为16,接收16个字符定长数据时却被当作两次接收了,一次12个,一次4个。建议在OnComm事件中接收数据要定义通讯协议并检测数据的完整性。 对于不定长格式数据的接收程序员更喜欢定时器轮循法,也许OnComm事件不好控制吧。
对于不定长数据的接收,最佳方法可能是在OnComm事件中启动定时器轮循接收,并同时停止OnComm事件的触发,接收完毕后或超时开启OnComm事件。 


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值