其中,通訊協議(communication protocol)更是不斷誕生各種奇行種,就算是標準的 MODBUS RTU,也是有人硬要讓他位址長成橫的 = =
通訊協議的派系之分
字串派
這一派認為通訊協議應該用 ASCII 中的可見字元編碼,比方說 123 就編碼成 "7B",這有幾個優點:
- 除錯容易,sniffer 下來的資料容易識別
- 接收資料方便,因為只要拿個不可見字元來當結尾字元(sentinel),讀到結尾字元就代表讀到完整的封包。
- 各種常用程式語言都內建相關 API,比方 C/C++ sprintf()。
二進位派:
這一派認為前面那一派浪費頻寬,而且很容易給人看光光沒安全感,應該所有的資料都最大限度使用二進位緊密表示,這樣才能充分運用頻寬,順便保密,一兼二顧,個人相信本派得到了台灣企業 cost down 的真傳。
本派優點有:
本派優點有:
- 可運用 bit packing 技巧壓縮資料,比方說把年月時分秒放在一個 32bit 整數內。
- 如果沒有公開協議,外人難以猜測內容,具有某種程度的保密效果。
- 對於記憶體先天不足的小型裝置如微控制器,可以節省記憶體空間。
這一派也不是沒有缺點:
- 難以除錯,過份賣弄小聰明,還記得 Brian W. Kernighan and P. J. Plauger 的名言嗎?「除錯的難度兩倍於一開始寫的代碼。因此,如果你過份賣弄技巧,根據定義,你將不夠聰明去除錯他」
- 簡單的 check sum 不適用。因為此時 00H 變成合法值,比方我們收到四個 BYTE - A B C D(皆不為 00H),如果多收了一個 BYTE E,A B C D E,其中 E = 00H,所以會變成:
A + B + C + D = A + B + C + D + E
簡單的 check sum 將無法發現這個錯誤,這也是為何 MODBUS RTU 要改用 CRC16 的原因。
整人混合派:
本派相信可以結合「字串派」跟「二進位」派的優點,我們以 V 廠牌 VS 系列控制器為例,這個廠牌公開了自己的協議,他的協議長像如下:
除了頭部的 10H 02H 與尾巴的 10H 03H CHKSUM(Hex String)外,在灰色部份內如果出現 10H,就需要轉成 10H 10H。這不是什麼新鮮的用法,例如 Visual Basic 字串常數裡要表示「"」,就要打成「""」(例 "A""B" => A"B)。
假如我們傳送的資料是完全隨機的,比方說灰色的部份是 4 bytes 好了,那麼出現 10H 的機率是多少呢?
看來我們需要去展開 10H 的機率真的很小,但是 PLC 可不是亂數產生器,我們必須作最壞的打算。不過就算真的要展開 10H,大不了準備另一塊 buffer 存放結果就好。
真正麻煩的是接收,請問要如何判斷結尾呢?事實上,你只能判斷結尾的 10H 前不是 10H(下圖中的 XX),才能放心判斷已經讀完一個完整封包了:
所以這個協議 header 裡,又放了後續資料的長度(不包括 10H 03H CHKSUM),但是要讀到這筆資料,還是得先解開 header,那如果 header 裡面有 10H 10H,就必須先折疊回 10H,才能讀到正確的資料...所以變成得一邊讀一邊解,要不解完先保留,總而言之都是 #@#$%^&...
其實,如果當初該位設計者能站在 user 角度想一想,改成下面這樣,大家日子就會好過多了:
這樣 user 只要讀到 10H 後面是 Hex String (因為 Hex String 不可能有 10H),就可以放心判斷已經讀取結束,可以進行下一步的解碼了。
或許,該位設計者用心良苦,如果您能克服這個協議帶來的挑戰,基本上也是個 power user,您大概也不需要他們的技術支援,我們也只能這樣正面思考了。
沒有留言:
張貼留言