USART串口数据包

USART串口数据包

在这里插入图片描述
先来看两张图,本次程序是串口收发HEX数据包,第二种是串口收发文本数据包,之后两个图,展示的就是接收数据包的思路。

在PB1这里接了一个按键,用于控制。在串口助手,在发送模式和接收模式都选择HEX模式。
在OLED显示这样的数据包,在串口助手这,也显示接收到了这个数据包。

在这里插入图片描述
这个数据包有个规定的格式,就是以FF为包头,FE为包尾,中间固定4个字节为数据,这是STM32发送数据包。
STM32发送数据包:可以在串口助手的发送区,发送一个数据包给STM32,也是同样的格式,以FF开头,中间4个数据为用户数据,最后以FE结尾。

在这里插入图片描述

第二个程序串口收发文本数据包:在串口助手这的发送模式和接收模式都选择文本模式,这个程序我们要发送一个文本数据包,数据包的格式也是个人规定的,此次规定的是,以@符号为包头,中间是数据,如,@LED_ON ,数据也是规定好的指令,最后以换行符为包尾。

可以看到OLED显示接收到了LED_ON,led点亮,然后STM32回传一个字符串LED_ON_OK。如随便给个指令,STM32也能收到,但是返回ERROR_COMMAND,错误指令。

HEX数据包

在这里插入图片描述
在这里插入图片描述

先看—下HEX数据包格式。首先数据包是一种将单独的数据打包起来,整体进行传输的方式,方便进行多字节的通信。在实际应用中,可能需要把多个字节打包成一个整体进行发送。

比如说,我们有个陀摆仪传感器,需要用串口发送数据到STM32,陀螺仪的数据,比如X
轴一个字节、Y轴一个字节、Z轴一个字节,总共3个数据,需要连续不断地发送,但当你像这样XYZ XYZ XYZ这样连续发送的时候,就会出现一个问题,就是接收方,三不知道这数据哪个对应X哪个对应Y、哪个对应Z。因为接收方可能会从任意位置开始接收,所以会出现数据错位的现象。

解决这个现象:就是把这个数据进行分割,把XYZ 分成一个个数据包,这样接收的时候就知道了,数据包的第一个数据是X,数据包的第二个数据是Y,数据包的第三个数据是Z,这就是数据包的任务,就是把同一批的数据进行打包和分割,方便接收方进行识别,

比如,在XYZXYZ数据流中,我们可以在数据包第一个数据,也就是x的数据包上将最高位置1作为标志位,其余数据包最高位置0,当接收到的数据后,判断一下最高位,如果是1,那就是x数据,然后紧跟着的两个数据就分別是Y和Z,这是一种分割方法。**总结:这种方法是把每个数据的最高位当做标志位来进行分割的。**实际例子:如UTF8的编码方法。

本节,讲数据包分割方法,并不是在数据的高位添加标志位这种方式,这种方式破坏了原有的数据,使用起来比较复杂。

我们串口数据包,通常使用的是额外添加包头包尾的这种方式。数据包有2种格式:固定包长,就是每个数据包长度都固定不变,每个数据包前面是包头,后面是包尾。第2种是,可变包长,就是每个数据包长度可以是不一样,我们可以根据用户需求自行规定数据包格式。

例如,我们可以规定一批数据有4个字节,在4个字节之前添加包头0xFF,在之后添加包尾OXFE。当我们接收到OxFF时,就知道一个数据包来了,接萶接收到的4个字节就作为数据包的第1. 2.3.4个数据存储在数组中,最后接收到包尾OxFE时,就可以置一个标志位,告诉程序收到了一个数据包。这样就可以在一个连续不断的数据流中分割出我们想要的数据包了。这就是通过添加包头包尾实现数据分割打包的思路,

接着研究几个问题

第一个问题:包头包尾和数据载荷重复的问题,这里定义FF为包头,FE为包尾,如果我传输的数据本身就是FF和FE怎么办呢?那这个问题确实存在,如果数据和包头包尾重复,可能会引起误判。对应这个问题我们有如下几种解决方法

