Modbus 通訊協定是什麼?RTU 與 TCP 架構、封包結構與工業應用完全解析

一、概述與標準背景 (Overview & Standard Background)
1.1 Modbus 通訊協定的定義與誕生歷史
Modbus 是製造業與自動化領域歷史最悠久、應用最普及的開放式工業通訊協定(Industrial Communication Protocol)。它最早於 1979 年由 Modicon 公司(現隸屬於施耐德電機 Schneider Electric)為其可程式邏輯控制器(PLC)產品所開發。
由於 Modbus 的規格完全免費公開(Open Standard)、沒有專利保護限制,且訊息格式極為簡潔易懂,在過去四十幾年間迅速發展成為全球工業自動化領域的「事實標準(De Facto Standard)」。無論是 PLC、SCADA 系統、人機介面(HMI)、智慧多功能電表、溫度控制器還是各式工業感測器,絕大多數皆內建 Modbus 介面。
目前 Modbus 協定的管理與維護由非營利組織 Modbus Organization (Modbus.org) 主導,持續確保該標準的相容性與現代化演進(如 Modbus Security 安全標準)。
1.2 OSI 七層模型中的定位
在開放系統互連參考模型(OSI 7-Layer Model)中,Modbus 本質上屬於第 7 層——應用層(Application Layer)協定。
+-------------------------------------------------------------+| Layer 7: 應用層 (Application) --> Modbus Application PDU |+-------------------------------------------------------------+| Layer 4: 傳輸層 (Transport) --> TCP (Modbus-TCP) / RS-485|+-------------------------------------------------------------+| Layer 1: 實體層 (Physical) --> EIA/TIA-485, Ethernet |+-------------------------------------------------------------+
因為 Modbus 只專注於定義「請求與回應的訊息語法與語意(PDU, Protocol Data Unit)」,這意味著它可以無縫疊加於不同的底層物理網路之上,例如傳統的 RS-485 序列通訊(Modbus RTU / ASCII),或是現代乙太網路(Modbus TCP)。
二、核心運作機制與網路拓撲 (Architecture & Topology)
2.1 主從架構 (Master / Slave) 與 客戶端/伺服器架構 (Client / Server)
Modbus 的核心傳輸邏輯建立在請求-回應(Request-Response)機制之上:
sequenceDiagramautonumberparticipant Master as 主站 (Master / Client)participant Slave as 從站 (Slave / Server)Master->>Slave: 請求封包 (Request PDU: Function Code + Address + Length)Note over Slave: 驗證 Address, Function Code 與 CRCSlave-->>Master: 回應封包 (Response PDU: Data)
- Modbus RTU / ASCII(主從架構 Master / Slave):
- 在一條 RS-485 匯流排上,有且僅能有一個主站(Master),以及最多 247 個從站(Slave, 站號位址 1~247)。
- 從站絕不能主動發送數據。所有資料交換必須由主站發起查詢(Polling)請求,對應站號的從站收到後才可回傳回應。
- Modbus TCP(客戶端/伺服器架構 Client / Server):
- 在乙太網路環境中,發起查詢的設備稱為 Client(如 SCADA 或 Gateway),而被查詢的設備稱為 Server(如 PLC 或智慧電表)。
- 由於 TCP/IP 支援多連線,一個 Modbus TCP Server 可以同時接受多個 Client 的連線請求(例如同時給人機介面與 MES 系統提供數據)。
2.2 物理層電氣規格與拓撲 (RS-485 vs Ethernet)

A. RS-485 序列通訊物理層 (Modbus RTU)
- 電氣特性:採用 差動電壓訊號(Differential Signaling, A/B 線),具備極強的抗電磁干擾能力。
- 傳輸線路與拓撲:必須採用雙絞屏蔽線(STP),網路拓撲必須為手牽手串接(Daisy-Chain),嚴禁分支成星狀拓撲。
- 終端電阻:匯流排的最前端與最後端必須各並聯一顆 120 Ω 終端電阻(Termination Resistor),以防止訊號反射造成封包損毀。
- 常見傳輸參數:波特率(Baud Rate)常見為 9600, 19200, 38400, 115200 bps;資料位元為 8 位,停止位元為 1 位,校驗位(Parity)通常為 None 或 Even。
B. 乙太網路物理層 (Modbus TCP)
- 傳輸介質:標準 RJ45 網線(Cat.5e / Cat.6),走標準 IEEE 802.3 乙太網路與 TCP/IP 協定。
- 預設通訊埠 (Port):Modbus TCP 於全球標準中固定佔用 TCP Port 502。
三、暫存器模型與 Function Code 詳解 (Register Mapping & Function Codes)

