mfc如何将一个数组中的字节数据用串口发送出去_[翻译] 串口通信的帧(frame)...
在串口通信中,只傳輸一個字節是簡單的,但是如果要傳送一個幀(多個字節),將面臨以下問題:
- receiver從串口接收的是字節流,那它是如何知道幀的開始或結束呢?它又是如何知道這個幀有多長?
- 真實的物理硬件是充滿噪音和干擾的,由于電噪聲,某些字節的位可能被翻轉,字節甚至整個幀都可能會丟失。
要解決這些問題,首先需要了解下計算機網絡中數據鏈路層的基礎知識。
基于一個可以在設備之間傳輸信號的物理層,數據鏈路層的工作(粗略地說)就是傳輸整個數據幀,其中一些方法可以確保數據的完整性(減少錯誤)。當我們使用socket通過TCP或UDP進行網絡通信時,幀在硬件層面得到了很好的處理,以至于上層甚至都感覺不到。但是,在串口通信中,我們必須自己處理幀和數據錯誤。
處理幀有以下幾種方法:
方法1和2僅適用于硬件實現的數據鏈路層。當涉及多層軟件(比如在Windows上運行)時,確保計時非常困難。
方法3的意思是在幀頭中指定幀中的字節數。這樣做的問題是計數可能因傳輸錯誤而出現亂碼。在這種情況下,“重新同步”會非常困難,因而這種方法很少使用。
方法4和5有些相似。在本文中,我將重點關注4,因為5不適合串口通信。
帶字節填充的標志字節
讓我們從先一個簡單的想法開始,然后逐步將其發展成一個完整,強大的方案。flag bytes是特殊字節值,表示幀何時開始和結束。假設我們希望能夠發送任意長度的幀。特殊的start flag bytes表示幀的開始,end flag bytes表示幀的結束。
那么問題來了。假設end flag的值是0x98,如果0x98又正好出現在data的某處,協議將混淆并認為這個幀到data里的這個0x98就結束了。這個問題有一個簡單的解決辦法,所有熟悉字符串轉義引號和特殊字符的程序員都應該能想到。它被稱為字節填充,或簡單地轉義,具體方法如下:
每當數據中出現一個flag byte(開始或結束)時,我們將在它之前插入一個特殊的轉義字節(比如ESC)。 當receiver看到ESC時,它知道忽略它并且不將其插入到接收的實際數據中。每當ESC本身必須出現在數據中時,另一個ESC就會被置于其前面。Receiver移除第一個但保留第二個。
這里有一些示例:
此外,我們還需要某種錯誤檢查,比如checksum,或者更好的CRC。這通常是幀的最后一個字節,檢查范圍包括幀中的所有字節(以其未填充的形式)。
這種方案是穩健的:任何丟失的字節(無論是標志,轉義,數據字節還是校驗和字節)都會導致receiver僅丟失一幀,之后它將重新同步到下一幀的start flag。
PPP協議
事實上,這種方法可以算是點對點協議(PPP)的簡化版,在PPP中:
- 開始和結束的flag byte都是0x7E
- 轉義字節為0x7D
- 只要消息中出現標志或轉義字節,它就會被0x7D轉義,字節本身與0x20進行異或運算,例如0x7E變為0x7D 0x5E,0x7D變為0x7D 0x5D。Receiver取消轉義轉義字節并再次使用0x20對下一個字節進行異或,以獲得原始數據。
讓我們用一個完整的例子來演示它是如何工作的。
假設我們定義以下協議:
start flag:0x12 end flag:0x13 轉義字節:0x7D并且sender想要發送以下數據消息。原始數據在(a)中:
數據包含兩個需要轉義的標志,位置2的0x13(對,從0開始計數),以及位置4的0x7D。
Sender的數據鏈路層會將數據轉換為(b)中所示的幀。
接下來讓我們看看receiver如何處理這樣的幀。 為了演示,假設receiver從串口獲取的第一個字節不是消息的真實部分(我們想看看它如何處理這種情況)。 在下圖中,receiver state是接收字節后receiver的狀態,data buffer是接收數據的緩沖區,用于之后將數據傳遞到上層應用程序。
有幾點需要注意:
- 忽略start flag之前的“雜散”字節:根據協議,每個幀必須以start flag開頭,因此這不是幀的一部分。
- start flag和end flag本身不會進入數據緩沖區。
- 轉義字節由一特殊狀態AFTER_ESC處理。
- 當幀以end flag結束時,receiver擁有了一個可以往上層程序傳遞的幀,并且返回等待start flag,或者說等待一個新的幀。
最后,上層應用程序看到收到的消息正是發送的消息,所有協議細節(標志,轉義等)都由數據鏈路層透明地處理掉了。
本文翻譯自 https://eli.thegreenplace.net/2009/08/12/framing-in-serial-communications
原創翻譯,轉載請注明出處。
總結
以上是生活随笔為你收集整理的mfc如何将一个数组中的字节数据用串口发送出去_[翻译] 串口通信的帧(frame)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: boolean类型_JS核心理论之《数据
- 下一篇: m3u8文件在手机上用什么软件看_如何用