分类:
2008-12-17 18:00:15
-
串口数据包
数据包协议是为了在连续发送多条命令时,接收方能够容易判断从哪里开始是命令的开始,到哪里结束。
当属性 UsePackage=true 时,会启动数据包支持,你可以随时启动和停止数据包支持。
数据包有几种,例如:
1. 延时,如果持续有多长时间没接收到数据,再接收到数据时认为是命令的开始,要想可靠,需要长时间的延时,所以速度很慢,因为实现简单,很多人都在用;
2. 标识 + 长度 + 数据,如果接收方收到误码,把长度收错,后面的数据就乱套了,如果由于误码长度变大,再接收到的标识还以为是数据呢;
3. Victor控件采用的方法:头标识 + 数据 + 尾标识,这种方法发送的数据中,如果有作为头尾标识的字节,要转换为:控制符
+ 字节,这种方法的优点:
① 数据可以连续发送,不用间断;
② 接收到误码不串位,遇到包尾和包首会很容易同步;
③ 如果数据中包含CRC(循环冗余校验码),很容易判断数据是否有误码。
Victor的方法看起来有些复杂,在对数据可靠程度要求比较高的时候用的比较多。
实际上在单片机上实现这个算法也很简单,编码和解码程序都不超过30条汇编语言语句(8051汇编)。
所有常见的 CRC校验 的函数已经包含在 Victor 控件里面了,在 yb_base.h 头文件中。
CRC校验码需要自己计算,并且包含在数据中。
发送自定义的数据包时,FrameSettings的FrameHead、FrameTail、FrameCtrl 分别表示数据包的开始、结束、控制符,这些数据也发送到对方。
数据包格式:
数据包头 + 数据 + 数据包尾
如果数据中含有表示数据包头和数据包尾的字节时,要发送控制符 + 发送的字节
例如:头 0xDB, 尾 0xDE, 控制 0xDC
要发送 0x02 0xDB 0xEC,从串口里发出的数据是:
0xDB 0x02 0xDC 0xDB 0xEC 0xDE
包头 数据 控制 数据 数据 包尾
│
╰─ 这个0xDB因为前面有个0xDC控制符,所以按照数据处理,而不是包头。
如果收到误码,前面的0xDC坏了,收到0xDE时就会结束这个命令,通过数据里面的CRC校验码可知此包是错误的,下个0xDB自动同步,而不是数据串位。
以上编码和解码由控件内部完成,只需要调用 ReadPackage 和 WritePackage 方法就可以了
调用 WritePackage 时只需要给出 0x02 0xDB 0xEC, 接收端调用 ReadPackage 读出的数据是已经解码的数据:
0x02 0xDB 0xEC
//--------------------------------------------------------------------------- #pragma pack(push,1) //开始定义数据包, 采用字节对齐方式 const MyPkgSize = 1024; //数据包最大长度 typedef struct { long nBytes; //第一个参数必须是 32 位整数, 表示数据的字节数 char Data[MyPkgSize]; //数据, 可以是任意的 } TMyPackage; //自定义的数据包 #pragma pack(pop) //结束定义数据包, 恢复原来对齐方式 //--------------------------------------------------------------------------- try YbCommDevice1->PackageSize =
MyPkgSize; //这个数据必须正确! AnsiString t,s = Edit1->Text.Trim(); YbCommDevice1->WritePackage(&pkg);
//发送数据包 while(YbCommDevice1->ReadPackage(&pkg)) if(!s.IsEmpty()) |