当前位置:网站首页>串口接收数据方案设计
串口接收数据方案设计
2022-07-01 03:09:00 【风一样的航哥】
本篇文章是一篇经验笔记,记录下在工作中遇到的串口接收数据解析的策略。
本文以串口为例,但是也可以扩展到其他两个设备通信的地方,只要涉及到数据的传输和转移,就会有通信,只要通信的设备处理速率不同就会有缓存,只有有缓存,就会涉及到数据的组织形式,而先进先出的模式对应着现实世界大部分通信情况,队列成为了缓存的最佳选择。队列的大小与处理器有关,也与应用有关。合理的选择应当满足在每一包数据来的时候,有足够的空间来接收,并且程序能够在下一包数据来之前处理完缓存的数据并产生足够的空间。
串口接收数据本质上应该都是中断方式,但是处理数据上有所不同。
第一种模式:中断处理,中断处理是指解析处理函数放在中断回调函数中执行,适合小数据量。
第二种模式:查询处理,程序中没有延时,就查询是否有数据进来,当有数据来的时候再进行操作,这种情况适合接收指令的情况。
第一种模式:定时器模式,此种模式下知道发送方发送数据的周期,并且确定每一帧数据的长度,这样程序中使用相等时间的定时器每次来接收和处理相对应的信息。
在解析函数中,根据数据的接收情况会有几种情况;1,数据没有;2,数据有了但是只有一点,不够一帧的长度;3,恰好一帧的长度;4,超过一帧的长度,不足2帧;5,数据太多超过了缓存区域。
以上情况中,数据没有就什么也不做,等待数据就可以了;数据太多超过了缓存区,这种情况在设计和测试的时候就要考虑并且可以避免,不管是扩展缓存区,还是优化函数处理时间,或者降低发送方的频率。在实际程序运行过程中大部分都属于2-3-4的情况,4的情况处理完一帧之后,就变成了2的情况,所以主要是处理2-3这种情况,当数据有了但是这时候还不足一帧怎么办?
我的回答是继续等待,但是不是阻塞的等待,那样的话,接收方的主动权完全依赖于发送方。在每一帧数据的解析中,一般会有一些特征来提取,比如帧头,帧尾,长度,校验以及双方定义的特殊字符等。通信协议就是大家共同遵守的数据格式,解析是在协议的基础上进行的。如何等待呢?以以下字符为例子:
$CSDN,6,abcdef,07\r\n
上面所示的数据中,帧头为$CSDN,数据用逗号分割,第2段数据表示长度,第3段表示数据,第4段异或校验和,\r\n表示数据结尾。
当程序第一次查看接收数据的时候,可能只收到了$一个字节,这个可能是有效数据的开始也可能是一个乱码,我们先当做有效字符的开始来处理,记录在一个数组(这个数组表示我们将要解析的有效数据)中,当下一次检测的时候发现是C,这个时候我们继续将这个字符认为是有效数据添加的数组中,依次检测直到遇到回车换行,这个时候认为接收了完整的一帧,然后进行检验和其他处理;如果数据中发送了错误比如$CSE,即第四位传输错误不满足头的时候,或者校验不通过我们认为数据发生了异常,清空数组,继续接收并寻找帧头。那我们如果记录当前接收数据的状态呢?既然已经提到了状态,那自然就能想到这是一个状态机,从没有数据---有数据--完整数据---处理了---没有数据之间发生不断的跳转。于是这样就可以实现了。
让我们再增加一点难度,如果数据格式种多样,长度不一,帧头帧尾各不相同怎么处理呢?以上提到的方法还能适用吗?
先说我的理解,上面的方式还是可以使用的,要做一些变化和扩展。要考虑到所有的数据格式,并对接收到数据匹配各种可能的帧头,只要数据帧头和帧尾匹配上了,就认为是一帧完整数据,校验和解析随后进行。
当数据格式很多的时候,存在两种情况,一种是交互式,一种是纯接收式,如何做到不重不漏才是难点。这些细节就靠编程的实现和经验来解决了。
不管是面向过程还是面向对象的方式,实现上述功能难度都是一样的。而对字符串的解析函数推荐一个C语言库的strtok函数,
#include <string.h>
#include <stdio.h>
int main () {
char str[80] = "This is - www.runoob.com - website";
const char s[2] = "-";
char *token;
/* 获取第一个子字符串 */
token = strtok(str, s);
/* 继续获取其他的子字符串 */
while( token != NULL ) {
printf( "%s\n", token );
token = strtok(NULL, s);
}
return(0);
}运行结果:
This is
www.runoob.com
website非常方便好用,不过要注意指针数组等不要越界,否则hardfault也挺烦人的。
边栏推荐
- Od modify DLL and exe pop-up contents [OllyDbg]
- 实战 ELK 优雅管理服务器日志
- Communication protocol -- Classification and characteristics Introduction
- Force buckle - sum of two numbers
- 世界上最好的学习法:费曼学习法
- [linear DP] longest common subsequence
- 【小程序项目开发-- 京东商城】uni-app之首页商品楼层
- Golang多图生成gif
- 咱就是说 随便整几千个表情包为我所用一下
- [applet project development -- Jingdong Mall] user defined search component of uni app (Part 1)
猜你喜欢

Overview of EtherCAT principle

HTB-Lame

Cloud native annual technology inventory is released! Ride the wind and waves at the right time

servlet【初识】

Design practice of current limiting components

几行事务代码,让我赔了16万
![[linear DP] longest common subsequence](/img/47/c3172422e997009facbada929adb1a.jpg)
[linear DP] longest common subsequence

Druid monitoring statistics source

Edge Drawing: A combined real-time edge and segment detector 翻译

Example of Huawei operator level router configuration | example of configuring optionc mode cross domain LDP VPLS
随机推荐
[applet project development -- Jingdong Mall] user defined search component of uni app (Part 1)
xxl-job使用指南
Chapitre 03 Bar _ Gestion des utilisateurs et des droits
If a parent class defines a parameterless constructor, is it necessary to call super ()?
Restcloud ETL WebService data synchronization to local
EtherCAT简介
MySQL knowledge points
How do spark tasks of 10W workers run? (Distributed Computing)
Detailed explanation of pointer array and array pointer (comprehensive knowledge points)
Restcloud ETL practice data row column conversion
性能测试常见面试题
世界上最好的学习法:费曼学习法
UE4 rendering pipeline learning notes
About the application of MySQL
[linear DP] longest common subsequence
A few lines of transaction codes cost me 160000 yuan
Redis 教程
Ctfshow blasting WP
如何校验两个文件内容是否相同
# 使用 KubeKey 搭建 Kubernetes/KubeSphere 环境的'心路(累)历程'