modbus-tcp 協議詳解

Modbus由MODICON公司於1979年開發,是一種工業現場總線協議標準。1996年施耐德公司推出基於以太網TCP/IP的Modbus協議,ModbusTCP。
Modbus通信的設備分爲主站(mater)和從站(slave),主站爲主動方,從站爲被動方。

通信過程

通信的過程爲:

  1. 主站設備主動向從站設備發送請求
  2. 從站設備處理主站的請求後,向主站返回結果。
  3. 如果從站設備處理請求出現異常,則向主站設備返回異常功能碼。

數據傳輸方式

modbus的數據傳輸被定義爲對以下4個存儲塊的讀寫:

  1. 線圈(coils) 操作單位爲1位字的開關量,PLC的輸出位,在Modbus中可讀可寫
  2. 離散量(discreteinputs) 操作單位爲1位字的開關量,PLC的輸入位,在Modbus中只讀
  3. 輸入寄存器(inputregisters) 操作單位爲16位字(兩個字節)數據,PLC中只能從模擬量輸入端改變的寄存器,在Modbus中只讀
  4. 保持寄存器(holdingregisters) 操作單位爲16位字(兩個字節)數據,PLC中用於輸出模擬量信號的寄存器,在Modbus中可讀可寫

MODBUS-TCP報文結構

modbus-tcp報文結構:
在這裏插入圖片描述
如上圖所示:modbus-tcp的報文由MBAP+PDU組成。

MBAP報文頭

其中MBAP報文頭的組成爲:

長度 描述
事務元標識符 2 個字節 MODBUS 請求/響應事務處理的識別碼,主要用於在主站設備在接收到響應時能知道是哪個請求的響應
協議標識符 2 個字節 對於MODBUS 協議來說,這裏恆爲0
長度 2 個字節 以下字節的數量,也就是完整報文的字節數減去6
單元標識符 1 個字節 串行鏈路或其它總線上連接的遠程從站的識別碼,也就是要訪問的從站的標識號,因爲只有一個字節,所以一個主站最多隻能訪問256個從站設備

由上表可知,報文頭爲 7 個字節長。

PDU報文體

PDU的組成爲功能碼(一個字節)和數據(n個字節)

其中功能碼爲一個字節,modbus定義的功能碼有:

  • 01 讀線圈(coils)狀態,讀取單個或多個
  • 02 讀離散輸入(discreteinputs)狀態,讀取單個或多個
  • 03 讀保持寄存器(holdingregisters),讀取單個或多個
  • 04 讀輸入寄存器(inputregisters),讀取單個或多個
  • 05 寫單個線圈(coils)狀態,單個寫入
  • 06 寫單個保持寄存器(holdingregisters),單個寫入
  • 15 寫多個線圈(coils),多個寫入
  • 16 寫多個保持寄存器(holdingregisters),多個寫入

另外,當響應報文的功能碼最高位爲1時(即:(function & 0x80) != 0),表示爲異常響應,這時數據爲一個字節的異常碼,具體的異常碼定義有:

  • 01 功能碼不能被從機識別
  • 02 從機的單元標識符不正確
  • 03 值不被從機接受
  • 04 當從機試圖執行請求的操作時,發生了不可恢復的錯誤。
  • 05 從機已接受請求並正在處理,但需要很長時間。返回此響應是爲了防止在主機中發生超時錯誤。主站可以在下一個輪詢程序中發出一個完整的消息,以確定處理是否完成。
  • 06 從站正在處理長時間命令。Master應該稍後重試。
  • 07 從站不能執行程序功能。主站應該向從站請求診斷或錯誤信息。
  • 08 從站在內存中檢測到奇偶校驗錯誤。主設備可以重試請求,但從設備上可能需要服務。
  • 10 專門用於Modbus網關。表示配置錯誤的網關。
  • 11 專用於Modbus網關的響應。當從站無法響應時發送。

PDU報文詳情

1、讀線圈

請求報文:

