STM32 USART串口数据包
单片机学习!
目录
前言
一、数据包
二、HEX数据包
三、文本数据包
四、HEX数据包和文本数据包优缺点
4.1 HEX数据包
4.2 文本数据包
五、HEX数据包接收
六、文本数据包接收
总结
前言
本文介绍了串口数据包收发的思路和流程。
一、数据包
数据包的作用是把一个个单独的数据给打包起来,方便进行多字节的数据通信。之前串口的代码就是发送一个字节,接收一个字节,都可以实现。但在实际应用中可能需要把多个字节打包为一个整体进行发送。
例如用陀螺仪传感器,需要串口发送数据到STM32.陀螺仪的数据为X轴一个字节,Y轴一个字节,Z轴一个字节,总共3个数据需要连续不断地发送。如果像这样XYZXYZXYZ连续发送的时候,就会出现一个问题,就是接收方不知道这些数据哪个对应X、哪个对应Y、哪个对应Z,因为接收方可能会从任意位置开始接收,所以会出现数据错位的现象。
这时候就需要研究一种方式,把数据进行分割,就是把XYZXYZXYZ这一串数据分割开,分成一个个数据为XYZ数据包。这样再接收的时候就知道。
- 数据包的第一个数据就是X,
- 数据包的第二个数据就是Y,
- 数据包的第三个数据就是Z。
以上是数据包的任务,就是把属于同一批的数据进行打包和分割,方便接收方进行识别。一串数据如何进行分割打包,需看实际情况来决定,只要逻辑行的通,可以发挥想象力来设计。
比如可以给XYZXYA数据流中设计数据包的第一个数据,也就是X的数据包,把它的最高位,置为1。其余数据包的最高位,都置为0。当接收到数据之后,判断一下最高位,如果是1,那就是X数据,然后紧跟着的两个数据就分别是Y和Z。这就是一种可行的分割方法,这种方法就是把每个数据位的最高位当做标志位来进行分割的。实际也有应用的例子,比如UTF8的编码方法和这种类似,当然UTF8要更高级一些。
二、HEX数据包
本节主要讲的数据包分割方法并不是在数据的高位添加标志位这种方式,因为这种方式破坏了原有数据,使用起来比较复杂。串口数据包通常使用的是额外添加包头包尾这种方式。比如图中列举的两种数据包格式:
第一种是固定包长,含包头包尾。也就是每个数据包的长度都固定不变。数据包前面是包头,后面是包尾。
第二种是可变包长,含包头包尾。也就是每个数据包的长度可以是不一样的,数据包前面是包头,后面是包尾。
这两种的数据包格式可以是用户根据需求来规定,也可以是买一个模块,别的开发者规定。比如在这里规定一批数据有4个字节。
- 在这4个字节之前,加一个包头,定义0xFF为包头;
- 在这4个字节之后,加一个包尾,定义0xFE为包尾。
当接收到0xFF之后就知道一个数据包来了,接着再接收到的4个字节就当作数据包的第1、2、3、4个数据,存在一个数组里。
最后跟一个包尾,当接收到0xFE之后就可以置一个标志位,告诉程序收到了一个数据包。然后新的数据包过来,再重复之前的过程。这样就可以在一个连续不断的数据流中分割出需要的数据包了。这就是通过添加包头包尾实现数据分割打包的思路。
以下来研究几个问题:
第一个问题是,包头、包尾和数据载荷重复的问题。
假设定义FF为包头,FE为包尾,如果传输的数据本身就是FF和FE怎么办呢?也就是发生包头、包尾和数据载荷重复的问题,会引起误判。
对应这个问题有如下几种解决方法:
- 第一种,限制载荷数据的范围,如果可以的话,在数据发送的时候对数据进行限幅。比如XYZ这3个数据,变化范围都可以是0~100.那就可以在载荷中只发送0~100的数据,数据中就不会有FF和FE这样的值存在,这样就不会和包头、包尾重复了。
- 第二种,如果无法避免载荷数据和包头、包尾重复,那就尽量使用固定长度的数据包。由于载荷数据是固定的,只要通过包头、包尾对齐了数据,就可以严格知道哪个数据应该是包头,哪个数据应该是包尾,哪个数据应该是载荷数据。在接收载荷数据的时候,并不会判断它是否是包头或者包尾;而在接收包头包尾的时候,会判断它是不是确实是包头包尾,用于数据对齐。这样在经过几个数据包的对其之后,剩下的数据包应该就不会出现问题了。
- 第三种,就是增加包头包尾的数量,并且让它尽可能呈现出载荷数据出现不了的状态。比如使用FF、FE作为包头,FD、FC作为包尾。这样也可以避免载荷数据和包头包尾重复的情况发生。
第二个问题是,包头、包尾是不是全部都需要呢?
包头、包尾并不是全部都需要。
比如可以只要一个包头,把包尾删掉,这样数据包的格式就是,1个包头FF加4个数据。当检测到FF就开始接收,收够4个字节后置标志位,一个数据包接收完成。
不过这种方式会有弊端,载荷和包头重复的问题会更严重一些。比如最严重的情况下,载荷全是FF,包头也是FF。那肯定不知道哪个是包头了。而加上FE作为包尾,无论数据怎么变化,都是可以分辨出包头和包尾的。
第三个问题是,固定包长和可变包长的选择问题。
对应HEX数据包来说:
如果载荷会出现和包头、包尾重复的情况,那就最好选择固定包长,这样可以避免接收错误。如果载荷会出现和包头、包尾数据重复的情况下,又选择了变包长,那一个数据包的包头包尾就有了不确定性,相应的数据包的长度也会有影响,这就会导致数据乱套。
如果载荷不会和包头、包尾重复,那可以选择可变包长。数据长度如4位、3位、1位、10位等等,来回任意变肯定都没问题。因为包头、包尾是唯一的。只要出现包头,就开始数据包;只要出现包尾,就结束数据包。这样就非常灵活。
第四个问题是,各种数据转换为字节流的问题。
这里的数据包都是一个字节一个字节组成的。如果想发送16位的整型数据、32位的整型数据、float、double甚至是结构体其实都没问题。因为它们内部其实都是由一个字节一个字节组成的,只需要用一个uint8_t的指针指向它,把它们当作一个字节数组发送就可以了。
三、文本数据包
文本数据包和HEX数据包就分别对应了文本模式和HEX模式这两种模式。
- 在HEX数据包里面,数据都是以原始的字节数据本身呈现的。
- 在文本数据包里面,每个字节就经过了一层编码和译码,最终表现出来的就是文本格式。
但实际上,每个文本字符的背后其实都还是一个字节的HEX数据。
文本数据包同样举例固定包长和可变包长这两种模式。由于数据译码成了字符形式,这就会存在大量的字符可以作为包头和包尾。可以有效避免载荷和包头包尾重复的问题。
比如图中规定的就是以@这个字符作为包头;以\r和\n,也就是换行,这两个字符作为包尾。在载荷数据中间可以出现除了包头包尾的任意字符。所以文本数据包基本不用担心载荷数据和包头、包尾重复的问题,使用非常灵活。可变包长、各种字母、符号、数字都可以随意使用。
当接收到载荷数据之后得到的就是一个字符串,在软件中再对字符串进行操作和判断,就可以实现各种指令控制的功能了。而且字符串数据包表达的意义很明显,可以把字符串数据包直接打印到串口助手上,什么指令、什么数据一眼就能看明白。所以这个文本数据包通常会以换行作为包尾。这样在打印的时候就可以一行一行地显示了,非常方便。
四、HEX数据包和文本数据包优缺点
HEX数据包和文本数据包这两种对比下来,其实也是各有优缺点。需要根据实际场景来选择和设计数据包格式。
4.1 HEX数据包
- 优点是传输最直接,解析数据非常简单,比较适合一些模块发送原始的数据。比如一些使用串口通信的陀螺仪、温湿度传感器。
- 缺点是灵活性不足,载荷数据容易和包头、包尾重复。
4.2 文本数据包
- 优点是数据直观易理解,非常灵活,比较适合一些输入指令进行人机交互的场合,比如蓝牙模块常用的AT指令、CNC和3D打印机常用的G代码,都是文本数据包的格式。
- 缺点是解析效率低,比如发送一个数100,HEX数据包就是一个字节100,完事;文本数据包就得是3个字节的字符:1、0、0,收到之后还要把字符转换成数据,才能得到100.
五、HEX数据包接收
本节来看一下数据包收发流程。
首先是数据包的发送,数据包的发送比较简单。
- 在HEX数据包这里,如果想发送一个数据包,就定义一个数组,填充数据,然后用SendArray函数一发就完事了。
- 在文本数据包这里,写一个字符串,然后调用SendString函数一发送也就完事了。
所以说发送数据包简单,是因为发送过程完全是自主可控的,想发啥就发啥,写代码的时候也能感受到,串口发送比串口接收简单多了。
接收一个数据包就比较复杂了。这里演示固定包长HEX数据包的接收方法和可变包长文本数据包的接受方法。其他的数据包也都可以套用这个形式。写数据包接收的程序就会根据这里面的流程来。
先看一下如何接收固定包长HEX数据包根据上一章博文的代码可以知道,每收到一个字节程序都会进一遍中断。在中断函数里,可以拿到这一个字节。但拿到字节之后就得退出中断了,所以每拿到一个数据都是一个独立的过程。
STM32 USART串口发送+接收_配置stm32的usart串口参数,编写程序实现数据的发送和接收-CSDN博客https://blog.csdn.net/Echo_cy_/article/details/143817933
而对于数据包来说它具有前后关联性,包头之后是数据,数据之后是包尾。对于包头、数据和包尾这3种状态,需要有不同的处理逻辑。
所以在程序中需要设计一个能记住不同状态的机制,在不同状态执行不同的操作,同时还要进行状态的合理转移。这种程序设计思维就叫做状态机。在这里就使用状态机的方法来接收一个数据包。
要想设计一个好的状态机程序,画一个状态转移图是必要的。如图所示,对于图中这样一个固定包长HEX数据包来说,可以定义3个状态。
- 第一个状态是等待包头、
- 第二个状态是接收数据、
- 第三个状态是等待包尾。
每个状态需要用一个变量来标志一下,比如这里用变量S来标志,三个状态依次为S=0、S=1、S=2这一点类似于置标志位。只不过标志位只有0和1,而状态机是多标志位状态的一种方式。
执行流程:
第一个状态:最开始S=0,收到一个数据,进中断,根据S=0,进入第一个状态的程序,判断数据是不是包头0xFF。如果是0xFF则代表收到包头。之后置S=1,退出中断,结束。这样下次再进中断,根据S=1,就可以进行接收数据的程序了。那在第一个状态,如果收到的不是0xFF,就证明数据包没有对齐,应该等待数据包包头的出现。这时状态仍然是0。下次进中断,就还是判断包头的逻辑。直到出现0xFF才能转到下一个状态。
第二个状态:那之后出现了0xFF,就可以转移到接收数据的状态了。这时再收到数据,就直接把它存在数组中。另外再用一个变量,记录收了多少个数据。如果没收到4个数据,就一直是接收状态。如果收够了,就置S=2,下次进中断时就可以进入下一个状态了。
第三个状态:最后一个状态就是等待包尾了,判断数据是不是0xFE,正常情况,应该是0xFE,这样就可以置S=0,回到最初的状态,开始下一个轮回。当然也有可能这个数据不是0xFE,比如数据和包头重复,导致包头位置判断错了。那这个包尾位置就有可能不是0xFE,这时就可以进入重复等待包尾的状态,直到接收到真正的包尾。这样加入包尾的判断,更能预防因数据和包头重复造成的错误。
以上就是使用状态机接收数据包的思路。
状态机其实是一种很广泛的编程思路,在很多地方都可以用到。使用的基本步骤是,先根据项目要求定义状态,画几个圈。然后考虑好各个状态在什么情况下会进行转移,如何转移,画好线和转移条件。最后根据这个图来进行编程。这样思维就会非常清晰了。
六、文本数据包接收
可变包长文本数据包的接收流程同样也是利用状态机,定义3个状态。
第一个状态,等待包头,判断收到的是不是规定的@符号。如果收到@就进入到第二个状态。
第二个状态,接收状态。在接收状态下依次接收数据。同时,第二个状态还应该要兼具等待包尾的功能。因为这是可变包长,接受数据的时候也要时刻监视,是不是收到包尾了。一旦收到包尾就结束。这个状态的逻辑就应该是收到一个数据,判断是不是\r。
- 如果不是\r,则正常接收;
- 如果是\r,则不接收,同时跳到下一个状态,等待包尾\n。
第三个状态,因为这里数据包有两个包尾\r和\n所以需要第三个状态。如果只有一个包尾,那在出现包尾之后就可以直接回到初始状态了,只需要两个状态就行。因为接收数据和等待包尾需要在一个状态里同时进行。由于串口的包头、包尾不会出现在数据中,所以基本不会出现数据错位的现象。
以上就是使用状态机接收文本数据包的方法。
总结
以上就是今天要讲的内容,本文仅仅简单介绍了接收数据包的思路。
相关文章:

