Modbus​協議​深入​講解

語言: CN / TW / HK

Modbus​是​一種​工業​協議,​於​1979​年​開發,​旨​在​實現​自動​化​裝置​之間​的​通訊。 Modbus​最初​是​作為​通過​串​行​層​傳輸​資料​的​應用​級​協議​實現​的,​現​已​擴充套件​到​包括​通過​串​行、​TCP/​IP​和​使用者​資料​報​協議​(UDP)​的​實現。 本文​檔​提供​了​協議​實現​的​深入​講解。

內容

什麼​是​Modbus​協議?

Modbus​是​使用​主從關係​實現​的​請求 - 響應​協議。 在​主從關係​中,​通訊​總是​成​對​發生 - 一個​裝置​必須​發起​請求,​然後​等待​響應 - 並且​發起​裝置​(主​裝置)​負責​發起​每次​互動。 通常,​主​裝置​是​人​機​介面​(HMI)​或​監​控​和​資料​採集​(SCADA)​系統,​從​裝置​是​感測器、​可​編​程​邏輯​控制器​(PLC)​或可​編​程​自動​化​控制器​(PAC)。 這些​請求​和​響應​的​內容​以及​傳送​這些​訊息​的​網路​層​由​協議​的​不同​層​來​定義。

圖1. 主​從​網路​關係

Modbus​協議層

在​最初​的​做法​中,​Modbus​是​建立​在​串​行​端​口​之上​的​單一​協議,​因此​它​不能​被​分成​多個​層。 隨著​時間​的​推移,​該​協議​引入​了​不同​的​應用​程式​資料​單元​來​更改​串​行​通訊​使用​的​資料​包​格式,​或​允許​使用​TCP/​IP​和​使用者​資料​報​協議​(UDP)​網路。 這​實現​了​定義​協議​資料​單元​(PDU)​的​核心​協議​和​定義​應用​資料​單元​(ADU)​的​網路​層​的​分離。

返回​頂部

協議​資料​單元​(PDU)

PDU​及其​處理​程式碼​構成了Modbus​應用​協議​規範的​核心。 該​規範​定義​了​PDU​的​格式、​協議​使用​的​各種​資料​概念、​如何​使用​功能​程式碼​訪問​資料,​以及​每​個​功能​程式碼​的​具體​實現​和​限制。

Modbus PDU​格式​被​定義​為​一個​功能​程式碼,​後面​跟著​一​組​關聯​的​資料。 該​資料​的​大小​和​內容​由​功能​程式碼​定義,​整個​PDU(功能​程式碼​和​資料)​的​大小​不能​超過​253​個​字​節。 每​個​功能​程式碼​都有​一個​特定​的​行為,​從​裝置​可以​根據​所需​的​應用​程式​行為​靈活​地​實現​這些​行為。 PDU​規範​定義​了​資料​訪問​和​操作​的​核心​概念;​但是,​從​裝置​可能​會​以​規範​中​未​明確​定義​的​方式​處理​資料。

訪問​Modbus​和​Modbus​資料​模型​中的​資料

通常,​Modbus​可​訪問​的​資料​儲存​在​四​個​資料​庫​或​地址​範圍​的​其中​一個: 線圈​狀態、​離散​量​輸入、​保持​暫存器​和​輸入​暫存器。 與​許多​規範​一樣,​名稱​可能​因​行業​或​應用​而​異。 例如,​保持​暫存器​也可以​稱為​輸出​暫存器,​線圈​狀態​可能​稱為​數字​或​離散​量​輸出。 這些​資料​庫​定義​了​所​包含​資料​的​型別​和​訪問​許可權。 從​裝置​可以​直接​訪問​這些​資料,​因為​這些​資料​由​裝置​本地​託管。 Modbus​可​訪問​的​資料​通常​是​裝置​主​存​的​一個​子​集。 相反,​Modbus​主​裝置​必須​通過​各種​功能​程式碼​請求​訪問​這些​資料。 表​1​中​描述​了​每​個​區塊​的​行為。

 

記憶體​區塊 資料​型別 主​裝置​訪問 從​裝置​訪問
線圈​狀態 布林 讀/寫 讀/寫
離散​輸入 布林 只讀 讀/寫
保持​暫存器 無​符號​雙​字​節​整型 讀/寫 讀/寫
輸入​暫存器 無​符號​雙​字​節​整型 只讀 讀/寫

表​1. Modbus​資料​模型​區塊

這些​區塊​允許​您​限制​或​允許​訪問​不同​的​資料​元素,​並且​為​應用​層​提供​簡化​的​機制​來​訪問​不同​的​資料​型別。

這些​區塊​是​完全​概念​性的。 它們​可能​作為​獨立​的​記憶體​地址​存在​於​給​定​的​系統​中,​但​也​可能​重疊。 例如,​線圈​狀態​1​可能​存在​於​與​保持​暫存器​1​所​代表​的​字​的​第​一位​相同​的​記憶體​中。 尋​址​方案​完全​由​從​裝置​定義,​其​對​每​個​記憶體​區​的​解釋​是​裝置​資料​模型​的​重要​組成​部分。

資料​模型​定址

該​規範​將​每​個​區塊​定義​為​包含​多​達​65,536(216)​個​元素​的​地址​空間。 在​PDU​的​定義​中,​Modbus​定義​了​每​個​資料​元素​的​地址,​範圍​從​0​到​65,535。​但是,​每​個​資料​元素​的​編號​從​1​到​n,​其中​n​的​最大值​為​65,536。​也就是說,​線圈​狀態​1​位於​地址​0​的​線圈​狀態​區塊​中,​而​保持​暫存器​54​位於​從​機​被​定義​為​保持​暫存器​的​記憶體​部分​中的​地址​53。

規範​允許​的​全部​範圍​不需要​給​定​裝置​實現。 例如,​裝置​可能​會​選擇​不​執行​線圈、​離散​輸入​或​輸入​暫存器,​而​只​使用​保持​暫存器​150​至​175​和​200​至​225。​這​是​完全​可以​接受​的,​並且​通過​例外​來​處理​無效​的​訪問​嘗試。

資料​尋​址​範圍

雖然​規範​將​不同​的​資料​型別​定義​為​存在​於​不同​的​區塊​中,​並​為​每​種​型別​分配​一個​本地​地址​範圍,​但​這​並不​一定​會​轉化​為​用於​記錄​或​理解​給​定​裝置​的​Modbus​可​訪問​記憶體​的​直觀​編​址​方案。 為了​簡化​對​記憶體​區塊​位置​的​理解,​引入​了​一種​編號​方案,​其​將​前​綴​新增​到​所​討論​的​資料​的​地址​中。

例如,​裝置​手冊​不會​引用​地址​13​暫存器​14​的​資料​項,​而是​引用​地址​4,014,40,014​或​400,014​的​資料​項。​在​任何​情況​下,​第​一個​數字​都是​4,​表示​保持​暫存器,​剩餘​數字​則​表示​指定​地址。 4XXX、​4XXXX​和​4XXXXX​的​區別​取決​於​裝置​使用​的​地址​空間。 如果​所有​65,536​個​暫存器​都在​使用​中,​應該​使用​4XXXXX​符號,​因為​其​允許​範圍​為​400,001~465,536。​如果​只​使用​幾個​暫存器,​通常​的​做法​是​使用​範圍​4,001​到​4,999。

在​這種​尋​址​方案​中,​每​種​資料​型別​都​被​分配​了​一個​前​綴,​如​表​2​所​示。

 

資料​區塊 字首
線圈​狀態 0
離散​輸入 1
輸入​暫存器 3
保持​暫存器 4

表​2. 資料​範圍​字首

線圈​狀態​存在​前​綴​為​0​的​情況。​這​意味​著​4001​的​引用​可能​指​的是​保持​暫存器​1​或​線圈​4001。​因此,​建議​所有​新​尋​址​方案​都​採用​帶​前​導​零​的​6​位​尋​址,​並​在​文​檔​中​進行​標​注。 因此,​保持​暫存器​1​的​地址​為​400,001,​而​線圈​4001​的​地址​則為​004,001。

資料​地址​起始值

記憶體​地址​和​參考​數字​之間​的​差異​會​由​給​定​應用​程式​選擇​的​索引​進一步​複雜​化。 如​前​所述,​儲存​暫存器​1​位於​地址​零。 通常,​參考​號碼​是​1​索引,​這​意味​著​給​定​範圍​的​起始​值​為​1。 因此,​400,001​就​表示​為​地址​0​的​保持​暫存器​00001。​一些​做法​選擇​以​零​開始​其​範圍,​這​意味​著​400,000​轉換​為​地址​零​的​保持​暫存器。 表​3​展示​了​這個​概念。

地址 暫存器​編號 編號​1(1​索引,​標準) 編號​(0​索引,​替換)
0 1 400001 400000
1 2 400002 400001
2 3 400003 400002

表​3.暫存器​索引​方案

 

1​索引​範圍​應用​較​為​廣泛,​強烈​建議​採用。 無論​哪​種​情況,​每​個​範圍​的​起始​值​都​應​在​文​檔​中​註明。

大​資料​型別

Modbus​標準​提供​了​一個​相對​簡單​的​資料​模型,​它​不​包含​無​符號​字​和​位​值​之外​的​其他​資料​型別。 如果​系統​的​位​值​對應​於​螺線​管​和​繼電器,​並且​字​值​對應​於​未​縮​放​的​ADC​值,​這​是​足夠​的,​但​對於​更​高階​的​系統​則​可能​不足。 因此,​許多​Modbus​實現​都​包含​跨​暫存器​邊界​的​資料​型別。 NI LabVIEW​資料​記錄​和​監​控​(DSC)​模組KEPServerEX都​定義​了​許多​參考​型別。 例如,​儲存​在​保持​暫存器​中的​字元​串​遵循​標準​格式​(400,001),​但​後​跟​一個​十進位制​數、​長度​和​字元​串​的​字​節​順序​(400,001.2H​是​指​保持​暫存器​1​中的​兩​個​字元​串,​其中​高位​字​節​對應​到​字元​串​的​第​一個​字元)。 這​是​必需​的,​因為​每​個​請求​的​大小​都是​有限​的,​所以​Modbus​主機​必須​知道​字元​串​的​確切​範圍,​而不是​像​NULL​那樣​搜尋​長度​或​分隔​符。

位​訪問

除了​允許​訪問​跨​暫存器​邊界​的​資料​之外,​一些​Modbus​主​裝置​還​支援​對​暫存器​中​各個​位​的​引用。 這​是有​好處​的,​因為​它​允許​裝置​將​相同​記憶體​範圍​內的​每​種​型別​的​資料​組合​在一起,​而不​必將​二​進位制​資料​分成​線圈​整體​和​離散​量​輸入​範圍。 這​通常​使用​小數點​和​位​索引​或​數字​進行​索引,​具體​取決​於​如何​實現。 也就是說,​第​一個​暫存器​的​第​一位​可能是​400,001.00​或​400,001.01。 建議​任何​文​檔​都要​說明​所​使用​的​索引​方案。

資料​字​節​順序

多​暫存器​資料​(單​精度​浮點​值),​可以​通過​將​資料​拆​分​到​兩​個​暫存器,​輕鬆​地​在​Modbus​中​傳輸。 由於​這​不是​由​標準​定義​的,​因此​分割​的​字​節​順序​沒有​規定。 儘管​每​個​無​符號​字​必須​以​網路​(big-​endian)​字​節​順序​傳送​以​滿足​標準,​但​許多​裝置​會​顛倒​多​字​節​資料​的​字​節​順序。 圖​2​所​示​的是​一個​不​常見​但​有效​的​例子。

圖​2.多​字​資料​的​字​節​順序​交換

請​務必​理解​裝置​如何​將​資訊​儲存​在​記憶體​中​並​對​其​進行​正確​解碼。 建議​文​檔​寫​明​系統​所​使用​的​字​順序。 如果​需要​靈活​性,​也可以​將​Endian​新增​為​系統​配置​選項,​提供​基礎​的​編碼​和​解碼​功能。

字串

字元​串​可以​很​容易​地​儲存​在​Modbus​暫存器​中。 為了​簡單​起​見,​一些​方法​要求​字元​串​長度​為​2​的​倍數,​並​使用​控制​來​填充​額外​的​空間。 字​節​順序​也是​字元​串​互動​中的​一個​變數。 字元​串​格式​可能​包含​也​可能​不​包含​NULL​作為​最終​值。 舉​個​例子,​一些​裝置​的​資料​儲存​方法​可能​如​圖​3​所​示。

圖​3. Modbus​字元​串​中的​字​節​順序​反轉

瞭解​功能​程式碼