第一种,限制载荷数据的范围。如果可以的话,我们可以在发送的时候,对数据进行限幅。比如XYZ,3个数据,变化范围都可以是0~100 那就好办了,我们可以在载荷中只发送0-100的数据,这样就不会和包头包尾重复了。

第二种,如果无法避免载荷数据和包头包尾重复,那我们就尽量使用固定长度的数据包。这样由于载荷数据是固定的,只要我们通过包头包尾对齐了数据,我们就可以严格知道,哪个数据应该是包头包尾,哪个数据应该是载荷数据。
在接收载荷数据的时候,我们并不会判断它是否是包头包尾,而在接收包头包尾的时候,我们会判断它是不是确实是包头包尾,用于数据对齐。这样,在经过几个数据包的对齐之后,剩下的数据包应该就不会出现问题了。

第三种,增加包头包尾的数量,并且尽量让它呈现出载荷数据出现不了的状态。比如我们使用FF、FE作为包头,FD、FC作为包尾,这样也可以避免载荷数据和包头包尾重复的情况发生。

第二个问题这个包头包尾并不是全部都需要的,比如我们可以只要一个包头,把包尾删掉,这样数据包的格式就是,一个包头FF,加4个数据,这样也是可以的。
当检测到FF,开始接收,收够4个字节后,置标志位,一个数据包接收完成,这样也可以。不过这样的话,载荷和包头重复的问题会更严重一些,比如最严重的情况下,我载荷全是FF,包头也是FF,那你肯定不知道哪个是包头了,而加上了FE作为包尾,无论数据怎么变化,都是可以分辨出包头包尾的。

第三个问题固定包长和可变包长的选择问题
对应HEX数据包来说,如果你的载荷会出现和包头包尾重复的情况,那就最好选择固定包长,这样可以避免接收错误。如果你又会重复,又选择可变包长那数据很容易就乱套了。
如果载荷不会和包头包尾重复,那可以选择可变包长,数据长度,像这样,4位、3位、等等,1位、10位,来回任意变,肯定都没问题。因为包头包尾是唯一的,只要出现包头,就开始数据包,只要出现包尾,就结束数据包,这样就非常灵活了,这就是固定包长和可变包长选择的问题。

第四个问题各种数据转换为字节流的问题。这里数据包都是一个字节一个字节组成的,如果你想发送16位的整型数据、32位的整型数据,float、double,甚至是结构体,其实都没问题,因为它们内部其实都是由一个字节一个字节组成的,只需要用一个uint8_t的指针指向它,把它们当做一个字节数组发送就行了。

文本数据包

在这里插入图片描述
这里我同样介绍了固定包长可变包长这两种模式。由于数据被译码成字符形式,因此存在大量字符可以作为包头和包尾,这可以有效避免载荷和包头包尾重复的问题。
例如,以@字符作为包头,以’\r’ '\n’换行符作为包尾,在载荷数据中间允许出现除了包头包尾外的任意字符。这样,文本数据包不用担心载荷和包头包尾重复的问题,使用非常灵活。无论是可变包长还是各种字母、符号、数字,都可以随意使用。

当我们接收到载荷数据时,得到的是一个字符串。在软件中对字符串进行操作和判断,可以实现各种指令控制的功能。此外,字符串数据包的表达意义明显,可以把字符串数据包直接打印到串口助手上,很明显能看出指令和数据。所以这个文本数据包,通常以换行作为包尾,文本数据包通常以
便在打印时逐行显示。

对比HEX数据包和文本数据包,各有优缺点。HEX数据包的优势在于,传输最直接,解析数据简单,适合一些模块发送原始数据,比如使用串口通信的陀摆仪,温温度传感器。其缺点灵活性不足,载荷容易和包头包尾重复。

文本数据包的优点在于,数据直观易于理解,比较适台输入指令进行人机交互的场合。
例如,蓝牙模块常用的AT指令、CNC和3D打印机常用的G代码都是文本数据包的格式,然而,其缺点是解析效率低。

