====== 关于串口通讯协议 ===========

愚者只看星不看答案 2018-02-06 08:39:21
我开发软件用于接收串口发送来的数据。现在有这样一个问题

假设协议约定

00 00 00 04 0f 0e ff ff

前面4个字节表示整个数据有多长 这里04 表示后面有 4 个字节
最后两字节 ff ff 为crc16


如果传输有误,04 变成了 05
那么认为没有接收完成, 等待下一个数据到来,假设接下来收到另一条正确的

00 00 00 04 0f 0e ff ff

此时认为这样的数据是一个完整的

00 00 00 05(误传的) 0f 0e ff ff 00

此时crc16校验失败,放弃此条数据,那么问题是后面接下来的所有数据都错了,怎么解决?

此种情况下应该关闭串口再打开吗?还有什么更好的方法?多谢!
...全文
852 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
感谢楼上所有人的回复,一年了,还是没有找到切实可行的方案。。
VF-TECH 2018-02-23
  • 打赏
  • 举报
回复
这个都是你自己可以定的协议
色郎中 2018-02-21
  • 打赏
  • 举报
回复
这样搞一下呢 bootcode len cmd xx xx xx check 引导码 数据包长度 命令码 参数n个 校验码,,这样搞一下
笨狗先飞 2018-02-21
  • 打赏
  • 举报
回复
通讯超时机制,规定多少时间没有收到字节,就认为通讯结束,然后检查数据包。 这样就可以避免数据错位的问题了。
SupermanTm 2018-02-20
  • 打赏
  • 举报
回复
协议本身不完备,无论怎么是有错误几率的,串行口通讯,包含一个“断帧”(Framed)的操作,就是说,你假定数据是流式的,那么如何从数据流中把一个个数据帧提取出来呢? 你的 【长度】【数据】方案其实也是一个“Framed”的方案,但这个方案鲁棒性不良,因为不能自恢复。 一般地,改善这种鲁棒性的方法有两类(可以同时采用),一是通过帧间隔时间,就是说,每一个数据帧里字节与字节之间的间隔时间必须少于某个给定的时间值,当超过这个时间的间隔,系统(接收方)直接丢弃该帧,后续的数据被当作下一个帧头处理。另一个方案是通过特殊的字节来区分(ASCII里的那些控制符以及MODEM的AT命令集事实上也是应用这样的方案),就是约定一些字节用于这种控制符,这种方案应用比较理想,尤其在文本类型,但有个缺陷是数据报文里是有可能包含这些控制字节的,这时候就提出一个“转义符”的概念了,譬如我们约定 0x02 作为帧头符号,那么我也许应该再定义一个 0x03 作为“转义符”,报文中出现 0x02 或 0x03 时,前面应该先给一个 0x03
1586874907 2018-02-11
  • 打赏
  • 举报
回复
在增加帧头的同时,加入超时机制,一帧数据里任意两个字节之间的间隔时间不能大于某个时间,否则认为超时,扔掉前面接收到的不完整数据帧,准备接收新的数据帧。
hello_mcu 2018-02-08
  • 打赏
  • 举报
回复
确认机制,收到有效后要确认,否则重发。
tianxj001 2018-02-07
  • 打赏
  • 举报
回复
你的协议里面,明显少了一个起始串,用作识别包头,断帧。 有约定的起始串,等发行CRC错误,就全部舍弃,然后开始另外寻找起始串,自然就可以同步数据了。
of123 2018-02-07
  • 打赏
  • 举报
回复
如果你的数据传输链路差错率很高,比如说是太空数据传输,仅仅用 CRC 这一类的简单校验就远远不够了。 比如说,你可能要用到纠错码,能够恢复一定数目比特的错误。 再比如,采用交互方式,采用重发机制。 如果你的传输环境差错概率很低,就没有必要了。关键在需求。
of123 2018-02-07
  • 打赏
  • 举报
回复
引用 4 楼 tianxj001 的回复:
你的协议里面,明显少了一个起始串,用作识别包头,断帧。 有约定的起始串,等发行CRC错误,就全部舍弃,然后开始另外寻找起始串,自然就可以同步数据了。
那你是假定起始字符不会错,且实意数据中不含起始字符。如果这个条件不成立,还是不行。 实际上,高差错率通讯协议是有的,也不限于串口物理协议。只不过,在通常串口应用场景下,认为这种差错的概率很低,不那样做就是了。
Acuity. 2018-02-06
  • 打赏
  • 举报
回复
将数据分为一帧一帧发送,校验一帧,其他正确怎会干扰呢? 另外可以参考modbous的协议,非常厉害的一个协议,或者可以直接移植过来使用。
ckc 2018-02-06
  • 打赏
  • 举报
回复
约定一个帧头。 可以选择正常数据中不会出现的序列,比如约定4个00后面跟ff为帧头。 这样传输数据的时候如果出错可以依靠检验位识别错误的数据并丢弃,下次根据帧头还是可以继续通讯的。 如果正常数据中什么样的数据都可能存在,那就要用特殊方法,比如正常数据中如果有4个00,就在4个00后面再插入1个00, 接收的时候如果接收到4个00,后面是ff,说明是帧头,如果是00,就把这个00丢弃

27,373

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