功能碼:01,一個字節 偏移量offset(讀取數據的開始位置),兩個字節 讀取數量,兩個字節

正常響應報文:

功能碼:01,一個字節 數據長度(字節數),一個字節 線圈狀態數據,n個字節(由於網絡傳輸的數據都是以整字節爲單位的,所以收到的數據可能比請求中要讀的位數要多,這時按位將數據轉換爲開關量,只需解析請求中讀取數量字段設定的位數就可以了

異常響應報文:

功能碼:129(0x81),一個字節 異常碼,一個字節

2、讀離散輸入

請求報文:

功能碼:02,一個字節 偏移量offset(讀取數據的開始位置),兩個字節 讀取數量,兩個字節

正常響應報文:

功能碼:02,一個字節 數據長度(字節數),一個字節 離散輸入狀態數據,n個字節(由於網絡傳輸的數據都是以整字節爲單位的,所以收到的數據可能比請求中要讀的位數要多,這時按位將數據轉換爲開關量,只需解析請求中讀取數量字段設定的位數就可以了

異常響應報文:

功能碼:130(0x82),一個字節 異常碼,一個字節

3、讀保持寄存器

請求報文:

功能碼:03,一個字節 偏移量offset(讀取數據的開始位置),兩個字節 讀取數量,兩個字節

正常響應報文:

功能碼:03,一個字節 數據長度(字節數,這裏應該是請求報文中的讀取數量的2倍),一個字節 保持寄存器數據,n個字節(數據的字節數應該是請求報文中的讀取數量的2倍

異常響應報文:

功能碼:131(0x83),一個字節 異常碼,一個字節

4、讀輸入寄存器

請求報文:

功能碼:04,一個字節 偏移量offset(讀取數據的開始位置),兩個字節 讀取數量,兩個字節

正常響應報文:

功能碼:04,一個字節 數據長度(字節數,這裏應該是請求報文中的讀取數量的2倍),一個字節 輸入寄存器數據,n個字節(數據的字節數應該是請求報文中的讀取數量的2倍

異常響應報文:

功能碼:132(0x84),一個字節 異常碼,一個字節

5、寫單個線圈

請求報文:

功能碼:05,一個字節 偏移量offset(寫入數據的開始位置),兩個字節 要寫入的線圈狀態值(只關注0和非0),兩個字節

正常響應報文:

功能碼:05,一個字節 偏移量offset(寫入數據的開始位置),兩個字節 要寫入的線圈狀態值(只關注0和非0),兩個字節

異常響應報文:

功能碼:133(0x85),一個字節 異常碼,一個字節

6、寫單個保持寄存器

請求報文:

功能碼:06,一個字節 偏移量offset(寫入數據的開始位置),兩個字節 要寫入的保持寄存器數據,兩個字節

正常響應報文:

功能碼:06,一個字節 偏移量offset(寫入數據的開始位置),兩個字節 要寫入的保持寄存器數據,兩個字節

異常響應報文:

功能碼:134(0x86),一個字節 異常碼,一個字節

7、寫多個線圈

請求報文:

功能碼:15,一個字節 偏移量offset(寫入數據的開始位置),兩個字節 要寫入的數量,兩個字節 數據長度(字節數),一個字節 線圈狀態數據,n個字節

正常響應報文:

功能碼:15,一個字節 偏移量offset(寫入數據的開始位置),兩個字節 要寫入的數量,兩個字節

異常響應報文:

功能碼:143(0x8f),一個字節 異常碼,一個字節

8、寫多個保持寄存器

請求報文:

功能碼:16,一個字節 偏移量offset(寫入數據的開始位置),兩個字節 要寫入的數量,兩個字節 數據長度(字節數),一個字節 保持寄存器數據,n個字節

正常響應報文:

功能碼:16,一個字節 偏移量offset(寫入數據的開始位置),兩個字節 要寫入的數量,兩個字節

異常響應報文:

功能碼:144(0x90),一個字節 異常碼,一個字節
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章