自定義通訊協議 網摘

2021-09-01 20:35:27 字數 4319 閱讀 8038

現在大部分的儀器裝置都要求能過通過上位機軟體來操作,這樣方便除錯,利於操作。其中就涉及到通訊的過程。在實際製作的幾個裝置中,筆者總結出了通訊程式的通用寫法,包括上位機端和下位機端等。

1.自定義資料通訊協議

這裡所說的資料協議是建立在物理層之上的通訊資料報格式。所謂通訊的物理層就是指我們通常所用到的rs232、rs485、紅外、光纖、無線等等通訊方式。在這個層面上,底層軟體提供兩個基本的操作函式:傳送乙個位元組資料、接收乙個位元組資料。所有的資料協議全部建立在這兩個操作方法之上。

通訊中的資料往往以資料報的形式進行傳送的,我們把這樣的乙個資料報稱作為一幀資料。類似於網路通訊中的tcpip協議一般,比較可靠的通訊協議往往包含有以下幾個組成部分:幀頭、位址資訊、資料型別、資料長度、資料塊、校驗碼、幀尾。

幀頭和幀尾用於資料報完整性的判別,通常選擇一定長度的固定位元組組成,要求是在整個資料鏈中判別資料報的誤位元速率越低越好。減小固定位元組資料的匹配機會,也就是說使幀頭和幀尾的特徵位元組在整個資料鏈中能夠匹配的機會最小。通常有兩種做法,一、減小特徵位元組的匹配機率。二、增加特徵位元組的長度。通常選取第一種方法的情況是整個資料鏈路中的資料不具有隨即性,資料可**,可以通過人為選擇幀頭和幀尾的特徵字來避開,從而減小特徵位元組的匹配機率。使用第二種方法的情況更加通用,適合於資料隨即的場合。通過增加特徵位元組的長度減小匹配機率,雖然不能夠完全的避免匹配的情況,但可以使匹配機率大大減小,如果碰到匹配的情況也可以由校驗碼來進行檢測,因此這種情況在絕大多說情況下比較可靠。

位址資訊主要用於多機通訊中,通過位址資訊的不同來識別不同的通訊終端。在一對多的通訊系統中,可以只包含目的位址資訊。同時包含源位址和目的位址則適用於多對多的通訊系統。 

資料型別、資料長度和資料塊是主要的資料部分。資料型別可以標識後面緊接著的是命令還是資料。資料長度用於指示有效資料的個數。

校驗碼則用來檢驗資料的完整性和正確性。通常對資料型別、資料長度和資料塊三個部分進行相關的運算得到。最簡單的做法可是對資料段作累加和,複雜的也可以對資料進行crc運算等等,可以根據運算速度、容錯度等要求來選取。

2.上位機和下位機中的資料傳送

物理通訊層中提供了兩個基本的操作函式,傳送乙個位元組資料則為資料傳送的基礎。資料報的傳送即把資料報中的左右位元組按照順序乙個乙個的傳送資料而已。當然傳送的方法也有不同。

在微控制器系統中,比較常用的方法是直接呼叫串列埠傳送單個位元組資料的函式。這種方法的缺點是需要處理器在傳送過程中全程參與,優點是所要傳送的資料能夠立即的出現在通訊線路上,能夠立即被接收端接收到。另外一種方法是採用中斷傳送的方式,所有需要傳送的資料被送入乙個緩衝區,利用傳送中斷將緩衝區中的資料傳送出去。這種方法的優點是占用處理器資源小,但是可能出現需要傳送的資料不能立即被傳送的情況,不過這種時延相當的小。對於51系列微控制器,比較傾向於採用直接傳送的方式,採用中斷傳送的方式比較占用ram資源,而且對比直接傳送來說也沒有太多的優點。以下是51系列微控制器中傳送單個位元組的函式。

void sendbyte(unsigned char ch)

上位機中關於串列埠通訊的方式也有多種,這種方式不是指資料有沒有緩衝的問題,而是操作串列埠的方式不同,因為pc上資料傳送基本上都會被緩衝後再傳送。對於程式設計來說操作串列埠有三種方式,一、使用windows系統中自帶的串列埠通訊控制項,這種方式使用起來比較簡單,需要注意的是接收時的阻塞處理和執行緒機制。二、使用系統的api直接進行串列埠資料的讀取,在windows和linux系統中,裝置被虛擬為檔案,只需要利用系統提供的api函式即可進行串列埠資料的傳送和讀取。三、使用串列埠類進行串列埠操作。在此只介紹windows環境下利用串列埠類程式設計的方式。

cserialport是比較好用的串列埠類。它提供如下的串列埠操作方法:

void writetoport(char* string, int len);

串列埠初始化成功後,呼叫此函式即可向串列埠傳送資料。為了避免串列埠緩衝所帶來的延時,可以開啟串列埠的沖刷機制。

3.下位機中的資料接收和協議解析

下位機接收資料也有兩種方式,一、等待接收,處理器一直查詢串列埠狀態,來判斷是否接收到資料。二、中斷接收。兩種方法的優缺點在此前的一篇關於串列埠通訊的文章中詳細討論過。得出的結論是採用中斷接收的方法比較好。