與​資料​模型​可能​因​裝置​而​異​不同,​功能​程式碼​及其​資料​由​標準​明確​定義。 每​個​功能​都​遵循​一種​模式。 首先,​從​裝置​會​驗證​功能​程式碼、​資料​地址​和​資料​範圍​等​輸入。 然後​執行​所​請求​的​操作​並​傳送​與​程式碼​相符​的​響應。 如果​此​過程​中的​任何​步驟​失敗,​則會​向​請求​程式​返回​異常。 這些​請求​的​資料​傳輸​就​稱為​PDU。

Modbus PDU

PDU​由​一個​單字​節​的​功能​程式碼​組成,​後面​跟著​多​達​252​字​節​的​針對​特定​函式​的​資料。

圖4. Modbus PDU

功能​程式碼​是​第​一個​需要​驗證​的​項。 如果​功能​程式碼​沒有​被​接收​到​請求​的​裝置​識別,​則會​迴應​一個​異常。 如果​功能​程式碼​被​接受,​則​從​裝置​根據​功能​定義​開始​分解​資料。

 

由於​資料​包​大小​限制​為​253​字​節,​裝置​可​傳輸​的​資料​量​有限。 最​常見​的​功能​程式碼​可以​240​到​250​字​節​的​從​裝置​資料​模型​資料,​具體​取決​於​程式碼。

從​函式​執行

不同​的​函式​由​資料​模型​定義​訪問​不同​的​概念​資料​塊。 一個​常見​的​做法​是​讓​程式碼​訪問​靜態​記憶體​位置,​但​其他​行為​是​可用​的。 例如,​功能​程式碼​1(讀​取​線圈​狀態)​和​3(讀​取​保持​暫存器)​可以​訪問​記憶體​中​相同​的​物理​位置。 而​功能​程式碼​3(讀​取​保持​暫存器)​和​16(寫​入​保持​暫存器)​可以​訪問​記憶體​中​完全​不同​的​位置。 因此,​建議​在​定義​從​資料​模型​時​同時​考慮​每​個​功能​程式碼​的​執行。

無論​執行​的是​何​種​實際​行為,​所有​的​從​裝置​都應該​遵循​每​個​請求​的​簡單​狀態​流程​圖。 圖​5​是​程式碼​1​讀​取​線圈​狀態​的​一個​例子。

圖​5.Modbus​協議​規範​定義的​讀​取​線圈​狀態​流程圖

每​個​從​裝置​必須​驗證​功能​程式碼、​輸入​數量、​起始​地址、​總​範圍​以及​實際​進行​讀​取​行為​的​從屬​定義​函式​(slave-​defined function)​的​執行。

儘管​上面​的​狀態​圖​包含​了​靜態​地址​範圍,​但​真實​系統​的​需求​可能​會​使​靜態​地址​範圍​與​定義​的​數字​有所不同。 在​某些​情況​下,​從​裝置​無法​傳輸​協議​定義​的​最大​字​節​數。 也就是說,​如果​主​裝置​請求​0x07D0​輸入,​從​裝置​只能​用​0x0400​進行​響應。 如果​主​裝置​從​地址​0​開始​請求​125,​則​這​是​正確​的,​但是​如果​主​裝置​從​地址​400​開始​發出​相同​的​請求,​最後​一個​線圈​狀態​將​位於​地址​525,​超出​了​該​裝置​的​範圍,​會​導致​出現​狀態​圖​定義​的​異常​02。

標準​功能​程式碼

每​個​標準​功能​程式碼​的​定義​都​包含​在​說明​書​中。 即使​對於​最​常見​的​功能​程式碼,​在​主​裝置​上​啟用​的​功能​與​從​裝置​可以​處理​的​功能​之間​也​存在​不可避免​的​不​匹配。 為了​解決​這個​問題,​Modbus TCP​規範​的​早期​版本​定義​了三​個​一致性​類。 官方的Modbus​一致性​測試​規範沒有​引用​這些​類,​而是​在​每​個​功能​的​基礎​上​定義​一致性;​但是,​這些​仍然​很​容易​理解。 建議​任何​文​檔​都​遵循​測試​規範,​並​根據​其​支援​的​程式碼​而不是​傳統​分類​來​定義​它們​的​一致性。

0​類​程式碼

0​類​程式碼​通常​被​認為​是​有用​Modbus​裝置​的​最低​配置,​因為​它們​使​主​裝置​能夠​讀​取​或​寫​入​資料​模型。

