沙亞雄,徐駿善
(南京理工大學 機械工程學院,江蘇 南京 210094)
隨著計算機及網絡技術的發展和我國數字化景區建設步伐的加快,電子票務管理系統已成為智慧景區建設的重要組成部分,是實現景區標準化管理、樹立良好形象必不可少設備和管理手段。閘機作為票務管理系統的重要終端,其主要功能是實現自動檢票、管理人流、規范行人出入、上傳檢票信息[1]。
本文所應用的景區閘機為翼閘,如圖1,其內部邏輯結構有二維碼讀寫器、IC卡讀寫器、身份證讀寫器、通行算法控制板、機芯控制板和通信主控板。其中通信主控板對上通過RS485串口與PC機通信,對下通過RS232串口與二維碼讀寫器、IC卡讀寫器、身份證讀寫器、機芯控制板通信。無論是RS485還是RS232都屬于異步串行通信方式,所以有必要設計一套簡單、高效、安全、復用性強的通信協議,以保證設備之間信息的穩定交互。

圖1 翼閘內部邏輯結構示意圖
眾所周知,串口通信接收和發送數據都是面向字節的,但一個字節的信息量和可靠性顯然不能達到設備之間通信的要求。故串口通信通常都是面向幀的,即以多個字節組成一幀來傳遞信息。幀的設計比較自由靈活,一般根據具體的通信方式、實時性及可靠性要求等進行設計[2]。本文從結構和類型對通信幀進行設計。
通信幀結構如下:
1) 幀頭:表示幀的開始,一般選用固定的1個字節或多個字節。
2) 報頭開始:表示幀中報頭的開始,一般選用固定的1個字節或多個字節。
3) 報頭:表示幀中報頭的內容,報頭內容可自定義、放地址碼、幀類型、幀長度等,其內容不宜過多。
4) 報文開始:表示幀中報文的開始,一般選用固定的1個字節或多個字節。
5) 報文:表示幀中報文的內容、報文內容可自定義,放命令碼、參數等,是通信中數據的載體。
6) 幀尾:表示幀的結束,一般選用固定的1字節或多字節。
7) 校驗碼:數據校驗,在此選擇BCC校驗方式,即報頭內容和報文內容依次異或。
圖2列出3種通信幀結構,其中標準結構擁有報頭和報文,也有無報文結構和無報頭結構,可根據需要選定。

圖2 通信幀結構示意圖
考慮到翼閘使用了半雙工的RS485和全雙工的RS232串行通信方式,故設計2種類型的通訊幀,即控制幀和數據幀,其中控制幀主要用于對通訊流程進行控制,數據幀則用于傳輸數據。同時幀頭等固定字節均選用對應含義ASCII碼,為避免報頭或報文中出現此類選定的ASCII碼,在此采用轉義字符的方式,即若報頭或報文中出現DLE(0X10),則需要在其前面加上一個DLE轉義字符,校驗時只計入一個DLE字符??刂茙褂妙l率較高,信息量小,應盡量短小,故在此選擇無報文結構的幀。且報頭內容固定為3個字節:地址碼、類型碼、指令碼。地址碼用于表示此幀的接收對象;類型碼用于表示幀的類型,在此即控制幀和數據幀;指令碼則是表示此控制幀的功能。
控制幀格式為:

ACK 表示校驗通過,收到正確的幀;
NAK 表示校驗未通過,收到錯誤幀或接收超時;
ENQ 請求建立通信,發送數據;
XON 設備空閑,可以接收數據;
XOFF 設備繁忙,暫停接收數據。
數據幀格式為:

環形緩沖區是嵌入式系統中十分重要的一種數據結構,在串行通訊中發送方將環形緩沖區中的數據逐一取出通過串行接口發送出去,而接收方接收后方可將收到的數據依次置入環形緩沖區中,待檢測到一個完整的數據幀后再進行處理。環形緩沖區是一個先進先出(first in first out,FIFO)的隊列,數據只能從尾部添加,從頭部獲取。其在內存中占用一塊連續的地址空間,通常用一個數組來定義[2]。
若要對一幀數據進行描述,用一個結構體是非常適合的,若將此結構體作為鏈表的數據域,再將鏈表組織為隊列的形式,則使得串口接收發送數據幀變得簡單。接收數據時,將收到的字符依次放入接收環形緩沖區中,檢測到一個完整的幀后,從隊列尾部尋找一個可用空節點,將此幀的描述賦與節點,推入接收隊列中。應用層則只需檢測接收隊列是否非空,若非空則根據節點中的幀描述從接收緩沖區中取出幀進行處理。發送數據時組織好幀后,將幀內容添加進發送緩沖區,同時幀描述推入發送隊列中,若要發送數據只需檢測發送隊列,非空則根據節點幀描述從發送環形緩沖區中取出幀進行發送。
圖3以接收幀過程說明環形緩沖區和隊列在幀接收和提取時的應用,發送過程類似。