3.1 記憶體四分區與暫存器映射 (Memory Mapping)
Modbus 將設備內部的數據抽象化定義為四大獨立的記憶體區域:
| 記憶體分區名稱 | 英文名稱 | 數據類型 | 存取權限 | PLC 傳統位址範圍 | 說明與典型應用 |
|---|---|---|---|---|---|
| 0X 線圈 | Coils | 1-Bit (開關量) | 可讀、可寫 (R/W) | 00001 ~ 09999 | 控制繼電器開關、馬達啟停指令 |
| 1X 離散輸入 | Discrete Inputs | 1-Bit (開關量) | 只讀 (Read-Only) | 10001 ~ 19999 | 讀取按鈕狀態、光電開關警報感測 |
| 3X 輸入暫存器 | Input Registers | 16-Bit (字元量) | 只讀 (Read-Only) | 30001 ~ 39999 | 讀取感測器原始數值(如即時溫度、電壓) |
| 4X 保持暫存器 | Holding Registers | 16-Bit (字元量) | 可讀、可寫 (R/W) | 40001 ~ 49999 | 設定溫度目標值、PID 參數、設備參數配置 |
3.2 常用功能碼 (Function Code) 詳解
Modbus 功能碼用以告知從站執行何種動作,最常用的標準功能碼如下:
FC 01 (0x01) : 讀取線圈狀態 (Read Coils)FC 02 (0x02) : 讀取離散輸入 (Read Discrete Inputs)FC 03 (0x03) : 讀取保持暫存器 (Read Holding Registers) --> 最常用!FC 04 (0x04) : 讀取輸入暫存器 (Read Input Registers)FC 05 (0x05) : 寫入單一線圈 (Write Single Coil)FC 06 (0x06) : 寫入單一暫存器 (Write Single Register)FC 15 (0x0F) : 寫入多個線圈 (Write Multiple Coils)FC 16 (0x10) : 寫入多個暫存器 (Write Multiple Registers)
3.3 異常回應機制 (Exception Responses)
當從站收到請求但無法執行時(例如請求的暫存器位址不存在,或寫入數值超出範圍),從站會回傳一個異常回應封包。
- 異常功能碼:將原功能碼最高位(MSB)置 1,即 ext原功能碼 + 0 imes80。例如
0x03的異常回應功能碼為0x83。 - 常見 Exception Code:
01 (ILLEGAL FUNCTION):不支援該功能碼。02 (ILLEGAL DATA ADDRESS):無效的暫存器位址。03 (ILLEGAL DATA VALUE):寫入數值非法。04 (SLAVE DEVICE FAILURE):從站內部硬體故障。
四、封包結構與 CRC-16 檢錯機制 (Frame Structure & CRC-16)
4.1 Modbus RTU vs Modbus TCP 封包結構剖析
Modbus RTU ADU 結構:+---------------+------------------+---------------------+-------------------+| Slave ID (1B) | Function Code(1B)| Data Payload (N B) | CRC-16 (2 Bytes) |+---------------+------------------+---------------------+-------------------+Modbus TCP ADU 結構:+------------------------------------------------+------------------+---------------------+| MBAP Header (7 Bytes: TxID+ProtoID+Len+UnitID) | Function Code(1B)| Data Payload (N B) |+------------------------------------------------+------------------+---------------------+
十六進位實例解析(主站查詢與從站回應)
範例:主站向 1 號從站讀取保持暫存器 40001 開始的 2 個暫存器數值。
- 主站發送請求 (Master Request - RTU Hex):
01 03 00 00 00 02 C4 0B
01:站號 Address = 103:功能碼 FC03 (Read Holding Registers)00 00:起始暫存器位址0x0000(即 40001)00 02:讀取暫存器數量 = 2 個 (共 4 Bytes)C4 0B:CRC-16 檢錯碼 (Low Byte在前面:0x0BC4)
- 從站正常回應 (Slave Response - RTU Hex):
01 03 04 01 2C 00 64 B9 9F
01:站號 Address = 103:功能碼 FC0304:傳回資料位元組總數 = 4 Bytes01 2C:第一個暫存器數值0x012C(十進位 = 300)00 64:第二個暫存器數值0x0064(十進位 = 100)B9 9F:CRC-16 檢錯碼
4.2 CRC-16 演算法算式與計算邏輯
Modbus RTU 採用 CRC-16-IBM 檢錯演算法(Polynomial 多項式為 0xA001,初始值為 0xFFFF):
// C 語言 Modbus CRC-16 標準計算實作unsigned short calculate_modbus_crc(unsigned char *buf, int len) {unsigned short crc = 0xFFFF;for (int pos = 0; pos < len; pos++) {crc ^= (unsigned short)buf[pos]; // XOR byte into least sig. byte of crcfor (int i = 8; i != 0; i--) { // Loop over each bitif ((crc & 0x0001) != 0) { // If the LSB is setcrc >>= 1; // Shift right and XOR 0xA001crc ^= 0xA001;} else { // Else LSB is not setcrc >>= 1; // Just shift right}}}return crc; // 傳回 CRC 數值 (發送時注意低位元組先發)}
五、Modbus RTU vs Modbus ASCII vs Modbus TCP 技術規格對比
| 比較項目 | Modbus RTU | Modbus ASCII | Modbus TCP |
|---|---|---|---|
| 物理層 | RS-485 / RS-232 序列埠 | RS-485 / RS-232 序列埠 | 乙太網路 (Ethernet IEEE 802.3) |
| 資料編碼 | 8-bit 二進位 (Binary) | 7-bit ASCII 文字碼 | 8-bit 二進位 (Binary) |
| 訊號偵測開頭/結尾 | 靜置 3.5 字元時間 (T1-T2-T3-T4) | 開頭 : (0x3A), 結尾 CRLF | 由 TCP/IP 封包長度欄位決定 |
| 檢錯機制 | CRC-16 (Cyclic Redundancy) | LRC (Longitudinal Redundancy) | TCP 協定內建 CRC Checksum |
| 最大傳輸距離 | 最長 1200 公尺 (RS-485) | 最長 1200 公尺 (RS-485) | 100 公尺 (網線) / 光纖無限擴充 |
| 最大站號/連線數 | 最多 247 個從站 | 最多 247 個從站 | 由 IP 與 Socket 連線數決定 |
| 傳輸效率 | 高(格式精簡) | 低(耗費雙倍 ASCII 字元) | 極高(Gigabit 速度) |
六、工業現場應用與 Python / C 實務代碼範例
6.1 Python 實務讀寫代碼 (pymodbus)
# Python 3 透過 Modbus-TCP 讀取智慧電表參數範例from pymodbus.client import ModbusTcpClient# 建立 TCP 連線至 Modbus 電表 (預設 Port 502)client = ModbusTcpClient('192.168.1.100', port=502)if client.connect():print("成功連線至 Modbus-TCP Server")# 讀取站號 1 的 40001 開始之 2 個 Holding Registers (電壓與電流)result = client.read_holding_registers(address=0, count=2, slave=1)if not result.isError():voltage = result.registers[0] / 10.0 # 假設電表數值放大 10 倍current = result.registers[1] / 100.0 # 假設電流數值放大 100 倍print(f"即時電壓: {voltage} V, 即時電流: {current} A")else:print(f"Modbus 讀取失敗: {result}")client.close()else:print("無法連線至 Modbus-TCP Server,請檢查網路設定與 Port 502。")
七、資安考量、故障排查與診斷工具 (Security & Diagnostics)
7.1 Modbus 的資安缺陷與防護
- 原生資安缺陷:原始 Modbus 協定設計於 1979 年,完全沒有加密(Plaintext)、沒有身份驗證機制(No Authentication)。任何接入廠區網路的設備,皆可發送寫入指令改寫 PLC 暫存器。
- 防護建議:
- 將 OT 通訊網路劃分為獨立 VLAN,並在 Edge 網關設置防火牆封鎖非授權 IP 存取 Port 502。
- 升級至 Modbus Security(TLS 封裝,標準 Port 802)。
7.2 常見故障排查步驟與診斷工具
- 檢查物理層連線:RS-485 A/B 線是否接反?終端電阻是否在首尾兩端正確並聯?
- 校對通訊參數:Baud rate、Parity(偶/奇/無校驗)、Slave ID 是否一致?
- 診斷工具軟體:
- Wireshark:強大的網路封包抓取分析軟體,內建 Modbus-TCP 封包解碼器。
- ModScan32 / Modpoll:經典的 Modbus 主站測試軟體,可用於發送測試指令驗證暫存器。
八、結論與技術總結
Modbus 作為工業自動化領域歷史最悠久、最成功的開放式通訊協定,憑藉其簡潔性、穩定性與跨品牌高相容性,至今仍是現場設備對接的共通語言。深入理解其四大記憶體分區、功能碼運作邏輯、封包結構與 CRC-16 檢錯算式,是所有 OT/IT 工程師與智慧製造專家必備的核心基本功。