例如,发送数字100时,HEX数据包只需一个字节100即可,而文本数据包则需要三个字节的字符’1,“0,0。收到后还需字符转换为,数据才能得到100。所以,需要根据实际场景来选择和设计数据包格式。数据包格式定义。

数据包收发流程

在这里插入图片描述
首先,发送数据包的过程相对简单。在发送HEX数据包时,可以通过定义一个数组,填充数据,然后使用之前我们写过的SendArray函数发送即可。
在发送文本数据包时,可以通过写一个字符串,然后调用SendString函数发送。因此,发送数据包的过程是可控的,我们可以根据需要发送任何类型的数据包。

接收一个数据包,比较复杂了,这里是固定包长HEX数据包的接收方法,和可变包长文本数据包的接收方法,其他的数据包也都可以套用这个形式,等会儿我们写程序就会根据这里面的流程来。

我们先看一下如何来接收这个固定包长的HEX数据包。要接收固定包长的HEX数据包,我们需要设计一个状态机来处理。根据之前的代码,我们知道每当收到一个字节,程序会进入中断。在中断函数里,我们可以获取这个字节,但获取后需要退出中断。因此,每个收到的数据都是独立的过程,而数据包则具有前后关联性,包括包头、数据和包尾。为了处理这三种状态,我们需要设计一个能够记住不同状态的机制,并在不同状态下执行不同的操作,同时进行状态合理转移。这种程序设计思维就是“状态机”

在这里我们就使用状态机的方法来接收—个数据包,要想设计一个好的状态机程序,画一个这样的状态转移因是必要的。

我们看一下,对于下面这样—个固定包长HEX数据包来说,我们可以定义3个状态,第一个状态是等待包头,第二个状态是收数据,第三个状志是等待包尾,每个状态需要用一个变量来标志一下,比如我这里用变量S来标志,三个状态依次为S=0 S=1 S=2,这一点类似于置标志位,只不过标志位只有0和1,而状态机是多标志位状态的一种方式。

执行流程是:

对于固定包长的HEX数据包,我们可以定义三个状态:等待包头.接收数据,等待包尾。每个状态都可以用一个变量来标志,例如变量S来表示。这三个状态可以依次定义为S=0、 S=1. S=2。类似于置标志位,但标志位只有0和1,而状态机允许多标志位状态。

初始时,S=0表示等待包头状态。当中断发生时,根据S=0的状态,程序会进入等待包头的逻辑。判断数据是不是包头FF,如果收到的数据是FF(包头),则将状态设置为S=1并退出中断。下次再进中断,然后根据S=1的状态,进行接收数据的程序。如果收到的不是FF,就证明数据包没有对齐,那么需要继续等待包头出现,状态保持为S=0。下次中断,还是判断包头的逻辑,直到出现FF,才能转到下一个状态。

当收到FF(包头)后,状态会转移到S=1(接收数据状态)。在此状态下,接收到的数据会被存储在数组中,并记录己收到的数据数量。如果没接收到4个数据,就一直是接收状态,当收到4个数据后,将状态设置为S=2(等待包尾状态)。

在等待包尾状态下(S=2),判断数据是不是FE, 程序会等待收到FE(包尾)。如果收到FE,则将状态重置为S=0(等待包头状态),开始下一个数据包的接收,开启轮回 。如果收到的不是FE,那么需要进入重复等待包尾的状态,直到接收到真正的包尾。

这就是使用状态机接收数据包的思路。这个状态机其实是一种很广泛的编程思路,在很多地方都可以用到,使用的基本步骤是,先根据项目要求定义状态,画几个圈,然后考虑好各个状态在什么情况下会进行转移,如何转移,画好线和转移条件,最后根据这个图来进行编程,这样思维就会非常清晰了。

文本数据包

在这里插入图片描述