程式碼 說明
3 讀​多​暫存器
16 寫​多​暫存器

表​4.0​類​一致性​程式碼

1​類​程式碼

1​類​功能​程式碼​由​訪問​所有​型別​的​資料​模型​所需​的​其他​程式碼​組成。 在​原始​定義​中,​這個​列表​包含​功能​程式碼​7(讀​取​異常)。 但是,​此​程式碼​由​當前​規範​定義​為​僅​限於​串​行​的​程式碼。

程式碼 說明
1 讀​線圈
2 讀​離散​輸入
4 讀​輸入​暫存器
5 寫​單​線圈
6 寫​單​暫存器
7 讀​取​異常​狀態​(僅​限​串​行)

表​5. 1​類​一致性​程式碼

2​類​程式碼

2​類​功能​程式碼​用於​更​為​專業​化​的​功能,​不太​常用。 例如,​讀/​寫​多個​暫存器​可能​有助​於​減少​請求/​響應​週期​的​總數,​但​該​行為​仍​可以​用​0​類​程式碼​實現。

程式碼 說明
15 寫​多​線圈
20 讀​檔案​記錄
21 寫​檔案​記錄
22 遮蔽​寫​暫存器
23 讀/​寫​多​暫存器
24 讀​取​FIFO

表​6. 2​類​一致性​程式碼

Modbus​封​裝​介面

Modbus​封​裝​介面​(MEI)​程式碼​功能​43​用於​封​裝​Modbus​資料​包​內的​其他​資料。 目前,​有​兩​個​MEI​號碼​可用,​13(CANopen)​和​14(裝置​識別)。

功能​43/14(裝置​識別)​非常​有用,​因為​它​允許​傳送​多​達​256​個​唯一​的​物件。 其中​一些​物件​已​預​定義​且​預​留​好,​例如​供應​商​名稱​和​產品​程式碼,​但​應用​程式​可以​將​其他​物件​定義​為​通用​資料​集。

此​程式碼​並不​常用。

例外

從​裝置​使用​異常​來​指示​各種​不良​狀況,​比如​錯誤​請求​或​不​正確​輸入。 但是,​異常​也可以​作為​對​無效​請求​的​應用​程式​級​響應。 從​裝置​不​響應​發出​異常​的​請求。 相反,​從​裝置​忽略​不​完整​或​損壞​的​請求,​並​開始​等待​新的​訊息​傳​入。

異常​以​定義​好的​資料​包​格式​報告​給​使用者。 首先​將​一個​功能​程式碼​返回​給​等​同​於​與​原始​功能​程式碼​的​請求​主​裝置,​除了​設定​了​最高​有效​位。 這​等​同​於​為​原始​功能​程式碼​的​值​加上​0x80。 異常​響應​包括​一個​異常​程式碼​來​代替​與​給​定​函式​響應​相關​的​正常​資料。

在​標準​內,​四​種​最​常見​的​異常​程式碼​是​01,02,03​和​04。​表​7​介紹​了​這些​程式碼​以及​每​種​功能​的​標準​含義。

異常​程式碼 含義
01 不​支援​接收​到​功能​程式碼。 要​確認​原始​功能​程式碼,​請​從​返回​值​中​減去​0x80。
02 嘗試​訪問​的​請求​是​一個​無效​地址。 在​標準​中,​只有​起始​地址​和​請求​的​數值​超過216時​才​會​發生​這種​情況。 但是,​有些​裝置​可能​會​限制​其​資料​模型​中的​地址​空間。
03 請求​包含​不​正確​的​資料。 在​某些​情況​下,​這​意味​著​引數​不​匹配,​例如​傳送​的​暫存器​的​數量​與“字​節​數”字​段​之間​的​引數​不​匹配。 更​常見​的​情況​是,​主機​請求​的​資料​比​從​機​或​協議​允許​的​要​多。 例如,​主​裝置​一次​只能​讀​取​125​個​保持​暫存器,​而​資源​受限​的​裝置​可能​會​將​此​值​限制​為​更少​的​暫存器。 例如,​主​裝置​一次​只能​讀​取​125​個​保持​暫存器,​而​資源​受限​的​裝置​可能​會​將​此​值​限制​為​更少​的​暫存器。
04 嘗試​處理​請求​時​發生​不可​恢復​的​錯誤。 這​是​一個​異常​的​程式碼,​表示​請求​有效,​但從​裝置​無法​執行​該​請求。

