数据通信的协议帧如果有帧头,是否需要定义转译和在发送前转译数据?

bandaoyu 2020-02-19 08:49:41

我的小组定的协议帧格式,帧头是0xFF0xFE,但是没有看到有数据内包含与帧头一样的数据时如何转译的说明,所以我就有疑问,

我就问:

有串口通信的需求吗? 有的话,“协议头” 在串口通信时是不是应该说明转译规则(数据中含有和协议头一样的数据),或者明确两帧之间的发送时隙的要求。不然会不会出现粘包或多帧合并发送时没法拆包?

对方回答:


我们实际上会在缓存解包,分包与拆包,不会出现大量粘包现象的。



问题来了,我不太理解他说的:“在缓存解包,分包与拆包” 是什么意思? 是如何识别帧头帧尾,分包拆包的?
...全文
1552 36 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
djc。 2022-01-20
  • 打赏
  • 举报
回复

我使用的串口通信,要对伺服读取实时示波器数据。也出现了粘包现象。实时数据最小采样间隔是0.1ms。

bandaoyu 2020-03-04
  • 打赏
  • 举报
回复
引用 34 楼 ba_wang_mao 的回复:
“单片机上如果上位机每次只发送一帧独立的报文(上位机如果不是将几个报文打包一起发的话),完全没有必须考虑粘包问题、分包问题,也就是说: (1)、如果上位机发送的2条报文之间的时间间隔大于10毫秒,就没有必须考虑粘包问题,粘包只会出现在TCP网络环境中。”
你这里说的单片机不考虑粘包,指的的串口通信吧? 是不是TCP和单片机有什么关系呢? 单片机也有支持TCP通信的呀。 我想你的意思应该是 串口通信,因为串口占用,所以只有一对一的通信,只要上位机每次只发一帧,所以不用考虑粘包问题。 而TCP 因为可以一对多,所以多个上位机来的数据可能都放到一个缓冲中,导致粘包 是这个意思吗
bandaoyu 2020-03-04
  • 打赏
  • 举报
回复
引用 34 楼 ba_wang_mao 的回复:
感谢!非常好,回答得很详细,认真~~
bandaoyu 2020-03-04
  • 打赏
  • 举报
回复
引用 40 楼 ba_wang_mao 的回复:
原来如此!你太厉害了,非常感谢!! 回答得很认真详细~~~
ba_wang_mao 2020-03-04
  • 打赏
  • 举报
回复
所以说单片机串口通信时,只需要前一帧报文和后一帧报文的间隔时间满足以下条件即可:单片机有充足的时间完成前一帧报文的接收和解析工作就OK啦!
ba_wang_mao 2020-03-04
  • 打赏
  • 举报
回复
1、有的单片机的串口通信也有【硬件发送缓冲区】和【硬件接收缓冲区】,只是缓冲区非常少,最大也就16字节(即最多可以缓存16个字节)。
2、单片机不粘包的原因是:它是串行通信的,硬件收到一个新的字节,就立即触发接收中断,程序员就可以在接收中断中读取,如果程序员不读取它,过一会又来了一个字节,就会把之前的字节覆盖掉。
3、而TCP粘包的原因是TCP协议算法的原因。
你要求程序发送一条报文,该报文长度很小,根据TCP协议,它认为这条报文还不到发送时间,它就把该报文暂存在系统中,当你又发送了一条报文,它认为达到发送条件了,它就把刚刚缓存的报文和现在的报文发送出去,所以就出现了粘包。

单片机串口通信就没有这样的机制,它不管三七二十一,当你往【硬件发送寄存器】装数据时,它就通过内部机制立即发送出去,不会像TCP通信那样由TCP协议来决定这条报文是否立即发送出去。




bandaoyu 2020-03-04
  • 打赏
  • 举报
回复
引用 38 楼 ba_wang_mao 的回复:
所谓粘包,是指某一个连接内传输报文时出现粘包,而不是指某1个连接和其它连接之间的报文粘在一起。
串口通信不需要考虑粘包,而TCP 需要考虑粘包,是因为“TCP有发送缓冲区,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包;” 而串口通信是没有发送缓冲区,调用发送接口就直接发出去?
ba_wang_mao 2020-03-04
  • 打赏
  • 举报
回复
所谓粘包,是指某一个连接内传输报文时出现粘包,而不是指某1个连接和其它连接之间的报文粘在一起。
ba_wang_mao 2020-03-04
  • 打赏
  • 举报
回复
1、单片机的串口通信没有必须考虑粘包问题、分包问题。
2、如果你使用以太网转串口芯片通过单片机上的串口和上位机通信,也没有必须考虑粘包问题、分包问题。
3、如果你使用单片机上的以太网直接和上位机通信,必须考虑粘包问题、分包问题。
4、而TCP 因为可以一对多,所以多个上位机来的数据可能都放到一个缓冲中,导致粘包。
你上面的这句话理解有问题。
粘包和分包对于TCP来说是建立在一个TCP连接上的,而不是什么几台电脑这种概念。

(1)、如果1台电脑和你的单片机通过以太网建立了1个连接,
那么电脑通过连接1发送给单片机的报文就需要考虑粘包问题。
(2)、如果1台电脑和你的单片机通过以太网建立了2个连接
那么电脑通过连接1发送给单片机的报文就需要考虑粘包问题。
那么电脑通过连接2发送给单片机的报文就需要考虑粘包问题。
但是不会出现连接1的报文和连接2的报文混在一起这种情况滴!

可以把以太网中的【TCP连接】想像成RS232通信电缆一样:
第一个TCP连接,就相当于通过一根电缆连接到单片机的USART1串口,
第二个TCP连接,就相当于通过另外一根电缆连接到单片机的USART2串口,
第三个TCP连接,就相当于通过另外一根电缆连接到单片机的USART3串口,
以此类推,所以TCP上的报文不可能出现不同的连接的报文混在一起滴。

ba_wang_mao 2020-02-24
  • 打赏
  • 举报
回复


// 定时器中断
void TIM1_UP_IRQHandler(void)
{

if (TIM_GetITStatus(TIM1,TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
TIM_Cmd(TIM1, DISABLE);
MB_USART1.Outtime_mark = TRUE; //定时器溢出表示接收完一帧完整的报文,置接收完成标识
}
}



//串口中断方式
void USART1_IRQHandler(void)
{
uint8_t ch;


if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
ch = USART_ReceiveData(USART1);
if (MB_USART1.receCount < MSCOMM_BUFFER_LENGTH)
MB_USART1.mscomm_buffer[MB_USART1.receCount++] = ch;
else
MB_USART1.receCount = 0;

TIM_Cmd(TIM1, DISABLE);
TIM_SetCounter(TIM1, 0x00); // 清定时器的计数
TIM_Cmd(TIM1, ENABLE);
}

if (USART_GetITStatus(USART1, USART_IT_TC) != RESET)
{
USART_ClearFlag(USART1,USART_FLAG_TC);
if (MB_USART1.sendPosi < MB_USART1.sendCount)
USART_SendData(USART1, MB_USART1.send_buffer[MB_USART1.sendPosi++]);
else
{
USART1_RS485_RECIVE_enable();
USART_ITConfig(USART1, USART_IT_TC, DISABLE);
}
}
}





ba_wang_mao 2020-02-24
  • 打赏
  • 举报
回复
单片机上如果上位机每次只发送一帧独立的报文(上位机如果不是将几个报文打包一起发的话),完全没有必须考虑粘包问题、分包问题,也就是说:
(1)、如果上位机发送的2条报文之间的时间间隔大于10毫秒,就没有必须考虑粘包问题,粘包只会出现在TCP网络环境中。
(2)、如果上位机发送的每条报文都是一条独立的报文,则没有必须使用环形缓冲区。
只需要在串口接收中断中启动一个3.5字节接收时间的定时器即可,当定时器溢出,就表示一帧报文接收完毕。
假如定时器溢出时,接收总长度=20
接收缓冲区 【0】 = 报文第1个字节
接收缓冲区 【19】 = 报文最后个字节

打个比方:当上位机发送的报文分别是【报文1】、【报文2】、【报文3】时
上位机发送时,只会发送【报文1】
只会发送【报文2】
只会发送【报文3】
不会出现【报文1】+【报文2】
不会出现【报文1】+【报文3】
不会出现【报文2】+【报文3】
不会出现【报文1】+【报文2】+【报文3】
就没有必要搞个环形缓冲区。

(3)、如果上位机发送的每条报文,有时候是一个单独的报文,有时候是几个报文叠加在一起发,则需要使用环形缓冲区识别出具体的每一个报文。
打个比方:当GPS设备发送报文时,不是每次只单独分别发送GPGGA报文、GPTRA报文、GPRMC报文,
而是有时候发送 GPGGA报文+GPTRA报文
有时候发送GPGGA报文+GMRMC报文
有时候发送GPGGA报文+GPTRA报文+GPRMC报文
这个时候就要用到环形缓冲区解析报文。

总之,单片机中最简单的判断接收完一个报文的方法如下:
第一步:定义一个3.5字节接收时间的定时器
第二步:串口接收中断中只要收到一个字节,就清空定时器的计数
第三步:当定时器溢出,就表示一帧报文接收完毕。

bandaoyu 2020-02-23
  • 打赏
  • 举报
回复
引用 31 楼 丁劲犇 的回复:
我不是版主,不知为什么会显示版主,额,真的很奇怪。我也管理不了别人的帖子。没有人联系过我,估计是bug 对的,就是如果不通过校验,就要逐个字节去挪动。校验可以自己定算法,比如把头部字节按照uint16算数想加,或者异或都可以。
我还是不大明白你的意思,“比如把头部字节按照uint16算数想加,或者异或都可以”你说的”头部字节“是指帧头吗?校验是指校验出帧头? 我的疑问是如何 区分出真的帧头 和 假的帧头。 我的想法是这样的,比如下面这个缓存数据,第一帧的帧头不完整,且帧数据内有和帧头一样的数据。 在检出帧头的操作中,检到8,9,10 字节时,怀疑是”帧头“,然后再从该”帧头“的后面一个字节得到”长度“ send_buffer[12] = 0x89; ,然后再按照这个长度 获取出0x89长度字节的数据, 最后对获取出来的 帧头+长度+数据 进行CRC校验,再与 帧数据里面带的CRC对比,如果错误,说明 send_buffer[9] = '$'; send_buffer[10] = 'G'; send_buffer[11] = 'P'; 不是帧头。 继续从send_buffer[11]往后挪 找下一个帧头,而不是从send_buffer[11]+帧长度+0x89 之后的挪,也就是当前帧头错的话,就是从当前假帧头之后的字节继续往前找帧头。(这样的话,就要再给环形缓冲加一个 指针专门找帧头的指针,而是不用读指针边读边找帧头)我的想法对吗? 你的想法是什么样的? 缓存数据: //send_buffer[0] = '$' --------------------> 帧头="$GP" --->去掉$ 制造一个不完成帧 send_buffer[1] = 'G' send_buffer[2] = 'P' send_buffer[6] = 0 --------------------->帧长度 send_buffer[7] = 14;--------------------->帧长度=0014 send_buffer[8] = 0x11; send_buffer[9] = '$'; send_buffer[10] = 'G'; send_buffer[11] = 'P'; send_buffer[12] = 0x89; send_buffer[13] = 0x90; send_buffer[14] = '$' --------------------> 帧头="$GP" send_buffer[15] = 'G' send_buffer[16] = 'P' send_buffer[17] = 0 --------------------->帧长度 send_buffer[18] = 14;--------------------->帧长度=0014 send_buffer[19] = 0x11; send_buffer[20] = 0x12; send_buffer[21] = 0x13; send_buffer[22] = 0x14; send_buffer[23] = 0x89; send_buffer[24] = 0x90;
丁劲犇 2020-02-23
  • 打赏
  • 举报
回复
仔细看了楼上,已经很清楚了,环形缓存和头校验。只要没有频繁的内存动态分配,性能都差不多。pppoe,ip,asn,都是用于嵌入式的成熟协议,可以看看一些开源代码里是怎么折腾的。
丁劲犇 2020-02-23
  • 打赏
  • 举报
回复
等待的时候,是每个字节推过去。如果图像里有假头,校验不通过,还是逐个字节后推。直到校验通过了,才是直接取长度
丁劲犇 2020-02-23
  • 打赏
  • 举报
回复
第二种,因为有二进制总计校验,所以如果校验不对,就不是贞头,接着等待。二进制总计校验很节约时间。 第三个,适合封非常复杂的指令,可以用各种标志位,决定后面有哪些块。比如是不是有电机数据,温度数据。这个东西用语言描述结构,而后有工具asn4c asn4j直接把asn语言编译成c或者java
丁劲犇 2020-02-23
  • 打赏
  • 举报
回复
引用 30 楼 bandaoyu的回复:
[quote=引用 29 楼 丁劲犇 的回复:]
哇!原来是版主大人!!版主出马 又让我学了不少东西。 请问什么是“二进制总计校验”? 也就是说 二进制总计校验不通过的时候,不丢弃假头后面假“帧长度”的数据,而是从假头继续往后推进去找帧头然后按后面的“帧长度”取数据校验,通过了才把数据从环形缓存里面取出来对吗? [/quote] 我不是版主,不知为什么会显示版主,额,真的很奇怪。我也管理不了别人的帖子。没有人联系过我,估计是bug 对的,就是如果不通过校验,就要逐个字节去挪动。校验可以自己定算法,比如把头部字节按照uint16算数想加,或者异或都可以。
bandaoyu 2020-02-23
  • 打赏
  • 举报
