PDF下载
基于SLIP协议的串口通讯软件设计

陈涛 杨柳喧 李京

苏州长风航空电子有限公司

摘要: 论述嵌入式产品在软件开发过程中,使用SLIP协议,通过串口物理层与外设进行通信。基于SLIP协议帧头帧尾的特征和串口传输数据时不完整的现象,论述如何在软件开发中组包数据,发送数据、接收数据、解析数据等一系列的开发过程。解决数据组包难题,解决数据接收不全导致丢包现象,本文贯穿整个软件开发的开发全过程,说明其通用性、易用性、可实现广泛应用。
关键词: SLIP;软件测试;C语言;测试软件通讯
DOI:10.12721/ccn.2023.157079
基金资助:
文章地址:

引言

嵌入式软件项目中,为增加软件的安全可靠性,有时需要使用SLIP协议,串口作为物理通信链路,与外设进行通信。SLIP的字节数量不确定,给数据解析带来很大困扰,数据解析时要判断包头包尾,校验数据位,串口接收的数据不全,经常发生丢包,表现出来的现象就是软件没有响应。本文通过使用链表技术,将接收到的数据存放在链表中,结合实际产品软件设计,对不定长数据的接收处理进行论述,解决数据接收问题。

1  SLIP介绍

1.1  什么是SLIP

SLIP是串行线路网际协议,是串行线路上对IP数据报进行封装的简单形式。

1.2  SLIP特征

数据包以END(0xC0)的特殊字符结束,而有些数据包的开始处也传一个END字符以防止数据包到来之前的线路噪声当做数据包内容。若IP报文中某个字符为END,那么连续传输两个字节0xdb和0xdc来取代(0xdb这个特殊字符被称为SLIP的ESC字符)。若IP报文中某个字符为ESC,那么就连续传输两个字节0xdb和0xdd来取代。

1.3  SLIP特点

SLIP没有校验字段,不提供差错检测的功能。当SLIP帧在传输中出差错时,只能靠高层协议来进行纠正。在项目中,可以人为的加入校验位来弥补SLIP本身的缺陷。将帧头帧尾以外的数据进行异或得到一个信息校验位,放置在帧尾前一位。

1.4  传输格式说明

a) 数据长度和消息数据均要经过转移处理

b) 多字节传输先传输高字节,再传输低字节,如ABCD的发送顺序为bit8-bit15,bit0-bit7, BA DC

c) 数据流向:从上至下发送数据帧的每个字节,没一个字节从低位至高位发送,如:C0H的发送顺序为Bit0-Bit7 :0000 0011

d) 有符号的数据采用补码方式处理,取反加1。

2  软件方案设计

软件设计中使用软件中断的方式来检测端口是否有数据,中断接收到数据后,采用C语言链表的方式临时存储数据;中断接收存储完数据后,软件将对存放在链表中的数据进行协议规则检查,符合规则时将进行SLIP数据转义,对高低字节和特殊字符的转义;转义完成的数据才是真实的数据,这时对数据解析才有效;解析完成后,及时清理链表,防止链表太长,耗费程序空间和重复处理数据。软件设计流程图见图1。

 图片2.png

图1 软件设计流程图

3  链表技术设计

3.1 链表的定义

链表数据结构时一种常见的数据结构,它是一种线性表,单并不是按线性顺序存储数据的,而是在每一个节点里存到下一个节点的指针。链表有一系列的结点组成,结点可以在运行时动态生成。结点是链表中的一个元素。包含两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。相比于线性表顺序结构,操作复杂。由于不必按顺序存储,链表在插入的时候可以查到任意位置,比线性顺序表性能响应快速;查找结点或者访问一个结点需要根据特点的编号进行。该数据结构比较适合频繁的进行插入和删除操作。

3.2 链表初始化

链接在使用前不能为空,必须进行初始化链表。链表初始化操作包括,定义一个结构体(包括数据域,指向数据的指针)和创建一个头结点。声明一个指针,指向头结点。

3.3  链表插入数据

链接在使用前不能为空,必须进行初始化链表。链表初始化操作包括,定义一个结构体(包括数据域,指向数据的指针)和创建一个头结点。声明一个指针,指向头结点。