表​7.常見​的​Modbus​異常​程式碼

 

每​個​功能​程式碼​的​狀態​圖​至少​應​包含​異常​程式碼​01,​通常​包含​異常​程式碼​04,02,03,​並且​任何​其他​定義​的​異常​程式碼​都是​可​選​的。

返回​頂部

應用​資料​單元​(ADU)

除了​Modbus​協議​的​PDU​核心​定義​的​功能​外,​您​還​可以​使用​多種​網路​協議。 最​常見​的​協議​是​串​行​和​TCP/​IP,​但​也可以​使用​其他​協議,​如​UDP。 為了​在​這些​層​之間​傳輸​Modbus​所需​的​資料,​Modbus​包含​一​組​適用​於​每​種​網路​協議​的​ADU。

通用​特徵

Modbus​需要​某些​功能​來​提供​可靠​的​通訊。 單元​ID​或​地址​用​在​每​個​ADU​格式​中,​為​應用​層​提供​路​由​資訊。 每​個​ADU​都​帶有​一個​完整​的​PDU,​其中​包含​給​定​請求​的​功能​程式碼​和​相關​資料。 為了​可靠性,​每​條​訊息​都​包含​錯誤​檢查​資訊。 最後,​所有​的​ADU​都​提供​了​一種​機制​來​確定​請求​幀​的​開始​和​結束,​但​實現​這些​機制​的​方式​各不相同。

標準​格式

ADU​的​三​種​標準​格式​是​TCP、​遠端​終端​單元​(RTU)​和​ASCII。 RTU​和​ASCII ADU​通常​用於​串​行​線路,​而​TCP​則​用於​現代​TCP/​IP​或​UDP/​IP​網路。

TCP/​IP

TCP ADU​由​Modbus​應用​協議​(MBAP)​報​文​頭​和​Modbus PDU​組成。 MBAP​是​一個​通用​的​報​文​頭,​依賴​於​可靠​的​網路​層。 此​ADU​的​格式​(包括​報​文​頭)​如​圖​6​所​示。

圖​6.TCP/​IP ADU

報​文​頭​的​資料​字​段​代表​其​用途。 首先,​它​包含​一個​事務​處理​標識​符。 這​有助​於​網路​允許​同時​發生​多個​未​處理​的​請求。 也就是說,​主​裝置​可以​傳送​請求​1、​2​和​3。​在​稍​後​的​時間​點,​從​裝置​可以​以​2、​1、​3​的​順序​進行​響應,​並且​主​裝置​可以​將​請求​匹配​到​響應​並​準確​解析​資料。 這​對​以太​網​網路​很有​用。

協議​標識​符​通常​為​零,​但​您​可以​使用​它​來​擴充套件​協議​的​行為。 協議​使用​長度​字​段​來​描述​資料​包​其餘​部分​的​長度。 這個​元素​的​位置​也​表明​了​這個​報​文​頭​格式​在​可靠​的​網路​層​上​的​依賴​關係。 由於​TCP​資料​包​具有​內​置​的​錯誤​檢查​功能,​可​確保​資料​一致性​和​傳送,​因此​資料​包​長度​可​位於​報​文​頭​的​任何​位置。 在​可靠性​較​差​的​網路​上​(比如​串​行​網路),​資料​包​可能​會​丟失,​其​影響​是​即使​應用​程式​讀​取​的​資料​流​包含​有效​的​事務​處理​和​協議​資訊,​長度​資訊​的​損壞​也​會​使​報​文​頭​無效。 TCP​為​這種​情況​提供​了​適當的​保護。

TCP/​IP​裝置​通常​不​適用​單元​ID。 但是,​Modbus​是​一種​常見​的​協議,​因此​通常​會​開發​一些​網​關​來​將​Modbus​協議​轉換​為​另​一種​協議。 在​最初​的​預期​應用​中, Modbus TCP/​IP​轉​串​行​網​關​用於​連線​新的​TCP/​IP​網路​和​舊​的​串​行​網路。 這時,​單元​ID​用於​確定​PDU​對應​的​從​裝置​的​地址。

最後,​ADU​包含​一個​PDU。 對於​標準​協議,​PDU​的​長度​仍​限制​為​253​字​節。

