打印
[C语言]

一种高效的串口数据包接收方式

[复制链接]
21604|57
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
科技猎人|  楼主 | 2014-1-14 16:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 科技猎人 于 2016-6-19 19:47 编辑

大概思路:
1.要构建一个结构体用于记录串口接收需要用到的数据
2.初始化硬件,中断接收,初始化上面那个结构体,给串口接收动态分配一个缓存区
3.每次串口接收中断将收到的数据放入缓存区,并对计时清零
4.用定时器中断检查是否超时,超时则认为一包数据已接收完成,发送消息以便中断返回后处理,再为串口接收申请另一块缓存空间,这样就可以马上继续接收下一包数据了
。。。

这样做的好处时:
1.对数据包的格式(固定包头,包尾。长度等)没有任何限制,只要求数据包之间的时间间隔大于数据包内每个字节间的间隔(这是自然的传输情况)
2.不像其他一些缓存式的接收方式需要缓存间的二次拷贝
3.所有处理都是在中断中进行的,没有延时,CPU效率很高,处理及时,能有效避免数据包丢失
。。。


具体程序读者可以根据思路自己编写,也可以参考本人已实现的源码。具体程序在另一篇帖子的附件“MsgOS-51”里有源码
地址:https://bbs.21ic.com/icview-673162-1-1.html
补加感触:
此贴其实只是“MsgOS-51”里很微不足道的一点技术,却比整个系统的访问量多的多,也是醉了。现在更加完善的面向cortex-m的MsgOS系统也已近发布了,不知道最后能不能比这个帖子火。


相关帖子

沙发
dota_yy| | 2014-1-14 17:19 | 只看该作者

使用特权

评论回复
板凳
dirtwillfly| | 2014-1-14 21:50 | 只看该作者
谢谢楼主分享

使用特权

评论回复
地板
pangencao| | 2014-1-14 22:33 | 只看该作者
问题:
数据包的正确性仍需要再次判断,因为可能有畸变、干扰数据,再次判断仍然绕不开包头、校验等处理。
如果与PC相连,数据传输的连贯性可能得不到保证,也会出问题,与usb串口、以太网转串口等相连时也有类似问题,通用性不强。

帧超时倒是有点像modbus概念。

使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
科技猎人 + 2 赞一个!
5
allround| | 2014-1-14 23:12 | 只看该作者
楼主的情况,若波特率不一致也是可接收到错误内容的

使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
科技猎人 + 2 赞一个!
6
科技猎人|  楼主 | 2014-1-15 08:43 | 只看该作者
pangencao 发表于 2014-1-14 22:33
问题:
数据包的正确性仍需要再次判断,因为可能有畸变、干扰数据,再次判断仍然绕不开包头、校验等处理。
...

校验确实是必须的,但现在是把接收数据包和处理数据包(包括校验)分开了,做到了不会由于数据处理而耽误了下一包数据的接收。这种方式适合数据包得接收,而连续的数据流就不合适了。

使用特权

评论回复
7
科技猎人|  楼主 | 2014-1-15 08:46 | 只看该作者
allround 发表于 2014-1-14 23:12
楼主的情况,若波特率不一致也是可接收到错误内容的

如果物理层都没有匹配,那通信肯定会错误。所以对包处理时还因该先校验。

使用特权

评论回复
8
pangencao| | 2014-1-15 09:10 | 只看该作者
科技猎人 发表于 2014-1-15 08:43
校验确实是必须的,但现在是把接收数据包和处理数据包(包括校验)分开了,做到了不会由于数据处理而耽误 ...

采用循环队列通用性应更好一些。

使用特权

评论回复
9
科技猎人|  楼主 | 2014-1-15 09:52 | 只看该作者
pangencao 发表于 2014-1-15 09:10
采用循环队列通用性应更好一些。

