modbus --- Modbus RTU 從站協定

此模組提供一個純 Python 實作的 Modbus RTU 從站,透過 UART 通訊。它維護一個內部的保持暫存器陣列,並回應標準的 Modbus 功能碼 0x03(讀取保持暫存器)、0x06(寫入單一暫存器)以及 0x10(寫入多個暫存器)。CRC-16(Modbus 多項式)使用查找表計算。

例如:

from machine import UART
from modbus import ModbusRTU

uart = UART(1, 115200, timeout=10, timeout_char=10)
modbus = ModbusRTU(uart, slave_id=0x01, register_num=30)

while True:
    if modbus.any():
        modbus.handle(debug=False)

class ModbusRTU

一個從 UART 讀取請求、更新其內部暫存器陣列,並將對應回應寫回 UART 的 Modbus RTU 從站。

class modbus.ModbusRTU(uart: machine.UART, slave_id: int = 0x01, register_num: int = 30)

建構一個 ModbusRTU 從站。

  • uart 是用於傳送與接收 Modbus 影格的 UART 實例(例如 machine.UARTpyb.UART)。傳入前,UART 必須先設定好適當的鮑率、同位元與逾時。

  • slave_id 是此實例將回應的 Modbus 從站位址(1-247)。發往其他從站 ID 的影格會被忽略。

  • register_num 是支援此從站的 16 位元保持暫存器數量。暫存器儲存於 REGISTER 清單中並初始化為零。

SLAVE_ID: int

此實例將回應的 Modbus 從站位址。由 slave_id 建構子引數設定。

uart: machine.UART

傳入建構子的 UART 實例,用於所有 I/O。

register_num: int

16 位元保持暫存器的數量,由 register_num 建構子引數設定。

REGISTER: list[int]

長度為 register_num 的清單,保存目前的 16 位元暫存器值。透過傳入的 Modbus 請求所執行的讀取與寫入會更新此清單。應用程式碼可直接讀取或寫入此清單,以與 Modbus 主站交換資料。

CRC16_TABLE: list[int]

預先計算的 256 項查找表,用於 Modbus CRC-16 多項式,由 crc16() 使用。

any() int

傳回底層 UART 接收緩衝區目前可用的位元組數(委派給 uart.any())。在呼叫 handle() 之前可用此來檢查是否有傳入請求。

clear() None

REGISTER 中的每一項重設為 0

crc16(data: bytes | bytearray) bytes

使用 CRC16_TABLE 計算 data 的 Modbus CRC-16,並以可附加至 Modbus 影格的 2 位元組小端序 bytes 物件形式傳回。

  • data 是包含要計算總和檢查碼之位元組的 bytesbytearray(或任何整數的可迭代物件)。

handle(debug: bool = False) None

從 UART 讀取單一 Modbus 請求,依需要更新內部暫存器陣列,並將對應回應寫回 UART。

支援的功能碼:

  • 0x03 讀取保持暫存器 --- 以所請求範圍的暫存器值回應。

  • 0x06 寫入單一暫存器 --- 寫入單一暫存器並回傳該位址與值。

  • 0x10 寫入多個暫存器 --- 寫入一段連續範圍的暫存器,並以起始位址與數量回應。

下列情況會傳回 Modbus 例外回應:

  • 非法功能(0x01) --- 不支援的功能碼。

  • 非法資料位址(0x02) --- 暫存器索引超出範圍。

  • 非法資料值(0x03) --- 位元組數與所宣告的暫存器數量不符。

CRC 不符,或從站位址與 SLAVE_ID 不符的影格會被靜默丟棄。

  • debug 若為 True,會將原始請求、解析出的功能碼、產生的回應以及任何錯誤細節印出至 REPL。預設為 False