圖3 接收和提取幀數據結構示意圖
幾個重要數據結構說明:
1) 結構體1:幀描述結構體,用于描述幀在環形緩沖區中的位置和一些重要屬性,如幀的報頭報文在緩沖區中的位置和長度、幀地址、幀類型、發送狀態、生命周期等。
2) 結構體2:幀描述鏈表的節點。
3) 鏈表:將多幀數據的描述組織成隊列存放。
4) 環形緩沖區:接收環形緩沖區,用于存放接收到的字符。
5) 結構體3: 接收幀結構體,用于存放幀的有效內容,即去除幀頭等固定字符后的內容、報頭和報文的內容和一些重要屬性。
如圖3所示,接收幀過程中,先將串口接收到的有效字符放入接收緩沖區中,待接收到BCC字符并校驗通過后將接收幀描述(結構體1)存入隊列中。提取幀時通過隊列中鏈表節點(結構體2)的描述將接收緩沖區中的報頭、報文內容提取到接收幀結構體(結構體3)中。應用層中,結構體3的內容就是幀的有效內容,只需對其進行解析處理即可。
一套可靠的通訊協議,一次完整的通訊過程必然需要設備之間進行多次握手,才能保證通訊穩定可靠,同時通訊過程中還應該包含確認機制,否定重發機制,超時重發機制等,用通訊實現圖可清楚描述此類過程。圖4共列出7種情況。


圖4 通訊實現圖
1) 正常通信過程:發送方發送請求,接收方回復設備空閑,發送方發送數據,接收方回復數據接收正確。
2) ENQ請求3次內無回應:發送ENQ請求后,若在設定時間Xms后無應答,則重發ENQ請求,若重發2次后仍然無響應則中斷通訊,認定接收設備通訊異常。
3) ENQ請求回應為XOFF:發送ENQ請求后,收到XOFF回應,則Nms后再次發送ENQ請求,直到收到XON。
4) 數據發送3次內無回應:若ENQ請求成功,并發送數據后,若在設定時間Xms后無回應,則重發數據,若重發2次后仍然無回應則中斷通訊,認定接收設備通訊異常。
5) 數據發送3次內有回應:若ENQ請求成功,并發送數據后,若在設定時間Xms后無應答,則重發數據,若在3次內有ACK或NAK回應,則進入正常通訊階段。
6) 數據發送3次內無ACK回應:若ENQ請求成功,并發送數據后,Xms時間內收到NAK回應,則立刻再次重發該數據,若在3次內無ACK回應,則中斷通訊,認定通訊線路干擾過大。
7) 數據發送3次內有ACK回應:若ENQ請求成功后,發送數據后,Xms時間內收到NAK回應,則立刻再次重發該數據,若在3次內有回應有ACK,則進入正常通訊階段。
通信協議結構設計好之后,發送、接收都應該嚴格按照設計的結構來處理,對于接收來說要符合設計結構的幀,即需要屏蔽異常字符,同時需要去除幀頭等固定字符,提取報頭、報文等有效字符。由于串口是面向字節的,且串口通訊速度非常慢,在此選用有限狀態機來實現按設計幀結構接收數據。有限狀態機的原理是發生事件后,根據當前狀態,決定執行的動作,并設置下一個狀態,其使用范圍很廣[4]。
圖5的狀態遷移圖中使用UML標準標記法,即當一個系統處于“狀態A”時發生“觸發”事件,只有當[臨界條件]為真時系統會轉換到“狀態B”,然后,一個動作被執行。圖中可以看出根據設計的幀結構一共有8個狀態,而觸發事件是串口接收到一個字節,動作則是將報頭或報文內容推入接收緩沖區。根據此圖可方便編制出接收幀函數。若在單片機中使用,則只需將接收幀函數放入串口接收終端中,即每接收一個字節,執行一次有限狀態機。待BCC驗證后,幀有效內容存入接收緩沖區,幀描述推入接收隊列。

