前文提到MODBUS的傳送格式
至於接收的部分
我想跳過編碼的介紹
直接介紹通訊間的一些問題
編碼的部分
上一篇文章中所提供的PDF文件
有很完整的描述
只是內容是英文的
如果有人看了不太能理解的
再告訴我一聲吧~~~
我們都曉得
根據MODBUS所制定的格式來看
裝置端(slave)在接收指令的負擔是很輕的
以RTU模式來看
只要8Bytes就完成一組指令了
ASCII的話也只要17Bytes就搞定 (1+8x2)
但是回應的時候
RTU長一點就可能要30~40個Bytes
(假設一次要拿16組資料, 每組都2 Bytes)
同樣的ASCII就要近80Bytes 的資料在傳~~~
對於暫存區空間較少的MCU來說
這是一個夢魘!!!
因為通訊時別台裝置的回應碼
不單單只是回應給主控端
還同時會傳給其它的裝置端
如果串列中斷裡沒有規劃好因應的對策
災難很快就會發生
要不是系統的堆疊會爆掉
就是串列資料不小心改掉堆疊的內容
讓程式進入亂七八糟的鬼上身狀態
規劃的方向有幾個重點
提一下概念給大家思考看看
1. Timeout 機制 (逾時中止)
Timeout是MODBUS通訊中一定會用到的第一個概念
特別是在RTU傳送模式下
因為通訊碼裡面並沒有結束碼的設計
所以只能透過
"經過多久時間沒有在送資料"來判斷它已經結束了
這個等待時間一般來說是5~10 個Bytes的時間間隔
拿9600bps的鮑率來看
1個Byte約需1mS
那麼適當的Timout時間就是5mS~10mS
為什麼要這樣設定?
因為資料在傳送的過程
主控端有可能受到其它多工運作的影響
導致指令並不是連續送出來的
把Timeout設得太低
有可能當指令傳到一半時
裝置就開始分析指令了
這樣一來
指令分析一定會錯誤
裝置也就不會正確動作及回應了!!
2. 循環指標歸零時機
一般在設計通訊碼的暫存空間
會使用循環旗標
意思就是讓暫存器透過串列中斷一直存放資料
不要去管內容是什麼
每存一個Byte指標就+1
當發生Timeout
或是旗標已經加到陣列的邊界
才把旗標歸零
分析指令時
如果是第一種歸零時機
通常是正確的通訊碼
第二種則是部分資料被覆蓋的不完整碼
透過歸零時機的判斷
可以拿到正確的通訊資料
3. 善用ASCII的啟始碼與結束碼
在ASCII的模式下
:是啟始碼
CRLF是結束碼只要遇到
啟始碼
就自動擺到暫存空間的最前面
遇到
結束碼就立刻分析資料
這樣就能保證資料一定是從頭開始而且是完整的
以上
就是MODBUS的必勝秘訣
如果能依照這樣的原則來寫程式
一定可以避開很多莫須有的怪問題
不過
很多實際的應用還是會有出乎意料的狀況
此時就要善用示波器來觀察通訊的波形是否正確了~~~