这得看应用情况了。在我现在做的实际项目中用我的方法在可靠性、丢包率、内存和CPU效率等方面都是最好的。循环队列一般需要较大的内存空间吧,还需要二次拷贝数据,提取数据包和校验也相对繁琐;不过用在数据流通信时很合适。。。

使用特权

评论回复
10
chenbb8| | 2014-1-15 10:17 | 只看该作者
我的做法是不用申请另外一块内存,用的是双缓冲,
超时后,当前缓冲就给后台处理,并使用另外一块缓冲存接收的数据,
不过后台要是没办法在一定时间内处理完的话,还是可能会被覆盖掉的~~

使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
科技猎人 + 2 很给力!
11
科技猎人|  楼主 | 2014-1-15 10:50 | 只看该作者
chenbb8 发表于 2014-1-15 10:17
我的做法是不用申请另外一块内存,用的是双缓冲,
超时后,当前缓冲就给后台处理,并使用另外一块缓冲存接 ...

双缓存得方法之前也想过,不过我的实际应用中数据包来的时间和数量都不确定,也是担心当前的还没处理完又来了好几包,这样就要丢包了。我这么做也是和我那个协作式系统框架能很好匹配。

使用特权

评论回复
12
金融小数| | 2014-1-15 12:00 | 只看该作者
所有处理都在中断里面处理?--------这个好像不合适,中断里面的处理时间尽可能的短。

使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
科技猎人 + 2 赞一个!
13
youluo235| | 2014-1-15 12:16 | 只看该作者
这个号。感谢分享。

使用特权

评论回复
14
科技猎人|  楼主 | 2014-1-15 12:30 | 只看该作者
金融小数 发表于 2014-1-15 12:00
所有处理都在中断里面处理?--------这个好像不合适,中断里面的处理时间尽可能的短。 ...

是接收数据在中断中处理,即进入中断,将数据放入缓存,退出中断,耗时很短的。真正的对数据包进行校验和分析处理等工作是在应用层任务里处理的。

使用特权

评论回复
15
chenbb8| | 2014-1-15 12:31 | 只看该作者
金融小数 发表于 2014-1-15 12:00
所有处理都在中断里面处理?--------这个好像不合适,中断里面的处理时间尽可能的短。 ...

所谓的所有处理,指的是接收动作,而不是通讯协议放到中断中。

使用特权

评论回复
16
科技猎人|  楼主 | 2014-1-15 12:34 | 只看该作者
chenbb8 发表于 2014-1-15 12:31
所谓的所有处理,指的是接收动作,而不是通讯协议放到中断中。

楼上正解。。。

使用特权

评论回复
17
金融小数| | 2014-1-15 12:41 | 只看该作者
chenbb8 发表于 2014-1-15 12:31
所谓的所有处理,指的是接收动作,而不是通讯协议放到中断中。

指的是接收动作 ---- 通常都是在中断里处理,难道接收处理会有部分放在中断外面?

使用特权

评论回复
18
chenbb8| | 2014-1-15 12:58 | 只看该作者
金融小数 发表于 2014-1-15 12:41
指的是接收动作 ---- 通常都是在中断里处理,难道接收处理会有部分放在中断外面? ...

有啊,比如有些初级的单片机教程里,在后台死循环判断接收标志位来,达到接收的目的……

使用特权

评论回复
19
金融小数| | 2014-1-15 13:04 | 只看该作者
chenbb8 发表于 2014-1-15 12:58
有啊,比如有些初级的单片机教程里,在后台死循环判断接收标志位来,达到接收的目的…… ...

那是轮询操作,不是使用中断处理接收

使用特权

评论回复
20
科技猎人|  楼主 | 2014-1-15 13:24 | 只看该作者
咱们还是不要讨论中断处理这个问题了。暂时将我说的方法称为“时隙断句缓存接收法”,还有上面8楼提到的“循环队列缓存收法”可以讨论下这两种方式或者还有什么别的接收方法的优劣和适用范围。。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

31

主题

192

帖子

8

粉丝