Modbus RTU 協議介紹
異步串行傳輸方式,采用二進制格式,適用于串行通訊(如RS-485),效率高,是工業現場的主流選擇。
主站是Master,從站是Slave。
Modbus RTU 協議格式
幀結構
- 地址碼(1字節):從設備的地址,取值1-247。
- 功能碼(1字節):指定操作類型,如讀取或寫入。
- 數據區(長度可變):包含具體的操作數據。
- CRC校驗(2字節):循環冗余校驗碼,確保數據無誤。
功能碼
功能碼 | 功能 | 用途 |
---|---|---|
01 | 讀線圈狀態 | 獲取開關量輸出狀態 |
03 | 讀保持寄存器 | 獲取16位可讀寫數據 |
04 | 讀輸入寄存器 | 獲取16位只讀數據 |
05 | 寫單個線圈 | 控制單個開關量輸出 |
06 | 寫單個寄存器 | 修改單個16位數據 |
16(0x10 十六進制) | 寫多個寄存器 | 修改多個16位數據 |
CRC 校驗
CRC(循環冗余校驗)是Modbus RTU的關鍵,用于檢測傳輸錯誤。發送方計算CRC并附加在幀尾,接收方重新計算并比對。
CRC16校驗算法示例:
const unsigned short wCRCTalbeAbs[] =
{0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400,
};unsigned short mt_api_crc16(unsigned char *ptr, unsigned int len)
{unsigned short wCRC = 0xFFFF;unsigned short i;unsigned char chChar;unsigned char temp[2];for (i = 0; i < len; i++){chChar = *ptr++;wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4);wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4);}temp[0] = wCRC&0xFF; temp[1] = (wCRC>>8)&0xFF;wCRC = (temp[0]<<8)|temp[1];return wCRC;
}
0x01 功能碼(讀線圈狀態)
請求數據
01 01 00 00 00 08 9C 03
- 01:從設備地址(1-247)
- 01:功能碼(讀線圈狀態)
- 00 00:起始線圈地址(2 字節)
- 00 08:線圈個數(讀取 8 個線圈)
- 9C 03:CRC校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 起始線圈地址(高位) + 起始線圈地址(低位) + 線圈數量(高位) + 線圈數量(低位) + CRC(高位) + CRC(低位),一共 8 個字節。
響應數據
01 01 01 55 78 3A
- 01:從設備地址(1-247)
- 01:功能碼(讀線圈狀態)
- 01:線圈狀態數據的總字節數(
<font style="color:rgb(0, 0, 0);">ceil(線圈數量/8)</font>
,8 個線圈 = 1 字節) - 55:線圈狀態數據(1 個字節)
- 78 3A:CRC 校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 數據長度 + [線圈狀態數據(N 字節)] + CRC(高位) + CRC(低位)
0x03 功能碼(讀保持寄存器)
請求數據
01 03 00 00 00 01 C4 0B
- 01:從設備地址(1-247)
- 03:功能碼(讀保持寄存器)
- 00 00:起始寄存器地址(2 字節)
- 00 01:寄存器個數(讀取 1 個寄存器)
- C4 0B:CRC校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 起始寄存器地址(高位) + 起始寄存器地址(低位) + 寄存器數量(高位) + 寄存器數量(低位) + CRC(高位) + CRC(低位),一共 8 個字節。
響應數據
01 03 02 19 98 B2 7E
- 01:從設備地址(1-247)
- 03:功能碼(讀保持寄存器)
- 02:后面數據的字節數,一個寄存器有 2 個字節,所以后面的字節數等于 2*查詢的寄存器數量
- 19 98:寄存器的值是 19 98
- B2 7E:CRC 校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 數據長度 + 寄存器數據 + CRC 校驗碼
字節數:1+1+1+2*N+2
0x04 功能碼(讀輸入寄存器)
請求數據
01 04 00 01 00 03 60 0A
- 01:從設備地址(1-247)
- 04:功能碼(寫輸入寄存器)
- 00 01:起始寄存器地址(2 字節)
- 00 03:輸入寄存器數量
- 60 0A:CRC 校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 起始寄存器地址(高位) + 起始寄存器地址(低位) +寄存器數量(高位) + 寄存器數量(低位) + CRC 校驗(高位) + CRC 校驗(高位),一共 8 個字節。
響應數據
01 04 06 00 0A 01 F4 03 E8 75 3B
- 01:從設備地址(1-247)
- 04:功能碼(寫輸入寄存器)
- 06:輸入寄存器數據的總字節數(寄存器數量 ×2,3×2=6 字節)
- 00 0A:第一個輸入寄存器值
- 01 F4:第二個輸入寄存器值
- 03 E8:第三個輸入寄存器值
- 75 3B:CRC 校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 數據長度 + [N 組寄存器數據(每組 2 字節)] + CRC 校驗(高位) + CRC 校驗(高位)
0x05 功能碼(寫單個線圈)
請求數據
01 05 00 03 FF 00 8C 3A
- 01:從設備地址(1-247)
- 05:功能碼(寫單個線圈)
- 00 03:目標線圈地址
- FF 00:線圈狀態值
- 8C 3A:CRC 校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 目標線圈地址(高位) + 目標線圈地址(低位) + 線圈狀態值(高位) + 線圈狀態值(低位) + CRC 校驗(高位) + CRC 校驗(高位),一共 8 個字節。
響應數據
01 05 00 03 FF 00 8C 3A
- 01:從設備地址(1-247)
- 05:功能碼(寫單個線圈)
- 00 03:目標線圈地址
- FF 00:線圈狀態值
- 8C 3A:CRC 校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 目標線圈地址(高位) + 目標線圈地址(低位) + 線圈狀態值(高位) + 線圈狀態值(低位) + CRC 校驗(高位) + CRC 校驗(高位),一共 8 個字節。
0x06 功能碼( 寫單個保持寄存器)
請求數據
01 06 00 00 00 01 48 0A
- 01:從設備地址(1-247)
- 06:功能碼(寫保持寄存器)
- 00 00:起始寄存器地址(2 字節)
- 00 01:寫入的值
- 48 0A:CRC校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 起始寄存器地址(高位) + 起始寄存器地址(低位) + 寫入值(高位) + 寫入值(低位) + CRC(高位) + CRC(低位),一共 8 個字節。
響應數據
01 06 00 00 00 01 48 0A
- 01:從設備地址(1-247)
- 06:功能碼(寫保持寄存器)
- 00 00:起始寄存器地址(2 字節)
- 00 01:寫入的值
- 48 0A:CRC校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 起始寄存器地址(高位) + 起始寄存器地址(低位) + 寫入值(高位) + 寫入值(低位) + CRC(高位) + CRC(低位),一共 8 個字節。
0x010 功能碼( 寫多個保持寄存器)
請求數據
01 10 00 02 00 03 06 00 0A 01 02 03 04 75 F5
- 01:從設備地址(1-247)
- 10:功能碼(寫保持寄存器)
- 00 02:起始寄存器地址(2 字節)
- 00 03:寄存器數量
- 06:后續數據的總字節數(寄存器數量 x 2)
- 00 0A:寫入數據 1(2 字節)
- 01 02:寫入數據 3(2 字節)
- 03 04:寫入數據 3(2 字節)
- 75 F5:CRC 校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 起始寄存器地址(高位)+ 起始寄存器地址(低位) + 寄存器數量(高位) + 寄存器數量(低位) + 數據總字節數 + [N 組寫入值(每組 2 字節)] + CRC 高位 + CRC 低位
響應數據
01 10 00 02 00 03 A7 3C
- 01:從設備地址(1-247)
- 10:功能碼(寫保持寄存器)
- 00 02:起始寄存器地址(2 字節)
- 00 03:寄存器數量
- A7 3C:CRC 校驗
更詳細的格式如下:
從設備地址 + 功能碼 + 起始寄存器地址(高位)+ 起始寄存器地址(低位) + 寄存器數量(高位) + 寄存器數量(低位) + CRC 高位 + CRC 低位。