STM32 USART串口数据包
单片机学习! 目录 前言 一、数据包 二、HEX数据包 三、文本数据包 四、HEX数据包和文本数据包优缺点 4.1 HEX数据包 4.2 文本数据包 五、HEX数据包接收 六、文本数据包接收 总结 前言 本文介绍了串口数据包收发的思路和流程。 一、数据包 数据包的作用是把一个个单独…...
【LC】3232. 判断是否可以赢得数字游戏
题目描述: 给你一个 正整数 数组 nums。 Alice 和 Bob 正在玩游戏。在游戏中,Alice 可以从 nums 中选择所有个位数 或 所有两位数,剩余的数字归 Bob 所有。如果 Alice 所选数字之和 严格大于 Bob 的数字之和,则 Alice 获胜。如果…...

Linux基础学习--vi与vim
0.绪论 前面的内容基本学完了相关命令行,后面进行shell与shell script的学习。第一部分就是编辑器的学习,之前有写过vi/vim编辑器,但是我看了一下鸟哥这个非常详细,还是打算重头学习一下。 1.vi/vim的使用 一般命令模式(command…...
JavaScript 高级教程:异步编程、面向对象与性能优化
在前两篇教程中,我们学习了 JavaScript 的基础和进阶内容。这篇文章将带领你进入更深层次,学习 JavaScript 的异步编程模型、面向对象编程(OOP),以及性能优化的技巧。这些内容对于构建复杂、流畅的前端应用至关重要。 …...

qt QToolBox详解
1、概述 QToolBox是Qt框架中的一个控件,它提供了一个带标签页的容器,用户可以通过点击标签页标题来切换不同的页面。QToolBox类似于一个带有多页选项卡的控件,但每个“选项卡”都是一个完整的页面,而不仅仅是标签。这使得QToolBo…...
翁知宜荣获“易学名师”与“国学文化传承人”称号
在2024年10月19日举行的北京第六届国学文化传承峰会上,翁知宜老师以其在易学界的卓越成就和对国学文化的传承与发扬,荣获“易学名师”和“国学文化传承人”两项荣誉称号。 翁知宜老师在易经学术竞赛中荣获第一名,其深厚的易学造诣和对玄学学…...

20241128解决Ubuntu20.04安装libwxgtk3.0-dev异常的问题
20241128解决Ubuntu20.04安装libwxgtk3.0-dev异常的问题 2024/11/28 16:17 缘起:中科创达的高通CM6125开发板的Android10的编译环境需要。 安装异常:rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ sudo apt-get install libwxgtk3.0-de…...
sql分类
SQL(Structured Query Language)是一种用于管理和操作关系数据库管理系统(RDBMS)的编程语言。SQL 可以分为几个主要类别,每个类别都有其特定的用途和功能。以下是 SQL 的主要分类: 1. 数据定义语言&#x…...
stm32里一个定时器可以提供多路信号吗?
在STM32中,一个定时器通常只能提供一组信号(如输出PWM波形、定时中断等)。但是,定时器的多个通道可以提供不同的信号。例如,STM32的定时器可以通过不同的输出通道产生多种PWM信号,每个通道可以配置为不同的…...

Java安全—原生反序列化重写方法链条分析触发类
前言 在Java安全中反序列化是一个非常重要点,有原生态的反序列化,还有一些特定漏洞情况下的。今天主要讲一下原生态的反序列化,这部分内容对于没Java基础的来说可能有点难,包括我。 序列化与反序列化 序列化:将内存…...
2023考研王道计算机408数据结构+操作系统+计算机组成原理+计算机网络
from: https://blog.csdn.net/weixin_46118419/article/details/125611299 写得很好! 轻重缓急 2023考研计算机408【王-道计算机408】数据结构操作系统计算机组成原理计算机网络 网盘-链接:https://pan.baidu.com/s/13JraxUYwNVPeupdzprx5hA?pwd5h3d 提…...
YOLOv8-ultralytics-8.2.103部分代码阅读笔记-files.py
files.py ultralytics\utils\files.py 目录 files.py 1.所需的库和模块 2.class WorkingDirectory(contextlib.ContextDecorator): 3.def spaces_in_path(path): 4.def increment_path(path, exist_okFalse, sep"", mkdirFalse): 5.def file_age(path__fi…...

「Mac畅玩鸿蒙与硬件34」UI互动应用篇11 - 颜色选择器
本篇将带你实现一个颜色选择器应用。用户可以从预设颜色中选择,或者通过输入颜色代码自定义颜色来动态更改界面背景。该应用展示了如何结合用户输入、状态管理和界面动态更新的功能。 关键词 UI互动应用颜色选择器状态管理用户输入界面动态更新 一、功能说明 颜色…...

ELK(Elasticsearch + logstash + kibana + Filebeat + Kafka + Zookeeper)日志分析系统
文章目录 前言架构软件包下载 一、准备工作1. Linux 网络设置2. 配置hosts文件3. 配置免密登录4. 设置 NTP 时钟同步5. 关闭防火墙6. 关闭交换分区7. 调整内存映射区域数限制8. 调整文件、进程、内存资源限制 二、JDK 安装1. 解压软件2. 配置环境变量3. 验证软件 三、安装 Elas…...

07.ES11 08.ES12
7.1、Promise.allSettled 调用 allsettled 方法,返回的结果始终是成功的,返回的是promise结果值 <script>//声明两个promise对象const p1 new Promise((resolve, reject) > {setTimeout(() > {resolve("商品数据 - 1");}, 1000)…...

linux一键部署apache脚本
分享一下自己制作的一键部署apache脚本: 脚本已和当前文章绑定,请移步下载(免费!免费!免费!) (单纯的分享!) 步骤: 将文件/内容上传到终端中 …...
2022 年 6 月青少年软编等考 C 语言三级真题解析
目录 T1. 制作蛋糕思路分析T2. 找和最接近但不超过K的两个元素思路分析T3. 数根思路分析T4. 迷信的病人思路分析T5. 算 24思路分析T1. 制作蛋糕 小 A 擅长制作香蕉蛋糕和巧克力蛋糕。制作一个香蕉蛋糕需要 2 2 2 个单位的香蕉, 250 250 250 个单位的面粉, 75 75 75 个单位的…...

MySQL - Why Do We Need a Thread Pool? - mysql8.0
MySQL - Why Do We Need a Thread Pool? - mysql8.0 本文主要由于上次写的感觉又长又臭, 感觉学习方法有问题, 我们这次直接找来了 thread pool 的原文,一起来看看官方的开发者给出的blog – 感觉是个大神 但是好像不是最官方的 ,…...
Linux互斥量读写锁
一、互斥量 1.临界资源 同一时刻只允许一个进程/线程访问的共享资源(比如文件、外设打印机) 2.临界区 访问临界资源的代码 3.互斥机制 mutex互斥锁,用来避免临界资源的访问冲突,访问临界资源前申请互斥锁,访问完释放…...
网络安全之IP伪造
眼下非常多站点的涉及存在一些安全漏洞,黑客easy使用ip伪造、session劫持、xss攻击、session注入等手段危害站点安全。在纪录片《互联网之子》(建议搞IT的都要看下)中。亚伦斯沃茨(真实人物,神一般的存在)涉…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...