RTU

RTU ADU​看起來​要​簡單​得​多,​如​圖​7​所​示。

圖7. RTU ADU

與​較​為​複雜​的​TCP/​IP ADU​不同​的是,​除了​核心​PDU​之外,​該​ADU​僅​包含​兩​條​資訊。 首先,​地址​用於​定義​PDU​對應​的​從​裝置。 在​大​多數​網路​中,​地址​0​定義​的是“廣播”地址。 也就是說,​主​裝置​可以​傳送​輸出​命令​到​地址​0,​而​所有​從​裝置​應​處理​該​請求,​但是​不​做出​任何​響應。 除了​這個​地址​外,​CRC​還​用於​確保​資料​的​完整性。

然而,​現在​的​實現​機制​遠​沒有​那麼​簡單。 資料​包​的​首尾​一對​沉默​時間​(silent time),​即​總​線上​沒有​通訊​的​時​段。​對於​9,600​的​波特​率,​這個​速率​大約是​4ms。​該​標準​定義​了​一個​最小​沉默​長度,​不論​波特​率​如何,​都​低於​2 ms。

 

首先,​這​存在​效能​缺陷,​因為​在​處理​資料​包​之前​裝置​必須​等待​空閒​時間​結束。 然而,​更​危險​的是​串​行​傳輸​引入​了​不同​技術,​並且​波特​率​比​標準​更​快。 例如,​使用​USB/​串​口​轉換​器​電纜,​您​無法​控制​資料​的​資料​包​和​資料​傳輸。 測試​表明,​結合​NI-​VISA​驅動​程式​使用​USB​轉​串​口​電纜​會​在​資料​流​中​引入​了​尺寸​可變​的​大​間隙,​而​這些​間隙 – 沉默​期 – 會“誘​騙”符合​規範​的​程式碼​相信​訊息​是​完整​的。 由於​訊息​不​完整,​通常​會​導致​CRC​無效,​並​導致​裝置​將​ADU​解釋​為​損壞。

除了​傳輸​問題​之外,​現代​驅動​程式​技術​還​大量​提取​串​行​通訊,​並且​通常​需要​應用​程式​程式碼​中的​輪​詢​機制。 例如,​除非​通過​輪​詢​端​口上​的​字​節,.NET Framework 4.5 SerialPort Class和​NI-​VISA​驅動​程式​都不​提供​檢測​串​行​線路​上​的​沉默​的​機制。 這​會​導致​效能​降低​(如果​輪​詢​執行​過​慢)​或​CPU​使用​率​過​高​(如果​輪​詢​執行​過​快)。

解決​這些​問題​的​常用​方法​是​打破​Modbus PDU​和​網路​層​之間​的​抽象​層。 也就是說,​串​行​程式碼​詢問​Modbus PDU​資料​包​以​確定​功能​程式碼。 結合​資料​包​中的​其他​資料,​可以​發現​剩餘​資料​包​的​長度,​從而​確定​資料​包​的​結尾。 利用​這些​資訊,​可以​使用​更​長​的​超​時​時間,​以​允許​傳輸​間隙,​並且​應用​程式​級​的​輪​詢​速度​可能​更慢。 這種​機制​推薦​用於​新的​開發。 不​採用​此​方法​可能​會​遇到​大於​預期​數量​的“損壞”資料​包。

ASCII

如​圖​8​所​示,​ASCII ADU​比​RTU​更​複雜,​但​也​避免​了​RTU​資料​包​的​許多​問題。 然而,​它​自身​也有​一些​缺點。

圖 8. ASCII ADU

為了​解決​確定​資料​包​大小​的​問題,​ASCII ADU​為​每​個​資料​包​定義​了​一個​明確​且​唯一​的​開始​和​結束。 也就是說,​每​個​資料​包​以“:”開始 並​以​回車​(CR)​和​換​行​符​(LF)​結束。 另外,​像​NI-​VISA​和.NET Framework SerialPort Class​這樣​的​串​行​API​可以​輕鬆​讀​取​緩衝​區​中的​資料,​直到​收到​特定​字元​的​CR/​LF​為止。 這些​特性​有助​於​在​現代​應用​程式​程式碼​中​有效​地​處理​串​行​線路​上​的​資料​流。

