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,所以需要第三個狀態,如果只有一個包尾,那在出現包尾之后,就可以直接回到初始狀態了,只需要兩個狀態就行,因為接收數據和等待包尾需要在一個狀態里同時進行,由于串口的包頭包尾不會出現在數據中,所以基本不會出現數據錯位的現象,這就是使用狀態機接收文本數據包的方法

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/20265.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/20265.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/20265.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Debian 常用命令指南:基礎篇

Debian 是一款廣泛使用的 Linux 發行版,以其穩定性和安全性著稱。對于新手來說,掌握一些常用的命令行工具是順利使用 Debian 的第一步。本篇文章將介紹一些 Debian 系統中最常用的基礎命令,幫助你更好地管理和操作你的系統。 1. 系統信息相關…

JAVA攔截器的三種實現方式

JAVA攔截器的三種實現方式 一、java原生過濾器Filter二、springMVC攔截器三、aop切面實現攔截器 一、java原生過濾器Filter /*** 自定義Filter* 對請求的header 過濾token** 過濾器Filter可以拿到原始的HTTP請求和響應的信息,* 但是拿不到你真正處理請求方法的…

Java 基礎面試300題 (141- 170 )

Java 基礎面試300題 &#xff08;141- 170 &#xff09; 141. 編譯運行以下代碼時會發生什么&#xff1f; class Mammal {} class Cat extends Mammal { } List<Mammal> list new ArrayList<Cat>();上述代碼將出現編譯錯誤。這是因為為List指定了Mammal哺乳動物…

SpringSecurity6從入門到實戰之整合原生Filter鏈

SpringSecurity6從入門到實戰之整合原生Filter鏈 DelegatingFilterProxy 從官網上來進行學習可以看到第一個類就是DelegatingFilterProxy,我們首先看看官網給下的定義. Spring提供了一個名為DelegatingFilterProxy的過濾器實現&#xff0c;它允許在Servlet容器的生命周期和Spr…

Raid的全局熱備和獨立熱備

目錄 Hot Spare背景: 1.定義與功能 2.數據存儲與容量 3.配置模式 4.數量限制&#xff1a; 5.數據重建: 6.管理與維護 實操全局熱備和獨立熱備&#xff1a; 配置全局熱備: 配置獨立熱備: Hot Spare背景: 在RAID配置中&#xff0c;Hot Spare(熱備)是一個非常重要的概念…

amis源碼 Api接口調用解析:

Amis中傳入用戶自定義fetcher(基于fetcher做接口調用)&#xff1a; 1.embed渲染時可以傳入用戶定義的fetcher(接口調用)&#xff1a; import axios from "/libs/api.request"; //自定義的fetcher調用接口&#xff08;axios調用&#xff09; { fetcher: ()>{ ……

發現一個ai工具網站

網址 https://17yongai.com/ 大概看了下&#xff0c;這個網站收集的數據還挺有用的&#xff0c;有很多實用的ai教程。 懂ai工具的可以在這上面找找靈感。

善聽提醒遵循易經原則。世界大同只此一路。

如果說前路是一個大深坑&#xff0c;那必然是你之前做的事情做的不太好&#xff0c;當壞的時候&#xff0c;壞的結果來的時候&#xff0c;是因為你之前的行為&#xff0c;你也就不會再糾結了&#xff0c;會如何走出這個困境&#xff0c;是好的來了&#xff0c;不驕不躁&#xf…

事先預判事的結果事先預防從容應對防微杜漸

很多人呢&#xff0c;學習倪老師的知識&#xff0c;也都是從他的中醫方面&#xff0c;認識了他很多的東西呢&#xff0c;對于倪老師的知識性的總結的東西呢&#xff0c;不是很了解。 其實啊&#xff0c;倪老師也是一個&#xff0c;對于這種文化的傳承&#xff0c;有著很大很深刻…

一些匯編語言的總結

一、匯編語言的介紹 1、匯編語言和處理器指令集高度相關&#xff0c;不同指令集的匯編語言不兼容。 2、匯編語言是對機器語言的一種抽象&#xff0c;用英文字符來代表運算和控制指令&#xff0c;用英文字母和數字代表操作數。 二、常用的匯編語言 有 x86的匯編語言&#xff…

YOLOv10漲點改進:卷積魔改 | 分布移位卷積(DSConv),提高卷積層的內存效率和速度

??????本文改進內容: YOLOv10如何魔改卷積進一步提升檢測精度?提出了一種卷積的變體,稱為DSConv(分布偏移卷積),其可以容易地替換進標準神經網絡體系結構并且實現較低的存儲器使用和較高的計算速度。 DSConv將傳統的卷積內核分解為兩個組件:可變量化內核(VQK)和…

iOS編程入門:揭秘神秘的開發世界

iOS編程入門&#xff1a;揭秘神秘的開發世界 在數字化時代的浪潮中&#xff0c;iOS編程成為了許多開發者熱衷探索的領域。想要入門iOS編程&#xff0c;不僅需要掌握基礎知識&#xff0c;還需理解其獨特的生態系統。本文將通過四個方面、五個方面、六個方面和七個方面&#xff…

golang中通過反射獲取結構體Tag標簽定義的內容 函數和測試用例

當我們在go語言中定義結構體的時候&#xff0c; 經常需要給某些字段打上一個Tag標簽, 如 Name string json:"name" , 那這個標簽有和作用呢&#xff1f; 這個作用可大了&#xff0c;最為常用的是json序列化和反序列化&#xff0c; 還有各種ORM 的實體對象定義&…

C# yolov8 TensorRT +ByteTrack Demo

C# yolov8 TensorRT ByteTrack Demo 目錄 效果 說明 項目 代碼 Form2.cs YoloV8.cs ByteTracker.cs 下載 參考 效果 說明 環境 NVIDIA GeForce RTX 4060 Laptop GPU cuda12.1cudnn 8.8.1TensorRT-8.6.1.6 版本和我不一致的需要重新編譯TensorRtExtern.dll&…

微調醫療大模型,與通用大模型效果對比

下面是一份CT描述&#xff1a; “肝臟大小、形態未見明確異常。肝S2見一結節狀低密度影&#xff0c;大小約13x11mm&#xff0c;增強掃描呈明顯漸進性強化&#xff0c;延遲期呈等密度。余肝實質內未見異常密度影或強化灶。肝內大血管及其分支走行未見異常&#xff0c;肝門區層次…

ip地址告訴別人安全嗎?ip地址告訴別人會有什么風險

IP地址告訴別人安全嗎&#xff1f;在數字化時代&#xff0c;IP地址作為網絡連接的關鍵標識符&#xff0c;承載著重要的安全意義。然而&#xff0c;很多人可能并不清楚&#xff0c;輕易地將自己的IP地址告訴他人可能帶來一系列安全風險。那么&#xff0c;IP地址告訴別人會有什么…

文件夾損壞0字節:全面解析、恢復技巧與預防策略

在數字時代&#xff0c;數據的完整性和安全性至關重要。然而&#xff0c;我們時常會遭遇文件夾損壞并顯示為0字節的棘手問題。這種情況一旦發生&#xff0c;用戶可能會面臨數據丟失的風險。本文將詳細探討文件夾損壞0字節的現象&#xff0c;分析其背后的原因&#xff0c;并提供…

Redis-重定向

實驗環境&#xff08;3主3從的Redis-Cluster&#xff09; 一、Redis重定向基礎篇 1、MOVED重定向 Redis Custer 中&#xff0c;客戶端可以向集群中任意節點發送請求。此時當前節點先對 Key 進行 CRC 16 計算&#xff0c;然后按 16384 取模確定 Slot 槽。確定該 Slot 槽所對應的…

為什么使用短鏈系統?

短鏈接&#xff08;Short Link&#xff09;是指將一個原始的長 URL&#xff08;Uniform Resource Locator&#xff09;通過特定的算法或服務轉化為一個更短、易于記憶的 URL。短鏈接通常只包含幾個字符&#xff0c;而原始的長 URL 可能會非常長。 短鏈接的原理非常簡單&#x…

FPGA編程與PLC編程的區別:深入解析與對比

FPGA編程與PLC編程的區別&#xff1a;深入解析與對比 在工業自動化和控制系統領域&#xff0c;FPGA&#xff08;現場可編程門陣列&#xff09;編程和PLC&#xff08;可編程邏輯控制器&#xff09;編程都是關鍵的編程技術&#xff0c;但它們在應用、功能、結構和編程方法上存在…