圖5 接收幀狀態遷移圖
要想實現圖4中的7種通訊過程,需結合應用層實現,即需提取幀之后,判斷幀類型或幀內容后才能做出相應的回應,實現重發機制也需要在應用層進行一些設計。圖6為應用層狀態示意圖,其包含了發送幀和接收幀的狀態處理,二者不是孤立的,而是息息相關的,因為需要根據接收內容判斷是否需要重發幀。

圖6 應用層狀態示意圖
圖6中狀態的解釋如下:
1) 發送空閑:在此狀態下,首先需要不斷檢測發送隊列是否為空,非空則取出隊列中的幀判斷其發送狀態是否為待發送狀態,若是則發送此幀,發送完成后還需根據幀類型或控制幀指令碼判斷其是否需要等待回應,若無需等待回應則將此幀的超時生命周期置0;若需等待回應則將此幀的超時重發次數減1,并開啟應答超時計時。若應答超時計時溢出,需重發正在等待回應的幀。此外還需檢測發送隊列,從發送緩沖區和發送隊列中刪除生命周期為0 的幀。
2) 識別幀:此狀態是提取幀之后,根據幀類型和指令碼做出相應的動作。若收到A幀或XON幀則將正在等待回應幀的生命周期置0, 關閉應答超時計時。若收到NAK幀,則將否定重發次數減1,幀發送狀態置為待發送。若收到ENQ幀,則需要判斷接收緩沖區或接收隊列容量,若容量充足則組XON幀并推入發送隊列,相反組XOFF幀。若收到XOFF幀,則延時Nms后再繼續發送幀,同時應暫停向發送隊列中添加幀。
3) 處理幀:此狀態是用于解析接收到的數據幀內容,即根據幀的報文內容做相應的動作或任務。
評價一套良好的串行通訊協議,實時性是一個重要的標準,本文所述的通訊協議主要應用于單片機等嵌入式系統中,故測試平臺選用時下流行的STM32F103系列單片機,此款單片機時鐘頻率為72 MHz,同時在裸機和uC/OSII下對接收幀和發送幀時間進行測試,其中接收幀時間測試起始為接收到第一個字節開始,終止為從接收隊列中提取出幀;發送幀時間測試起始為將發送幀推入發送隊列,終止為此幀發送完成。
表1接收發送時間測試表
ms

如表1 所示,物理層設置的參數為1位起始位,8位數據位,1位停止位,無校驗位。即發送一字節數據需發送10位。 9 600bit/s的波特率下,理論上發送接收100字節數據時間為100×10/9 600=104ms,表中測試為103ms和105ms。故在此單片機系統中,接收發送程序對通信速度幾乎無影響。而在uC/OSII下接收幀測試時間和裸機相同,發送幀測試時間會略多幾毫秒,原因是發送幀和接收幀任務設計為2個任務,uC/OSII此操作系統規定每個任務在適當的情況下必須釋放CPU一段時間,故會多出幾毫秒,如果在實時性要求不高的應用中,可以忽略[5]。由于測試方法差異,實驗器材不同、串口驅動不相同等問題,實驗數據僅供參考。
異步串行通信以其通訊簡單占用資源少的特點,在數據通信領域尤其是在嵌入式系統中,必定在很長一段時間內依然會占據著重要地位。本文從幀結構設計到具體的幀接收發送的實現方法都做出了簡單敘述,即描述了一套串行通訊協議的設計與實現方法。雖然串行通信的應用設備或場合不盡相同,但所述方法還是對串行通訊協議的設計和實現有一定的參考價值。此外所述的通信協議已經應用到了實際的景區閘機中,且運行良好。
參考文獻:
[1] 宋哲. 地鐵閘機扇門控制系統設計[D]. 南京:南京理工大學,2010.
[2] 謝瑞和. 串行技術大全[M]. 北京:清華大學出版社,2003.
[3] 徐駿善,朱巖. 微型計算機原理與接口技術[M]. 北京:機械工業出版社,2014.
[4] 張臘明, 佟宇. 狀態機技術在數據通訊協議棧中的編程應用[J]. 工控技術,2008,35(3):146-148.
[5] 任哲. 嵌入式操作系統基礎μC/OS-II和Linux[M]. 北京:北京航空航天大學出版社,2011.