ASCII ADU​的​缺點​是​所有​資料​都​以​ASCII​編碼​的​十六​進位制​字元​進行​傳輸。 也就是說,​針對​功能​程式碼​3(0x03)​傳送​的​不是​單​個​字​節,​而是​傳送​ASCII​字元“0”和“3”或​0x30/0x33。 這​使​協議​更​具​可讀​性,​但​也​意味​著​必須​通過​串​行​網路​傳輸​兩​倍​的​資料,​並且​傳送​和​接收​應用​程式​必須​能夠​解析​ASCII​值。

擴充套件​Modbus

Modbus​是​一種​相對​簡單​和​開放​的​標準,​可以​進行​修改​以​適應​給​定​應用​的​需求。 這​常用​於​HMI​和​PLC​或​PAC​之間​的​通訊,​因為​在​這種​情況​下​組織​可以​控制​協議​的​首尾。 例如,​感測器​的​開發​人員​更​可能​遵守​書面​標準,​因為​他們​通常​只​控制​其​從​裝置​的​實現,​互通性​也是​可能​實現​的。

一般​來說,​不​建議​修改​協議。 本​節​僅​作為​對​其他​人​用​來​調整​協議​行為​的​機制​的​確認。

返回​頂部

新​功能​程式碼

Modbus​標準​定義​了​一些​功能​程式碼,​但​也​可​允許​您​開發​更多​的​功能​程式碼。 具體​而言,​功能​程式碼​1​至​64,73​至​99​以及​111​至​127​是​預​留​的​並​保證​唯一​的​公共​程式碼。 其餘​程式碼​65​至​72​和​100​至​110​可​由​使用者​自​定義。 使用​這些​使用者​定義​的​程式碼​時,​您​可以​使用​任何​資料​結構。 資料​甚至​可能​超過​Modbus PDU​的​標準​253​字​節​限制,​但​應​驗證​整個​應用​程式​以​確保​其他​層​在​PDU​超過​標準​限制​時​按​預期​工作。 高於​127​的​功能​程式碼​預​留作​異常​響應。

返回​頂部

網路層

除了​串​行​和​TCP​之外,​Modbus​還​可以​在​許多​網路​層​上​執行。 一個可能的​實現​是​UDP,​因為​它​適合​於​Modbus​通訊​風格。 Modbus​本質​上​是​基於​訊息​的​協議,​因此​UDP​能夠​傳送​明確​定義​的​資訊​包,​而​不需要​任何​額外​的​應用​程式​級​資訊,​如​起始​字元​或​長度,​這​使得​Modbus​非常​易​於​實現。 Modbus PDU​資料​包​可以​使用​標準​的​UDP API​傳送,​不需要​額外​的​ADU​或​重新​使用​現有​的​ADU,​並​由​另一​端​完全​接收。 雖然​由於​其​內​置​確認​系統,​TCP​對​某些​協議​有利,​但​Modbus​是在​應用​層​執行​確認。 因此,​以​這種​方式​使用​UDP​會​消除​TCP ADU​中的​事務​處理​標識​符​字​段,​從而​消除​了​存在​多個​同時​發生​的​未完成​事務​的​可能性。 因此,​主​裝置​必須​是​同步​主​裝置,​或者​UDP​資料​包​必須​有​一個​標識​符​以​幫助​主​裝置​組織​請求​和​響應。 建議​的​做法​是在​UDP​網路​層​上​使用​TCP/​IP ADU。

返回​頂部

ADU​修改

最後,​應用​程式​可以​選擇​修改​ADU,​或​使用​現有​ADU​的​未​使用​部分​(如​TCP)。 例如,​TCP​定義​了​一個​16​位​長度​字​段、​一個​16​位​協議​和​一個​8​位​單元​ID。​鑑於​最大​的​Modbus PDU​是​253​字​節,​長度​字​段​的​高​字​節​始終​為​零。 對於​Modbus/​TCP,​協議​字​段​和​單元​ID​始終​為​零。 協議​的​簡單​擴充套件​可以​通過​將​協議​字​段​更改​為非​零​數字​並​使用​兩​個​未​使用​的​字​節​(單元​ID​和​長度​字​段​的​高​字​節)​來​傳送​兩​個​附加​PDU​的​長度,​從而​同時​傳送​三​個​資料​包​(請​參閱​圖​9)。

圖​9. TCP ADU​修改​示例

 

分享到: