硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2243|回复: 13
收起左侧

[技术讨论] 讨论一下串口解析应该怎么设计比较合理?

  [复制链接]

102

主题

573

回帖

894

积分

金牌会员

积分
894
QQ
发表于 2024-11-7 17:49:22 | 显示全部楼层 |阅读模式
串口可以说是我们用到频率最多的一个外设了。
我们单片机要和外界进行通讯,首先想到的就是串口。
而存在接收数据,就存在解析数据。

首先,我们要明白的一点就是:解析的平均速度,必须大于接收的平均速度。
如果串口解析的速度比接收速度还慢的话,那么数据肯定是会被丢弃或者覆盖的。

在满足 解析的平均速度大于接收的平均速度的情况下,串口接收程序的稳定性就在于"应对突发的流量变动"。

假设接收的平均速度不变,在某个时刻突然有较多的数据涌入,为了保障这个时候不丢数据,就是需要缓冲。
把突发的数据缓存下来,然后解析的函数再一个个去消费掉这些数据。



我目前看到的解析函数的设计方法,大概分为两种:
方式一,把串口当成一个字符设备,一个字节一个字节的接收,并且解析。例如硬汉哥的comGetChar驱动。

串口FIFO的comGetChar函数正确使用姿势
https://forum.anfulai.cn/forum.p ... 9&fromuid=32469
(出处: 硬汉嵌入式论坛)



方式二,就是把串口数据按照分帧来解析,一帧一帧的接收,一帧一帧的解析。

方式一的好处就是没有粘包,断包的说法,但是需要通讯协议有明显的分包方式,比如有帧头帧尾。
方式二的好处就是可以支持没有帧头帧尾的数据,但是要考虑粘包或者断包。



我个人用第二种方式比较多,我喜欢把数据按照3.5字节分帧,然后收到一帧数据之后再去缓存,通知解析的函数去启动解析。
不知道各位坛友如何呢?


回复

使用道具 举报

3

主题

85

回帖

94

积分

初级会员

积分
94
发表于 2024-11-7 19:09:26 | 显示全部楼层
不定长数据咋搞
回复

使用道具 举报

1

主题

16

回帖

19

积分

新手上路

积分
19
发表于 2024-11-8 03:40:15 | 显示全部楼层
可以用COBS 编码数据包,用0 作为帧尾,然后每次连续读到帧尾或读空。我是喜欢弄个二级缓冲区,每次接收到东西都先全部读到二级缓冲区,再慢慢解析,这样就不会受到底层串口驱动内部缓冲区大小的影响
回复

使用道具 举报

39

主题

1516

回帖

1638

积分

至尊会员

积分
1638
发表于 2024-11-8 08:20:22 | 显示全部楼层
gjeoi 发表于 2024-11-7 19:09
不定长数据咋搞

串口DMA+串口空闲+定时器超时
回复

使用道具 举报

102

主题

573

回帖

894

积分

金牌会员

积分
894
QQ
 楼主| 发表于 2024-11-8 08:24:31 | 显示全部楼层
gjeoi 发表于 2024-11-7 19:09
不定长数据咋搞

1.用时间分帧可以接收不定长数据。
2.协议有包头包尾或长度也可以接收不定长数据。
回复

使用道具 举报

6

主题

46

回帖

64

积分

初级会员

积分
64
发表于 2024-11-8 09:29:17 | 显示全部楼层
我也是使用第二种方法比较多,大多数是通过串口DMA+空闲中断去接受并缓存数据,同时打开定时器进行超时等待,在通知串口数据解析程序进行数据解析;
我个人比较纠结的如何设计出一套自己的安全高效的自定义串口通信协议框架,因为有时候,并不会使用一些标准的通信协议;不知道楼主有没有一些经验可以分享一下
回复

使用道具 举报

16

主题

231

回帖

279

积分

高级会员

积分
279
发表于 2024-11-8 16:32:26 | 显示全部楼层
硬件根据当下情况选择合适的方式收数据(逐个字节或DMA搬运)。 软件逐字节解析。
回复

使用道具 举报

7

主题

158

回帖

179

积分

初级会员

积分
179
发表于 2024-11-22 15:52:54 | 显示全部楼层
哪种好用就用哪种,我也喜欢用阻塞式的串口
回复

使用道具 举报

0

主题

18

回帖

18

积分

新手上路

积分
18
发表于 2024-11-22 16:12:22 | 显示全部楼层
我的方案是:先使用3个以上的缓冲区,采用超时断帧,然后再去处理,处理时是按照逐字节处理,这样能处理分包和粘包(前提是协议格式支持帧结构,而不是单纯数据流)
回复

使用道具 举报

3

主题

10

回帖

19

积分

新手上路

积分
19
发表于 2024-11-22 16:39:15 | 显示全部楼层
bobde163 发表于 2024-11-22 16:12
我的方案是:先使用3个以上的缓冲区,采用超时断帧,然后再去处理,处理时是按照逐字节处理,这样能处理分 ...

这和modbus rtu那种方式差不多哦
回复

使用道具 举报

2

主题

71

回帖

77

积分

初级会员

积分
77
发表于 2024-11-22 17:31:43 | 显示全部楼层
如果两边都可控,必然是第一种稳定可靠,一帧数据截成5包也不影响解析,缺陷就是增加一些开销;串口/TCP这种天生就是流式的,是适合逐字节解析的
如果对方不可控(例如对接别人的modbus,别人的代码改不了),这时候再考虑基于空闲分帧的方案比较合适
回复

使用道具 举报

102

主题

573

回帖

894

积分

金牌会员

积分
894
QQ
 楼主| 发表于 2024-11-23 09:05:11 | 显示全部楼层
踩姑娘的小蘑菇 发表于 2024-11-22 17:31
如果两边都可控,必然是第一种稳定可靠,一帧数据截成5包也不影响解析,缺陷就是增加一些开销;串口/TCP这 ...

我一般用重发机制来保证可靠性。
然后第二种方式来解析简单。
回复

使用道具 举报

102

主题

573

回帖

894

积分

金牌会员

积分
894
QQ
 楼主| 发表于 2024-12-12 17:22:52 | 显示全部楼层
踩姑娘的小蘑菇 发表于 2024-11-22 17:31
如果两边都可控,必然是第一种稳定可靠,一帧数据截成5包也不影响解析,缺陷就是增加一些开销;串口/TCP这 ...

按照字节解析的时候,怎么判断到底是长度字节出错还是断帧?
回复

使用道具 举报

2

主题

71

回帖

77

积分

初级会员

积分
77
发表于 2024-12-16 17:27:00 | 显示全部楼层
会飞的猪_2020 发表于 2024-12-12 17:22
按照字节解析的时候,怎么判断到底是长度字节出错还是断帧?

根据长度字节持续接收指定数量的数据,以及界定校验字节
以校验结果确定是否接收到正确完整的一帧(长度字节错误会导致接收长度出错,校验不通过)
校验出错的帧数据丢弃,并重新开始等待包头

如果"断帧"指单帧数据分为2包,则没有影响;
如果"断帧"指某一包丢失了部分数据,仅影响下一包数据的接收,校验不通过重新等包头即可
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 02:44 , Processed in 0.047479 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表