回复
引用 29 楼 丁劲犇 的回复:
哇!原来是版主大人!!版主出马 又让我学了不少东西。 请问什么是“二进制总计校验”? 也就是说 二进制总计校验不通过的时候,不丢弃假头后面假“帧长度”的数据,而是从假头继续往后推进去找帧头然后按后面的“帧长度”取数据校验,通过了才把数据从环形缓存里面取出来对吗?
bandaoyu 2020-02-22
  • 打赏
  • 举报
回复
引用 24 楼 丁劲犇 的回复:
第一种:转译的方法我们知道的,需要发送和接收都需要转译,对性能影响应该不小,估计我同事就是因为这个放弃这个方法 第二种,固定头加长度加校验,比如参考ip。(这个方法,我就是还有一个疑惑不能解决: 这种方法就是 遇到帧头就安装后面的帧长度读出帧数据然后校验,校验错误就丢弃,从后面的数据继续找帧头……丢几帧后就会同步,不过有一种非常特殊的情况会造成 不管多少帧之后都无法同步,这种情况是这样的: 协议是 二进制数据的,你很难知道 帧数据中会出现什么样的数据,比如帧头是"$GP",如果对方每一帧都要传一张小图片,谁也无法保证图片中没有包含"$GP"这样的数据呢,这样的话如果首帧的帧头丢失,就会出现不管丢多少帧都无法验证通过无法同步的现象。 第三种,使用ASN.1数据规范,是3G里面广泛使用的,可灵活啦----这个能大概说说和前两种有什么不同吗
丁劲犇 2020-02-22
  • 打赏
  • 举报
回复
一种是类似pppoe,用字节7e分割,中间数据里7d转义,用7d5d代表7d,用7d5e代表7e。加不加校验自己选择。 第二种,固定头加长度加校验,比如参考ip。 第三种,使用ASN.1数据规范,是3G里面广泛使用的,可灵活啦。
丁劲犇 2020-02-22
  • 打赏
  • 举报
回复
参考pppoe吧。这个解决的很好了。
加载更多回复(16)
附录A 自我测试题答案 第1章 1. A。源路由挢接不检查M A C地址,因此如果R I F不存在,那么就将丢弃。源路由透明 桥接与源路由交换的工作方式不是这样。源路由透明交换根本就不存在。 2. D。路由器不转发广播提出报文(除非配置它使其转发D H C P广播报文),因此路由器能 有效地减少广播域的范围。增加路由器后,网络中的路径数不会减少,也不需另外增加新的 协议。 3. C。该方法延迟低,特别是与存储转发法相比。C u t - a n d - s t o r e与s t o r e - a n d - c u t法是不存 在的。 4. C。D。端口1 9与2 0用于将Catalyst 3900交换机接入到令牌环网中。端口1和2用于将设 备加入到交换机中。 5. A。带冲突检测的载波侦听多路访问协议( C S M A / C D)是I E E E在8 0 2 . 3规范中定义的协 议。令牌环网使用C S M D / C D协议。T 1与O C - 3是点到点链路,通常用于广域网中。 6. A。B。D。这三种设备可用来将局域网分段。每种设备的功能各不相同,因此你按自 己的需要选择适当的设备。“介质改变单元”不存在。 7. B。Cisco 5500交换机就是用这种方法转发分组。5 5 0 0交换机不支持直通法、自由分片 法与快速转发法。自由分片法与快速转发法是C i s c o对直通法进行改进而产生的新方法。 8. D。因为交换机是插在介质访问单元( M A U)上的,它看起来象一个设备。M A U单元检 测到交换机所插的端口工作不正常时,会把该端口排排除,而其他接在M A U上的节点却不受 影响。停止工作的是接在该交换机上的节点。 9. B。D。这两个词对网络性能有消极影响。F D D I与AT M是通常用于骨干网络的技术。 10. C。存储转发法对每一个通过交换机的进行循环冗余校验,进行C R C校验的目的是 为个保证中的数据没有被破坏。直通法不用C R C校验。S t o r e - a n d - c u t与C u t - a n d - f o r w a r d法不 存在。 11. D。9 0年代初,众多厂商决定开发一种新设备来代替路由器,因为它们觉得路由器成 本太高,并且难以配置。开发交换机不是用来取代中继器。S N A是一组网络协议。A S I C是专 用集成电路的缩写。 12. B。交换机只不是一种多端口网桥。与网桥一样,它们也用目的M A C地址将分组转发 到正确的端口。交换机不能比作多端口中继器与多端口路由器。 13. C。微分段法将局域网分成较小的网段,这样相应地增加了端用户可用的带宽。它不 会降低带宽,也不会增加或减少端用户可用的端口数。 14. B。交换机监视所有的网络业务流并生成一张M A C地址表。交换机用这张表将转发 到正确的端口,而不是使用源M A C地址来转发。不存在源A R P地址,交换机也没有什么 A R P地址表。

27,509

社区成员

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

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