在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
通信协议串行通信接口(如RS232、RS485等)作为计算机与单片机交互数据的主要接口,广泛用于各类仪器仪表、工业监测及自动控制领域中。 通信协议是需要通信的双方所达成的一种约定,它对包括数据格式、同步方式、传送速度、传送步骤、检纠错方式以及控制字符定义等问题作出统一规定,在双方的通信中必须共同遵守。在实际应用系统中,如果缺少一个严格、合理、规范的串口通信协议,将无法保证数据传输的正确性及通信的可靠性。 因此,需要提出一种基于状态机串口通信协议的设计方法:通过合理地设置数据包格式来保证了数据传输的正确性:引入了状态机方法,简化了协议的实现难度,提高了通信的可靠性,同时使通信过程具有较高的容错能力。 定义数据包格式 串口通信中最小的的信息单元是数据帧。一个数据帧通常包括起始位、数据位、结束位,另外还可以包含用于检测传输错误的“奇偶校验位”,每个数据帧中传输的数据位可以有5、6、7、8或9个。
另外,在多机通信中,数据包中还应增加源地址与设备地址等字段。 通信状态机状态机简介状态机由事物所处的状态及引发状态变化的外部事件两部分组成。 在软件编程中,事物所处的状态可以描述为某个程序片断或函数,而引发状态变化的处部条件可以理解为条件判断语句,当条件为真时,事物的状态发生变化。事物发生变化前的状态称为现态,变化后的状态称为次态,程序中可以通过不同的数字对不同的状态进行编号。现态到次态的变化可以通过状态变量值的改变来描述。 数据接受方在解释与分析数据包时可能存在两个问题:
为解决上面的两个问题,在协议中引入了状态机。 在状态机中,状态的变化依赖于外部触发条件,当条件满足时,状态将发生变化。 在协议中将数据包接收的各个阶段定义为不同的状态,将接收一帧新的数据或数据处理的结果作为外部触发条件,从而达到状态改变的目的,最终完成一个数据包的接收与校验。 串口通信状态图串口通信协议中,发送数据包时一般不需引入状态机,这主要是为提高发送速率和简化编程模型而考虑。 在协议中主要针对数据接收过程建立状态机。
串口通信数据接收过程
上位机软件编程逻辑上位机软件中,当接收到数据时,串口控件会触发一个事件,在事件处理代码中应及时将收到的数据存入接收冲区,同时不应该把串口通信协议接收部分的代码放置在此事件中,否则后面到来的数据可能因为前面先到的数据没有及时处理完毕而被冲掉,导致数据丢失。
当数据接收顺利时,sp的变化将会引导完成一个数据包的接收过程。这样处理可以简化编程的模型,使协议易于实现;数据包接收过程中,一旦发现数据传输出错,立即将sp置为0(空闲状态),也就是状态复位,使系统进入准备接收下一个数据包的状态,这样可提高通信过程的可靠性及容错能力。 状态机机制实现{------------------------------ @功能:状态机机制实现串口通讯 @author:成鹏致远 @net:lcw.cnblogs.com -------------------------------} procedure TBufferThread.Execute; var s,a :string; sp,mylen,oddEvenCheck,i :integer; begin sp :=0; {指示读数据状态} a :=''; while True do begin {quelist为接收缓冲区} if quelist.Count <>0 then {缓冲区取数} begin s :=quelist.Strings[0]; quelist.Delete(0); a :=a+s; end; if a='' then Continue; {是否空闲状态} if sp =0 then begin if ord(a[1]) =0xFE then begin sp :=1; {进入到起始标志状态} end else {起始标志错误} begin end; Delete(a,1,1); end {是否进入收到起始标志状态} else if sp =1 then begin mylen :=Ord(a[1]); sp :=2; {进入长度状态} Delete(a,1,1); end {是否进入长度状态} else if sp =2 then begin if Length(a) <=mylen +1 then Continue; {数据结束标志:正确} if ord(a[mylen +2])=0xFD then begin sp :=3; {进入数据校验状态} end else {数据结束标志:错误} begin sp :=0; {重新进入空闲状态} end; end {是否进入数据校验状态} else if sp =3 then begin for i:=2 to mylen do begin oddEvenCheck :=a[1] xor a[i]; end; if oddEvenCheck =Ord(a[mylen +1]) then begin sp :=4; {校验正确,进入完成状态} end else {检验错误,进入空闲状态} begin sp :=0; end; end else if sp =4 then begin {这里省略处理命令与附加数据代码} sp :=0; {进入空闲状态} Delete(a,1,mylen+2); end; end; end; |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论