同样也是利用状态机,定义3个状态。第一个状态,等待包头,判断收到的是不是我们规定的⑨符号,如果收到@,就进入接收状态,在这个状态(S=1)下,依次接收数据,同时,这个状态还应该要兼具等待包尾的功能。因为这是可变包长,我们接收数据的时候,也要时刻监视.是不是收到包尾了,一但收到包尾了,就结束。

那这里(S=2),这个状态的逻辑就应该是,收到一个数据,判断是不是\r,如果不是,则正常接收,如果是,则不接收,同时跳到下一个状态,等待包尾\n,因为我这里数据包有两个包尾\r\n,所以需要第三个状态,如果只有一个包尾,那在出现包尾之后,就可以直接回到初始状态了,只需要两个状态就行,因为接收数据和等待包尾需要在一个状态里同时进行,由于串口的包头包尾不会出现在数据中,所以基本不会出现数据错位的现象,这就是使用状态机接收文本数据包的方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/667654.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Satellite Stereo Pipeline学习

1.在Anaconda某个环境中安装s2p pip install s2p 2.在Ubuntu系统中安装s2p源代码 git clone https://github.com/centreborelli/s2p.git --recursive cd s2p pip install -e ".[test]" 3.在s2p中进行make all处理 中间会有很多情况,基本上哪个包出问题…

基于昇腾910B训练万亿参数的语言模型简介