資料報的解析過程可以設定到不同的位置。如果協議比較簡單,整個系統只是處理一些簡單的命令,那麼可以直接把資料報的解析過程放入到中斷處理函式中,當收到正確的資料報的時候,置位相應的標誌,在主程式中再對命令進行處理。如果協議稍微複雜,比較好的方式是將接收的資料存放於緩衝區中,主程式讀取資料後進行解析。也有兩種方式交叉使用的,比如一對多的系統中,首先在接收中斷中解析「連線」命令,連線命令接收到後主程式進入設定狀態,採用查詢的方式來解析其餘的協議。

以下給出具體的例項。在這個系統中,串列埠的命令非常簡單。所有的協議全部在串列埠中斷中進行。資料報的格式如下:

0x55, 0xaa, 0x7e, 0x12, 0xf0, 0x02, 0x23, 0x45, sum, xor, 0x0d

其中0x55, 0xaa, 0x7e為資料幀的幀頭,0x0d為幀尾,0x12為裝置的目的位址,0xf0為源位址,0x02為資料長度,後面接著兩個資料0x23, 0x45,從目的位址開始結算累加、異或校驗和,到資料的最後一位結束。

協議解析的目的,首先判斷資料報的完整性,正確性,然後提取資料型別,資料等資料,存放起來用於主程式處理。**如下:

if(state_machine == 0)     // 協議解析狀態機

else if(state_machine == 1)

else if(state_machine == 2)

else if(state_machine == 3)

else if(state_machine == 4)

else if(state_machine == 5)

else if(state _machine == 6 || state _machine == 7)

else if(state_machine == 8)

else if(state_machine == 9)

else if(state_machine == 10)

state_machine = 0;     // 復位狀態機 }

此過程中,使用了乙個變數state_machine作為協議狀態機的轉換狀態,用於確定當前位元組處於一幀資料中的那個部位,同時在接收過程中自動對接收資料進行校驗和處理,在資料報接收完的同時也進行了校驗的比較。因此當幀尾結束符接收到的時候,則表示一幀資料已經接收完畢,並且通過了校驗,關鍵資料也儲存到了緩衝去中。主程式即可通過retval的標誌位來進行協議的解析處理。

接收過程中,只要哪一步收到的資料不是預期值,則直接將狀態機復位,用於下一幀資料的判斷,因此系統出現狀態死鎖的情況非常少,系統比較穩定,如果出現丟失資料報的情況也可由上位機進行命令的補發,不過這種情況筆者還沒有碰到。

對於主程式中進行協議處理的過程與此類似,主程式迴圈中不斷的讀取串列埠緩衝區的資料,此資料即參與到主迴圈中的協議處理過程中,**與上面所述完全一樣。

4.上位機中的資料接收和命令處理 

上位機中資料接收的過程與下位機可以做到完全一致,不過針對不同的串列埠操作方法有所不同。對於阻賽式的串列埠讀函式,例如直接進行api操作或者呼叫windows的串列埠通訊控制項,最好能夠開啟乙個執行緒專門用於監視串列埠的資料接收,每接收到乙個資料可以向系統傳送乙個訊息。筆者常用的cserialport類中就是這樣的處理過程。cserialport開啟串列埠後開啟執行緒監視串列埠的資料接收,將接收的資料儲存到緩衝區,並向父程序傳送接收資料的訊息,資料將隨訊息一起傳送到父程序。父程序中開啟此訊息的處理函式,從中獲取串列埠資料後就可以把以上的**拷貝過來使用。 

cserialport向父類傳送的訊息號如下:

#define wm_comm_rxchar wm_user+7 // a character was received and placed in the input buffer.

因此需要手動新增此訊息的響應函式:

afx_msg long oncommunication(wparam ch, lparam port);

on_message(wm_comm_rxchar, oncommunication)

響應函式的具體**如下:

long cwellinfoview::oncommunication(wparam ch, lparam port)

else if(state_machine == 1) {

if(rcvdat == 0xaa)     // 接收到幀頭第二個資料

state_machine = 2;

else

state_machine = 0;    // 狀態機復位

......

5.總結

以上給出的是通訊系統運作的基本雛形,雖然簡單,但是可行。實際的通訊系統中協議比這個要複雜,而且涉及到資料報響應、命令錯誤、延時等等一系列的問題,在這樣的乙個基礎上可以克服這些困難並且實現出較為穩定可靠的系統

Arduino自定義通訊協議解析

給出了通訊協議的設計。通訊協議的格式如下 協議首部 指令長度 控制指令 校驗和 控制指令 設計成如下格式 裝置型別 裝置號埠號 比如說上位機傳送如下的格式的資料 aa0305020106,意思就是協議的首部為aa,指令長度為03,控制指令為050201 實際意義就是裝置型別為05,裝置號為02,埠為...

簡單高效可靠的自定義通訊協議(傳輸協議)

取 高效簡單可靠 這幾個形容詞還是很虛的,畢竟這是yy出來的東西。設計的目的在於 在收發雙方能夠正常執行的情況下,盡可能高的利用網路傳輸能力 不使用一應一答 以及提高傳輸效率 無須對每個報文幀進行應答 對比xmodem kermit,以及借鑑tcp的協議棧設計思想,設計一套通訊協議 1,定義傳送方s...

自定義 如何自定義協議

何為自定義協議,其實是相對標準協議來說的,這裡主要針對的是應用層協議 常見的標準的應用層協議如http ftp smtp等,如果我們在網路通訊的過程中不去使用這些標準協議,那就需要自定義協議,比如我們常用的rpc框架 dubbo,thrift 分布式快取 redis,memcached 等都是自定義...