3.4 链表查询数据

链接在使用前不能为空,必须进行初始化链表。链表初始化操作包括,定义一个结构体(包括数据域,指向数据的指针)和创建一个头结点。声明一个指针,指向头结点。

3.5 链表删除数据

链接在使用前不能为空,必须进行初始化链表。链表初始化操作包括,定义一个结构体(包括数据域,指向数据的指针)和创建一个头结点。声明一个指针,指向头结点。

3.6 链表显示

链接在使用前不能为空,必须进行初始化链表。链表初始化操作包括,定义一个结构体(包括数据域,指向数据的指针)和创建一个头结点。声明一个指针,指向头结点。

4  应用软件开发

测试软件中使用链表技术,首先需要对链表进行初始化分配空间,对头指针进行特定赋值;在CVI串口中断函数中,对接收的串口数据进行插入链表处理;对链表中存在的符合规则的数据进行相应处理;对处理完的链表数据进行删除操作,见图2。

 图片3.png

图2 链表设计流程图

4.1 初始化

由于链表中的结点是一个结构体类型,并且结点中有一个成员用于指向下一个结点,所以在使用中使用结构体来作为结点的格式。

typedef struct Link{

     int  data;

   struct Link *next;

}link;

动态分配存储空间,使用malloc()函数在存储区中动态分配一个长度为链表结构体长度字节的连续空间。函数返回值为一个指向分配域起始地址的指针,若分配失败则返回NULL值。

4.2 串口中断接收处理

测试软件中使用软件中断,定义中断接收函数,当串口有接收到数据时,就会触发中断函数。读取到串口中的数据,对接收的数据插入到链表中去。

数据插入链表,首先找到要插入位置的上一个结点,首次插入时上一个结点为头结点,后续插入时需进行查询得到上一个结点;创建一个新的结点,得到一个链表结构体newNode,将串口接收的数据赋值给newNode.data,newNode.next指向尾结点;上一个结点的next指针指向newNode。一番操作后,链表中就存放了串口中断接收的数据。串口传输数据量较多时,会多次触发串口中断,链表将多次插入数据。

4.3 数据处理

经过上述操作后,链表里已经存放了大量的数据。根据协议规则对数据进行提取解析。根据SLIP协议头尾均为0xC0,需要对链表中的数据进行查询,查询出第一个0xC0的位置和第二个0xC0的位置,若第一个位置和第二个位置信息,距离过近则不符合要求,说明两个C0之间接收的数据有异常,做淘汰处理。当两个C0之间的数据符合要求时,则对之间数据进行解析处理。

4.4 数据清除

嵌入式产品中软件串口发送数据经常周期性的,本方案中链表接收的数据也会越来越多,链表数据多会影响查询速度,更会影响到对接收数据的重复处理操作。现在需要将已经解析处理完的数据在链表中进行清除,清除链表中数据时,需要逐个数据的清除,没清除一个数据后,需要将上个结点的指针改向下一个结点。已经解析的数据将被清除,此时链表中存放是不完整未满足解析条件的数据,当中断再次发生激活链表处理是,保证每次解析处理的数据都是最新接收的数据。即避免了重复处理,又及时相应最新结果。

5  结语

本文通过实际测试,串口数据通过链表技术去解析,性能可以精确控制在1ms之内,大数据可以控制在5ms左右处理完,目前串口发送周期均远远小于5ms。串口数据全部存放在链表中,提取有用数据进行解析,所以链表技术可以有效解决工作中遇到的串口接收数据不全的问题。针对嵌入式系统软件的复杂性与特殊性,结合实际测试过程给出了符合软件的设计方案,为后续相关研究设计工作提供参考。

参考文献:

[1] 布鲁克曼.《嵌入式软件测试》. 北京:电子工业出版社,2004.

[2] Peter Van Der Linden.C专家编程.人民邮电出版社.2008, 81-88.

[3] Kenneth A.Reek.C和指针.人民邮电出版社.2008, 195-213.

[4] Stephen Prata. C Primer Plus[M].人民邮电出版社.2019.22-35

[5] 陈文智 嵌入式系统开发原理与实践[M] 北京:清华大学出版社,2005