Modbus RTU通訊協議在數據通訊上採用主從應答的方式進行。只能由主機(PC,HMI等)通過唯一從機地址發起請求,從機(終端設備)根據主機請求進行響應,即半雙工通訊。該協議只允許主機發起請求,從機進行被動響應,因此從機不會主動占用通訊線路造成數據衝突。
類似Modbus RTU協議的主從應答協議還有西門子的PPI、電錶常用的DL/T645-2007等協議。
一、協議格式
信息傳輸為異步方式,使用16進位進行通訊,信息幀格式:
地址碼 |
功能碼 |
數據區 |
CRC校驗碼 |
1位元組 |
1位元組 |
N字節 |
2位元組 |
地址碼
地址碼是每個通訊信息幀的第一個字節,一般支持1到247,部分設備也支持0地址,用於接收主機的廣播數據,每個從機在總線上地址必須唯一,只有與主機發送的地址碼相符的從機才能響應返回數據。
功能碼
功能碼是每個通訊信息幀的第二個字節。主機發送,通過功能碼告知從機設備應當執行何種操作。
常見的八種功能碼:
功能碼 |
定義 |
操作 |
01H |
讀取線圈 |
讀取一個或多個連續線圈狀態 |
05H |
寫單個線圈 |
操作指定位置的線圈狀態 |
0FH |
寫多個線圈 |
操作多個連續線圈狀態 |
02H |
讀取離散量輸入 |
讀取一個或多個連續離散輸入狀態 |
04H |
讀取輸入寄存器 |
讀取一個或多個連續輸入寄存器數據 |
03H |
讀保持寄存器 |
讀取一個或多個保持寄存器數據 |
06H |
寫單個保持寄存器 |
把兩個十六進位數據寫入對應位置 |
10H |
寫多個保持寄存器 |
把4*N個十六進位數據寫入N個連續保持寄存器 |
數據區
數據區隨功能碼以及數據方向的不同而不同,這些數據可以是「寄存器首地址+讀取寄存器數量」、「寄存器地址+操作數據」、「寄存器首地址+操作寄存數量+數據長度+數據」等不同的組合,在「功能碼分析」詳解不同功能碼的數據區。
Modbus CRC校驗
Modbus RTU協議常用與工業現場對數據傳輸的穩定性和正確性有較高的要求,因此通過CRC校驗保證數據傳輸的正確性和完整性。
二、錯誤反饋
地址與CRC校驗錯誤並不會收到從機的數據反饋,其他錯誤將向主機返回錯誤碼。數據幀的第二位加上0X80表示請求發生錯誤(非法功能碼、非法數據值等),錯誤數據幀如下:
地址碼 |
功能碼 |
錯誤碼 |
CRC校驗碼 |
1位元組 |
1位元組 |
1位元組 |
2位元組 |
常見錯誤碼如下:
值 |
名稱 |
說明 |
01H |
非法的功能碼 |
不支持該功能碼操作寄存器 |
02H |
非法的寄存器地址 |
訪問設備禁止訪問的寄存器 |
03H |
非法的數據值 |
寫入不支持的參數值 |
04H |
從機故障 |
設備工作異常 |
三、通訊信息傳輸過程
通訊命令由主機發送從機時,與主機發送的地址碼相符的從機接收通訊命令,如果CRC校驗無誤,則執行相應的操作,然後把執行結果(數據)返回給主機。返回信息中包含地址碼、功能碼、執行後的數據以及CRC校驗碼。如果地址不匹配或者CRC校驗出錯就不返回任何信息。
四、功能碼分析
功能碼01H:讀線圈
例如:主機要讀取從機地址為01H,起始線圈地址為00H的1個線圈狀態,主機發送:
主機發送 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
01 |
|
起始線圈地址 |
高字節 |
00 |
低字節 |
00 |
|
線圈數量 |
高字節 |
00 |
低字節 |
01 |
|
CRC校驗 |
低字節 |
FD |
高字節 |
CA |
如果從機寄存器00H線圈閉合,從機返回:
從機返回 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
01 |
|
字節數 |
01 |
|
線圈狀態 |
01 |
|
CRC校驗碼 |
低字節 |
90 |
高字節 |
48 |
仿真演示:
功能碼05H:寫單個線圈
例如:主機要控制從機地址為01H,線圈地址為0000H的線圈狀態,主機發送:
主機發送 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
01 |
|
線圈地址 |
高字節 |
00 |
低字節 |
00 |
|
控制方式 |
高字節 |
00(斷開)、FF(閉合) |
低字節 |
01 |
|
CRC校驗 |
低字節 |
XX |
高字節 |
XX |
從機返回與主機請求相同;
仿真演示:
功能碼0FH:寫多個線圈
例如:主機要控制從機地址為01H,起始線圈地址為00H的4個線圈狀態,主機發送:
主機發送 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
0F |
|
起始線圈地址 |
高字節 |
00 |
低字節 |
00 |
|
線圈數量 |
高字節 |
00 |
低字節 |
04 |
|
寫入字節數 |
01 |
|
控制方式 |
00(全部斷開)、0F(全部閉合) |
|
CRC校驗 |
低字節 |
XX |
高字節 |
XX |
功能碼0FH操作,從機返回:
從機返回 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
0F |
|
起始線圈地址 |
高字節 |
00 |
低字節 |
00 |
|
線圈數量 |
高字節 |
00 |
低字節 |
04 |
|
CRC校驗 |
低字節 |
54 |
高字節 |
08 |
仿真演示:
功能碼02H:讀離散輸入
例如:主機要讀取從機地址為01H,起始離散量地址為00H的4個輸入狀態,主機發送:
主機發送 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
02 |
|
起始離散量地址 |
高字節 |
00 |
低字節 |
00 |
|
讀取數量 |
高字節 |
00 |
低字節 |
04 |
|
CRC校驗 |
低字節 |
79 |
高字節 |
C9 |
如果從機首地址00H開始的4離散輸入全部檢測到輸入,從機返回:
從機返回 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
02 |
|
字節數 |
01 |
|
離散輸入狀態 |
0F |
|
CRC校驗碼 |
低字節 |
E1 |
高字節 |
8C |
仿真演示:
功能碼04H:讀取輸入寄存器
例如:主機要讀取從機地址為01H,起始寄存器地址為02H的1個輸入寄存器數據,主機發送:
主機發送 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
04 |
|
起始寄存器地址 |
高字節 |
00 |
低字節 |
02 |
|
寄存器數量 |
高字節 |
00 |
低字節 |
01 |
|
CRC校驗 |
低字節 |
90 |
高字節 |
0A |
如果從機輸入寄存器02H的數據為3344H,從機返回:
從機返回 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
04 |
|
字節數 |
02 |
|
寄存器05H數據 |
高字節 |
33 |
低字節 |
44 |
|
CRC校驗碼 |
低字節 |
AD |
高字節 |
F3 |
仿真演示:
功能碼03H:讀保持寄存器
例如:主機要讀取從機地址為01H,起始寄存器地址為05H的2個保持寄存器數據,主機發送:
主機發送 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
03 |
|
起始寄存器地址 |
高字節 |
00 |
低字節 |
05 |
|
寄存器數量 |
高字節 |
00 |
低字節 |
02 |
|
CRC校驗 |
低字節 |
D4 |
高字節 |
0A |
如果從機保持寄存器05H、06H的數據為1122H、3344H,從機返回:
從機返回 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
03 |
|
字節數 |
04 |
|
寄存器05H數據 |
高字節 |
11 |
低字節 |
22 |
|
寄存器06H數據 |
高字節 |
33 |
低字節 |
44 |
|
CRC校驗碼 |
低字節 |
4B |
高字節 |
C6 |
仿真演示:
功能碼06H:寫單個保持寄存器
例如:主機寫入9988H的數據給從機地址為01H,寄存器地址為0050H的寄存器,主機發送:
主機發送 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
06 |
|
寄存器地址 |
高字節 |
00 |
低字節 |
50 |
|
寫入值 |
高字節 |
99 |
低字節 |
88 |
|
CRC校驗 |
低字節 |
E3 |
高字節 |
ED |
從機返回與主機請求相同;
功能碼10H:寫多個保持寄存器
例如:主機要把數據0005H、2233H保存到從機地址為01H,起始寄存器地址為0020H的2個寄存器中,主機發送:
主機發送 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
10 |
|
起始寄存器地址 |
高字節 |
00 |
低字節 |
20 |
|
寄存器數量 |
高字節 |
00 |
低字節 |
02 |
|
寫入字節數 |
04 |
|
0000H 寄存器待寫入 |
高字節 |
00 |
低字節 |
05 |
|
0001H 寄存器待寫入 |
高字節 |
22 |
低字節 |
33 |
|
CRC校驗 |
低字節 |
B9 |
高字節 |
03 |
功能碼10H操作,從機返回:
從機返回 |
發送數據(HEX) |
|
地址碼 |
01 |
|
功能碼 |
10 |
|
起始寄存器地址 |
高字節 |
00 |
低字節 |
20 |
|
寄存器數量 |
高字節 |
00 |
低字節 |
02 |
|
CRC校驗 |
低字節 |
40 |
高字節 |
02 |
仿真演示: