Modbus功能碼詳解
Modbus功能碼是Modbus消息幀(報文)的重要組成部分,是Modubs協(xié)議中通信事務處理的基礎,代表消息將要執(zhí)行的動作。
功能碼概要
簡而言之,Modbus功能碼占用一個字節(jié),取值范圍是1127,之所以127以上不能使用,是因為Modbus規(guī)定出現(xiàn)異常時,功能碼+0x80(十進制128)代替異常狀態(tài),因此129(1+128)255(127+128)的取值代表異常碼。
Modbus標準協(xié)議中規(guī)定了由3類Modbus功能碼,分別是:
-
公共功能碼
- 被明確定義的功能碼
- 保證唯一性
- 由Modbus協(xié)會確認,并提供公開的文檔;
- 可進行一致性測試
- 包括協(xié)議定義的功能碼和保留將來使用的功能碼
-
用戶自定義功能碼
- 有兩個用戶自定義功能碼區(qū)域,分別是6572和100110;
- 用戶自定義,不保證唯一性。
-
保留功能碼
保留功能碼是因為歷史遺留原因,某些公司的傳統(tǒng)產(chǎn)品上現(xiàn)行使用的功能碼不作為公共使用。
Modbus部分功能碼如下:
代碼 | 名稱 | 寄存器PLC地址 | 位/字操作 | 操作數(shù)量 |
---|---|---|---|---|
01 | 讀線圈狀態(tài) | 00001~09999 | 位操作 | 單個或多個 |
02 | 讀離散輸入狀態(tài) | 10001~19999 | 位操作 | 單個或多個 |
03 | 讀保持寄存器 | 40001~49999 | 字操作 | 單個或多個 |
04 | 讀輸入寄存器 | 30001~39999 | 字操作 | 單個或多個 |
05 | 寫單個線圈 | 00001~09999 | 位操作 | 單個 |
06 | 寫單個保持寄存器 | 40001~49999 | 字操作 | 單個 |
15 | 寫多個線圈 | 00001~09999 | 位操作 | 多個 |
16 | 寫多個保持寄存器 | 40001~49999 | 字操作 | 多個 |
功能碼可分為位操作和字操作兩類。位操作的最小單位為一位(bit),字操作的最小單位為兩個字節(jié)。
- 位操作指令:讀線圈狀態(tài)功能碼01,讀(離散)輸入狀態(tài)功能碼02,寫單個線圈功能碼06和寫多個線圈功能碼15.
- 字操作指令:讀保持寄存器功能碼03,讀輸入寄存器功能碼04,寫單個保持寄存器功能碼06,寫多個保持寄存器功能碼16.
01(0x01)讀取線圈/離散量輸出狀態(tài)
功能說明讀取從設備的線圈或離散量輸出的狀態(tài),即各DO的ON/OFF狀態(tài)。消息幀中指定了需讀取的線圈起始地址和線圈數(shù)目。需要注意的一點是,在Modbus協(xié)議規(guī)定的PDU中,規(guī)定所有線圈或寄存器地址從0開始計算。
查詢報文查詢幀的消息里,定義了從設備地址為3,并讀取從設備的Modbus地址0001900055(線圈地址0002000056)共計37個狀態(tài)值。起始線圈地址為0x13(即十進制00019),因為線圈地址從0開始計數(shù)。
Modbus協(xié)議規(guī)定,起始地址由2個字節(jié)構成,取值范圍為0x00000xFFFF;線圈數(shù)量由2個字節(jié)構成,取值范圍為0x00010x07D0(即十進制1~2000).
ASCII模式中直接按每4個位拆分為對應的字符表示。
響應報文響應報文的數(shù)據(jù)字段中,每一個線圈占用1個位(bit),狀態(tài)被表示為1=ON和0=OFF兩種類型。第1個數(shù)據(jù)字節(jié)的LSB(最低有效位)標識查詢報文中的起始地址線圈的狀態(tài)值,其他線圈依次類推,一直到這個字節(jié)的MSB(最高有效位)位置,并在后續(xù)字節(jié)中按照同樣的方式(由低到高)排列。
一個字節(jié)可以表示8個線圈的狀態(tài),如果最后的數(shù)據(jù)字節(jié)中不能填滿8個線圈的狀態(tài),則由0填充。對應于查詢報文中需要讀取37個線圈的狀態(tài),則共需要5個字節(jié)保存狀態(tài)值。
02(0x02)讀取離散量輸入值
功能說明該功能碼用于讀取從設備的離散輸入即DI的ON/OFF狀態(tài)。消息幀中制定了需讀取的離散輸入寄存器起始地址和數(shù)目,可讀取1~2000個連續(xù)的離散量輸入狀態(tài)。如果從設備接受主設備的請求則回復功能碼02,并返回離散量輸入各離散量的當前狀態(tài)。如果返回的離散輸入數(shù)量的個數(shù)不是8的整數(shù)倍,將用0填充最后數(shù)據(jù)字節(jié)的剩余位。
03(0x03)讀取保持寄存器值
功能說明用于讀取從設備保持寄存器的內(nèi)容,不支持廣播模式。消息幀中指定了需讀取的保持寄存器的起始地址和數(shù)目。而保持寄存器中各地址的具體內(nèi)容和意義,則由設備開發(fā)者自行規(guī)定。
查詢報文在查詢報文中,必須指定保持寄存器的開始地址和需讀取的寄存器數(shù)量。起始位置由2個字節(jié)構成,取值范圍為0x00000xFFFF;寄存器數(shù)量由2個字節(jié)構成,取值范圍為0x00010x007D(即十進制1~255),即最多可以連續(xù)讀取125個寄存器。
有一點特別需要注意,Modbus的保持寄存器和輸入寄存器是以字(Word)為基本單位的(1Word=2byte),所以,如果讀取保持寄存器地址為40001開始的一個16位(bit)的無符號數(shù),那么返回2個字節(jié)(byte),并可以從40002開始讀取下一個16位的無符號數(shù)。如果需讀取寄存器地址40001開始的是一個32位浮點數(shù),則需要返回4個字節(jié),即必須連續(xù)讀取40001和40002的內(nèi)容,而且下一個32位浮點數(shù)必須從40003開始讀取。對于浮點數(shù)(或者32位的整數(shù))而言,連續(xù)讀取的兩個寄存器之間存在字節(jié)序和大小端的問題,這一點在開發(fā)時必須引起注意。
04(0x04)讀取輸入寄存器值
功能說明同功能碼03類似,該功能碼用于讀取從設備輸入寄存器的內(nèi)容,不支持廣播模式。消息幀中指定了需讀取的輸入寄存器的起始地址和數(shù)目。而輸入寄存器中各地址的具體內(nèi)容和意義,則由設備開發(fā)者自行規(guī)定。
查詢報文在查詢報文中,必須指定輸入寄存器的起始地址和需讀取的寄存器數(shù)量。
本功能碼中,起始地址由2個字節(jié)構成,取值范圍為0x00000xFFFF;寄存器數(shù)量由2個字節(jié)構成,取值范圍為0x00010x007D(即十進制1~125),即最多可以連續(xù)讀取125個寄存器。
同樣有一點需要注意,Modbus的保持寄存器和輸入寄存器是以字為基本單位的。所以對于浮點數(shù)(或32為的整數(shù))而言,連續(xù)讀取的兩個寄存器之間存在字節(jié)序和大小端的問題。
05(0x05)寫單個線圈或單個離散輸出
功能說明用于將單個線圈寄存器(或離散輸入)設置為ON或OFF,該功能碼支持廣播模式,在廣播模式下,所有從站設備的同一地址的值將被統(tǒng)一修改,查詢報文中的ON或OFF狀態(tài)由報文數(shù)據(jù)字段的常熟指定,0xFF00表示ON狀態(tài),0x0000表示OFF狀態(tài)。其他所有值均是非法的,并且對寄存器不起作用,將會返回異常相應。
查詢報文本功能碼中,起始地址由2個字節(jié)構成,取值范圍為0x0000~0xFFFF;變更目標數(shù)據(jù)由2個字節(jié)構成,取值只能為0xFF00或0x0000.
響應報文對于從設備,在線圈或離散輸出寄存器正常變更的情況下,則返回于查詢報文一樣的響應報文。如果修改失敗,則返回一個異常響應。
06(0x06)寫單個保持寄存器
用于更新從設備的單個保存寄存器的值。該功能嗎支持廣播模式,在廣播模式下,所有設備的同一地址的值將被統(tǒng)一修改。
查詢報文查詢報文中需要指定從設備地址以及需要變更的保持寄存器地址和設定的值。同樣需要注意的是,查詢報文中,寄存器地址從地址0開始技術。
本功能碼中,起始地址由2個字符構成,取值范圍為0x00000xFFFF;變更目標數(shù)據(jù)由2個字節(jié)構成,取值范圍為0x00000xFFFF。
響應報文對于從設備,在保持寄存器正常變更的情況下,則返回于查詢報文一樣的響應報文。如果修改失敗,則返回一個異常返回。
08(0x08)診斷功能
功能說明該功能碼僅用于串行鏈路,主要用于檢測主設備和從設備之間的通信故障,或檢測從設備的各種內(nèi)部故障,該功能碼不支持廣播。為了區(qū)別各診斷類型,查詢報文中提供了2各字節(jié)的子功能碼字段。
通常在正常的響應報文中,從設備將鴛鴦回復功能碼和子功能碼。
查詢報文查詢報文中需要指定從設備地址、功能碼以及子功能碼。
例如,表4-15中表示了子功能碼“原樣返回查詢數(shù)據(jù)”的診斷功能,其中子功能碼為0(0x0000)。在子功能碼0x0000的情況下,數(shù)據(jù)字段可以為任意值。
本功能碼中,子功能碼由2個字節(jié)構成,取值則根據(jù)意義不同;數(shù)據(jù)字段由2個字節(jié)構成,其取值由子功能碼確定。
響應報文對于從設備,在保持寄存器正常變更的情況下,則返回與查詢報文一樣的響應報文。如果修改失敗,則返回一個異常響應。
診斷子功能碼
各常用診斷子功能碼定義如下:
- Return Query Data(00)
診斷內(nèi)容 | 原樣返回查詢報文 |
---|---|
子功能碼 | 0x00,0x00 |
查詢報文數(shù)據(jù)字段 | 任意16位數(shù)據(jù) |
響應報文數(shù)據(jù)字段 | 同查詢報文 |
- Restart Communications Option(01)
診斷內(nèi)容 | 重啟通信選項 用于初始化并重新啟動從站設備,清除所有通信事件計數(shù)器。 如果端口處于Listen Only Mode下,不返回響應;否則在重啟之前返回響應 |
---|---|
子功能碼 | 0x00,0x01 |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 保持事件記錄 |
0xFF,0x00 清除事件記錄 | |
響應報文數(shù)據(jù)字段 | 同查詢報文 |
- Return Diagnostics Register(02)
診斷內(nèi)容 | 返回診斷寄存器 |
---|---|
子功能碼 | 0x00,0x02 |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 |
響應報文數(shù)據(jù)字段 | 診斷寄存器的內(nèi)容 |
- Force Listen Only Mode(04)
診斷內(nèi)容 | 強制只聽模式 強制被尋址的從站設備進入只聽模式,使得此設備與網(wǎng)絡中的其他設備斷開,不返回響應 |
---|---|
子功能碼 | 0x00,0x0A |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 |
響應 |
- Clear Counters and Diagnostic Register(10,0x0A)
診斷內(nèi)容 | 清除計數(shù)器和診斷寄存器 |
---|---|
子功能碼 | 0x00,0x0A |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 |
響應報文數(shù)據(jù)字段 | 同查詢報文 |
- Return Bus Message Count(11,0x0B)
診斷內(nèi)容 | 返回總線報文計數(shù) |
---|---|
子功能碼 | 0x00,0x0B |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 |
響應報文數(shù)據(jù)字段 | 返回報文的計數(shù)值 |
- Return Bus Communication Error Count(12,0x0C)
診斷內(nèi)容 | 返回總線通信CRC差錯計數(shù) |
---|---|
子功能碼 | 0x00,0x0C |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 |
響應報文數(shù)據(jù)字段 | 返回報文的CRC出錯總數(shù) |
- Return Bus Exception Error Count(13,0x0D)
診斷內(nèi)容 | 返回總線異常差錯計數(shù) |
---|---|
子功能碼 | 0x00,0x0D |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 |
響應報文數(shù)據(jù)字段 | 返回異常響應的總數(shù) |
- Return Slave Message Count(14,0x0E)
診斷內(nèi)容 | 返回從站設備報文總數(shù) |
---|---|
子功能碼 | 0x00,0x0E |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 |
響應報文數(shù)據(jù)字段 | 返回從站設備接收報文總數(shù) |
- Return Slave No Response Count(15,0x0F)
診斷內(nèi)容 | 返回從站設備無響應計數(shù) |
---|---|
子功能碼 | 0x00,0x0F |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 |
響應報文數(shù)據(jù)字段 | 返回加電后沒有返回響應的報文數(shù)量 |
- Return Slave Busy Count(17,0x11)
診斷內(nèi)容 | 返回從站設備忙計數(shù) |
---|---|
子功能碼 | 0x00,0x11 |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 |
響應報文數(shù)據(jù)字段 | 返回加電后異常響應忙的報文數(shù)量 |
- Return Bus Character Overrun Count(18,0x12)
診斷內(nèi)容 | 返回總線字符超限的計數(shù) |
---|---|
子功能碼 | 0x00,0x12 |
查詢報文數(shù)據(jù)字段 | 0x00,0x00 |
響應報文數(shù)據(jù)字段 | 返回超限的報文數(shù)量 |
11(0x0B)獲取通信事件計數(shù)器
功能說明該功能碼主要用于獲取從設備通信計數(shù)器中的狀態(tài)字和事件計數(shù)的值,本功能不支持廣播模式。通過在通信報文之前和之后讀取通信事件計數(shù)值,可以確定從設備是否正常處理報文。
對于正常完成報文處理和傳輸?shù)膱龊,事件計?shù)器增加1;而對于異常響應、輪詢命令或讀取事件計數(shù)器(即0x0B功能碼)的場合,則計數(shù)器不變。通過【0x08】診斷功能中的子功能碼【Restart Communiaction Option (0x01)】和【Clear Counters and Diagnostic Register(0x00A)】,可以復位事件寄存器。
響應報文對于從設備,在正常情況下,響應報文返回2個字節(jié)的狀態(tài)字和2個字節(jié)的事件計數(shù)。其中,如果從站設備處于忙狀態(tài),那么狀態(tài)字將為0xFFFF,否則狀態(tài)字將為0x0000.
12(0x0C)獲取通信事件記錄
功能說明該功能碼主要用于從從設備獲取轉(zhuǎn)狀態(tài)字、事件計數(shù)、報文計數(shù)以及事件字節(jié)字段。其中狀態(tài)字和事件計數(shù)與功能碼11(0x0B)獲取的值一致。
響應報文對于從站設備,在正常情況下響應報文包括一個2字節(jié)狀態(tài)字字段、一個2字節(jié)事件計數(shù)字段、一個2字節(jié)消息計數(shù)字段以及0~64個字節(jié)的事件字段。因為事件字段是變長的,所以增加了一個1字節(jié)的數(shù)據(jù)長度字段,以方便讀取響應數(shù)據(jù)。
15(0x0F)寫多個線圈
功能說明該功能碼,用于將連續(xù)的多個線圈或離散輸出設置為ON/OFF狀態(tài),支持廣播模式,在廣播模式下,所有從站設備的同一地址被統(tǒng)一修改。本功能碼中,起始地址字段由2個字節(jié)構成,取值范圍為0x00000xFFFF;而寄存器數(shù)量字段由2個字節(jié)構成,取值范圍為0x00010x07B0.
查詢報文查詢報文中,包含了請求數(shù)據(jù)字段,用于定義ON/OFF狀態(tài)。數(shù)據(jù)字段中為邏輯1的位對應ON;邏輯0的位對應OFF。其中,ON/OFF與數(shù)據(jù)字段的對應關系可參考“01(0x01)讀取線圈/離散量輸出狀態(tài)”中的內(nèi)容
響應報文對于從設備,在正常情況下響應報文包括功能碼、起始地址以及寫入的線圈數(shù)量。
16(0x10)寫多個保持寄存器
功能說明該功能碼用于設置或?qū)懭霃脑O備保持寄存器的多個連續(xù)的地址塊(1123個寄存器),支持廣播模式,在廣播模式下,所有從站設備的同一地址的值將被統(tǒng)一修改。本功能碼中,起始地址字段由2個字節(jié)構成,取值范圍為0x00000xFFFF;而寄存器數(shù)量字段由2個字節(jié)構成,取值范圍為0x0001~0x007B。
查詢報文查詢報文中,包含了請求數(shù)據(jù)字段。數(shù)據(jù)字段保存需寫入的數(shù)值,各數(shù)據(jù)按每個寄存器2個字節(jié)存放。
響應報文對于從設備,在正常情況下響應報文包括功能碼、起始地址以及寫入的寄存器數(shù)量。
在實際開發(fā)過程中,功能碼“16(0x10)寫多個寄存器”常常用于方便用戶寫入多字節(jié)類型的數(shù)據(jù)。
17(0x11)報告從站ID(僅用于串行鏈路)
功能說明該功能碼用于讀取從站設備的ID、類型描述、當前狀態(tài)以及其他信息,不支持廣播模式。響應消息的構成依賴于設備而不同。
響應報文對于從設備,在正常情況下響應報文包括從站ID、運行狀態(tài)以及其他附加信息。響應報文的組成由開發(fā)者決定。
Modbus異常響應
以上介紹了一些常見的公共功能碼的報文(消息幀)構成,對于廣播模式以外的查詢報文,都希望能夠獲取一個正常的響應報文。在通常的情況下,從站設備將返回一個正常響應報文,但是,在某些特殊情況下,將返回異常響應報文。對于查詢報文,存在以下4中處理反饋:
- 正常接收,正常處理,返回正常響應報文;
- 因為通信錯誤等原因,造成從站設備沒有接收到查詢報文,主站設備將按超時處理;
- 從站設備接收到的查詢報文存在通信錯誤(例如LRC、CRC錯誤等),此時從站設備將丟棄報文不響應,主站設備將按超時處理;
- 從站設備接收到正確的報文,但是超過處理范圍(例如,不存在的功能碼或者寄存器等),此時從站設備將返回包括異常碼(Exception Code)的響應報文。
異常響應報文由從站地址、功能碼以及異常碼構成。其中,功能碼與正常響應報文不同,在異常響應報文中,功能碼最高位(即MSB)被設置為1.因為Modbus協(xié)議中功能碼占用一個字節(jié),故用表達式描述為:異常功能碼=正常功能碼+0x80.
常見的異常碼說明
異常碼 名稱 說明 01 非法功能碼 從站設備不支持此功能碼 02 非法數(shù)據(jù)地址 指定的數(shù)據(jù)地址在從站設備中不存在 03 非法數(shù)據(jù)值 指定的數(shù)據(jù)超過范圍或者不允許使用 04 從站設備故障 從站設備處理響應的過程中,出現(xiàn)未知錯誤等