【轉載】串口中怎樣接收一個完整數據包的解析

来源:http://www.cnblogs.com/zyqgold/archive/2016/12/01/6123862.html
-Advertisement-
Play Games

這裡以串口作為傳輸媒介,介紹下怎樣來發送接收一個完整的數據包。過程涉及到封包與解包。設計一個良好的包傳輸機制很有利於數據傳輸的穩定性以及正確性。串口只是一種傳輸媒介,這種包機制同時也可以用於SPI,I2C的匯流排下的數據傳輸。在單片機通信系統(多機通信以及PC與單片機通信)中,是很常見的問題。 一、根... ...


這裡以串口作為傳輸媒介,介紹下怎樣來發送接收一個完整的數據包。過程涉及到封包與解包。設計一個良好的包傳輸機制很有利於數據傳輸的穩定性以及正確性。串口只是一種傳輸媒介,這種包機制同時也可以用於SPI,I2C的匯流排下的數據傳輸。在單片機通信系統(多機通信以及PC與單片機通信)中,是很常見的問題。

一、根據幀頭幀尾或者幀長檢測一個數據幀

1、幀頭+數據+校驗+幀尾

這是一個典型的方案,但是對幀頭與幀尾在設計的時候都要註意,也就是說幀頭、幀尾不能在所傳輸的數據域中出現,一旦出現可能就被誤判。如果用中斷來接收的話,程式基本可以這麼實現:

unsigned char recstatu;//表示是否處於一個正在接收數據包的狀態

unsigned char ccnt;      //計數

unsigned char packerflag;//是否接收到一個完整的數據包標誌

unsigned char rxbuf[100];//接收數據的緩衝區

void UartHandler()

{

       unsigned char tmpch;

       tmpch = UARTRBR;

       if(tmpch 是包頭)                          //檢測是否是包頭

       {  

            recstatu = 1;

            ccnt   = 0 ;

            packerflag = 0;

            return ;

       }

       if(tmpch是包尾)                          //檢測是否是包尾

       {

            recstatu = 0;

            packerflag = 1;                      //用於告知系統已經接收到一個完整的數據包

            return ;

       }

      if(recstatu ==1)                           //是否處於接收數據包狀態

      {

            rxbuf[ccnt++] = tmpch; 

      }

}

上面也就是接收一個數據包,但是再次提醒,包頭和包尾不能在數據域中出現,一旦出現將會出現誤判。另外一個。數據的校驗演算法是很必要的,在數據傳輸中,由於受到干擾,很難免有時出現數據錯誤,加上校驗碼可在發現數據傳輸錯誤時,可以要求數據的另一方重新發送,或是進行簡單的丟棄處理。校驗演算法不一定要很複雜,普通的加和,異或,以及迴圈冗餘都是可以的。我上面的接收程式在接收數據時,已經將包頭和包尾去掉,這些可以根據自己的需求加上,關鍵是要理解原理。

上述包協議出現了以下的幾種變種:

1.1 幀頭+數據長度+數據+校驗值

1.2包長+校驗值

上面兩種其實都是知道了數據包的長度,然後根據接收位元組的長度來判斷一個完整的數據包。例如,定義一個數據包的長度為256位元組,那我們就可以一直接收,直到接收到256個位元組,就認為是一個數據包。但是,會不會存在問題呢?比如說從機向主機發送數據,發送了一半,掉電,重啟,開機後繼續發送,這很明顯接收到的數據就不對了,所以此時很有必要定義一個超限時間,比如我們可以維護下麵這樣的一個結構體。

struct  uartrd{

char  rd[ 256];

unsigned int timeout;

}

成員變數rd用來存放接收到的數據位元組;成員變數timeout用來維護超時值,這裡主要討論這個。這個數值怎麼維護呢,可以用一個定時器來維護,也可以放在普通的滴答中斷裡面來維護,也可以根據系統運行一條指令的周期,在自己的迴圈中來維護,給其設置個初值,比如說100,當有第一個數據到來以後,timeout在指定的時間就會減少1,減少到0時,就認為超時,不論是否接收到足夠的數據,都應該拋棄。

二、根據接收超時來判斷一個數據包

2.1  數據+校驗

核心思想是如果在達到一定的時間沒有接受到數據,就認為數據包接收完成。modbus協議里就有通過時間間隔來判斷幀結束的。具體實現是要使用一個定時器,在接收到第一個數據時候,開啟定時器,在接收到一個數據時候,就將定時器清零,讓定時器重新開始計時,如果設定的超時時間到(超時時間長度可以設置為5個正常接收的周期),則認為在這一段時間內沒有接受到新的數據,就認為接收到一個完整的數據包了。流程大體如下圖所示:

26092459578

進行一個簡單的小的總結,上述幾種方法都還是較為常用的,在具體的實現上,可以根據具體的實際情況,設計出具體的通訊協議。數據校驗位,有時候感覺不出來其重要性,但是一定要加上,對數據進行一個相關的驗證還是必要的。現在很多MCU都帶有FIFO,DMA等功能,所以有時候利用上這些特性,可以設計出更好的通訊方式。有的人問在接受串口數據時候是應該中斷一次接收一個,還是進入中斷後接收一段數據呢,我認為應該中斷接收一個,因為CPU是很快的,至少對於串口是這樣,在接受每個數據的間隔期間,處理器還是可以做些其他工作的。這是在裸機下的模型。在多線程中,那就可以直接建立一個數據接收線程。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本隨筆續接:.NET 實現並行的幾種方式(三) 八、await、async - 非同步方法的秘密武器 1) 使用async修飾符 和 await運算符 輕易實現非同步方法 前三篇隨筆已經介紹了多種方式、利用多線程、充分利用多核心CPU以提高運行效率。但是以前的方式在WebAPI和GUI系統上、 使用起來 ...
  • 用法一、this代表當前實例,用this.來調用當前實例的成員方法,變數,屬性,欄位等 ...
  • 官方資料: "https://github.com/dotnet/core" "https://docs.microsoft.com/en us/aspnet/core" "https://docs.microsoft.com/en us/ef/core" 相關文章: "ASP.NET 5 RC1 ...
  • 本節從三個角度簡要總結之前介紹的各種容器類:用法和特點,數據結構和演算法,設計思維和模式。 ...
  • 一.簡介 pymsql是Python中操作MySQL的模塊,其使用方法和MySQLdb幾乎相同,但目前pymysql支持python3.x而後者不支持3.x版本 其執行語句與sql源碼相似 二.使用 1.安裝 pip install pymysql 2.使用操作 先來一例完整的連接加基本的操作 向數 ...
  • 這裡先從元素是否有序,按照什麼順序來應用進行Set的選擇,最後再從線程安全的角度說一下Set的選擇。 ...
  • #include<stdio.h>#include<stdlib.h>//此鏈表中的數據均為int型typedef struct Link_list{ int date; struct Link_list *next;}Link; int main(){ Link *Link_creat(); vo ...
  • 英文文檔: super([type[, object-or-type]]) Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for acces ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...