基于昇腾910B训练万亿参数的语言模型 Abstract 在本工作中,作者开发了一个系统,该系统在Ascend 910 AI处理器集群和MindSpore框架上训练了一个万亿参数的语言模型,并提出了一个含有1.085T参数的语言模型,名为PanGu-。 从PanGu-[…

Java18+​App端采用uniapp+开发工具 idea hbuilder智能上门家政系统源码,一站式家政服务平台开发 家政服务(师傅端)介绍

Java18​App端采用uniapp开发工具 idea hbuilder智能上门家政系统源码,一站式家政服务平台开发 家政服务(师傅端)介绍 家政服务师傅端是一个专为家政服务人员设计的平台,该平台旨在提供便捷、高效的工作机会,同时确保…

社交媒体数据恢复:QQ空间

本教程将指导您如何恢复QQ空间中的说说、日志和照片等内容。请注意,本教程不涉及推荐任何数据恢复软件。 一、恢复QQ空间说说 登录您的QQ账号,并进入QQ空间。点击“日志”选项,进入空间日志页面。在空间日志页面,您会看到一个“…

报表工具DataEase技术方案(一)

一、使用场景: 企业内部系统想要快速接入报表功能,但是局限于人力资源不足,不想沿用传统的前端后端开发模式,可以尝试使用开源报表工具 DataEase。 二、架构设计: 使用最简便的报表集成方式,通过DataEase…

区块链合约开发流程

区块链合约开发,尤其是以太坊智能合约开发,是一个多步骤的过程,从需求分析到部署和维护,每一步都需要仔细规划和执行。以下是详细的开发流程。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合…

CANDela studio新建和编辑服务

服务定义和编辑只能够在CDDT里面进行,思路分为三步: 1、Protocol Services里面添加服务,定义服务的格式、请求和正负响应。 2、根据服务的功能归类到Diagnostic Class Tenplates 3、Variant里面的Supported Diagnostic Classes勾选 然后我…

汽车IVI中控开发入门及进阶(二十四):杰发科技AC8015

前言: 在此之前的大部分时间,四维图新更多的是以图商的身份在业内出现,但现在四维图新图商之外的技术积累提现在了杰发科技身上,或者是从图商到汽车智能化一体解决方案供应商的角色转变。汽车智能化,可以简单的归为座舱智能化和智能驾驶两个板块。 随着汽车变得越来越智能…

AMS 仿真 ERROR

ERROR (OSSHNL-514): Netlist generation failed because of the errors reported above. The netlist might not have been generated at all, or the generated netlist could be corrupt. Fix the reported errors and regenerate the netlist. 原因:用的incisi…

Facebook开户|Facebook广告投放指南

家人们中午好~今天的文章由我们帅气逼人的大帅哥Zoey为大家分享(狗头)~有想要通过Facebook广告掘金的家人们!今天就跟大家分享一下Facebook广告投放的底层逻辑和实用技巧,帮助大家少走弯路,快速入门~ 基础知识&#x…

mysql的增删查改(进阶)

目录 一. 更复杂的新增 二. 查询 2.1 聚合查询 COUNT SUM AVG MAX MIN 2.1.2 分组查询 group by 子句 2.1.3 HAVING 2.2 联合查询/多表查询 2.2.1 内连接 2.2.2 外连接 2.2.3 全外连接 2.2.4 自连接 2.2.5 子查询 2.2.6 合并查询 一. 更复杂的新增 将从表名查询到…

java连接MySQL数据库

环境准备 JDK安装 Navicat MySQL安装 下载jar包 MySQL :: Download MySQL Connector/J (Archived Versions) 创建数据库 1. 打开Navicat 2. 新建数据库 3. 定义数据库名 4. 新建查询 运行如下代码创建表log CREATE TABLE log (user VARCHAR(255) NOT NULL UNIQUE,pwd …

[有监督学习]3.详细图解逻辑回归

逻辑回归 逻辑回归是一种用于有监督学习的分类任务的简单算法。虽然算法的名字中包含“回归”二字,但其实它是用于分类问题的算法。逻辑回归通过计算数据属于各类别的概率来进行分类。 概述逻辑回归是一种学习某个事件发生概率的算法。利用这个概率,可以…

simulink基础学习笔记

写在前面 这个笔记是看B站UP 快乐的宇航boy 所出的simulink基础教程系列视频过程中记下来的,写的很粗糙不完整,也不会补。视频教程很细跟着做就行。 lesson1-7节的笔记up有,可以加up的群,里面大佬挺活跃的。 lesson8 for循环 For …

AI科技,赋能企业财务管理

AI技术已深入千行百业,其实际任务解决能力愈发凸显和强劲。正如乔布斯所强调“技术不是为工程师而生,而是为应用而生”。 胜意科技深度集成业内领先技术,将AI融入到实际的财务工作流中,与OCR、RPA等智能技术组合式输出&#xff0c…

Android Coil的简单介绍及使用

前言: 本文是借鉴网上大佬的Coil相关技术文章及结合自己项目中的实际使用情况,对Coil作一个简单介绍。 简介: Coil是一个Android的图片加载框架库,是通过Kotlin协程的方式加载图片的,相对于Glide、Picasso、Fresco等…

CRMEB多店版v3.0前端技术革新与实践

摘要 随着移动互联网技术的飞速发展,用户对移动应用的体验要求日益提高。CRMEB多店版v3.0作为一款针对多门店管理的电商系统,在前端技术层面进行了全面的革新与优化。本文将从移动端UI设计、页面功能更新、DIY设计功能升级、移动端平台与门店管理、营销…

数据链路层相关知识

正文: 1.概述 数据链路层是计算机网络体系结构中的第二层,负责实现数据在物理层上的传输。在数据链路层中,数据被组织成帧(frame),并且通过MAC地址来进行寻址,以确保数据包能够被正确地发送到…

2020 6.s081——Lab1:Xv6 and Unix utilities梦开始的地方

一任宫长骁瘦 台高冰泪难流 锦书送罢蓦回首 无余岁可偷 ——知否知否 完整代码见:6.s081/kernel at util SnowLegend-star/6.s081 (github.com) Lecture 01知识点总结 首先透彻理解Lecture01的知识很是重要 ①pidwait((int *) 0); “wait(int *status)”函数用于…

【Java数据结构】详解LinkedList与链表(二)

目录 1.❤️❤️前言~🥳🎉🎉🎉 2.反转一个单链表 3. 找到链表的中间节点 4.输入一个链表,输出该链表中倒数第k个结点。 5.合并两个有序链表 6.链表分割 7. 判定链表的回文结构 8.输入两个链表,找…