跳到主要内容

示例程序

本章说明如何下载、配置并运行 C、Python、STM32 和 Arduino 示例,通过 Modbus RTU 使用 Modbus RTU Module (A) 的继电器输出、数字量输入、模拟量输入和模拟电流输出。

示例范围

本产品为成品功能模块,不属于二次开发模块,不提供模块内部固件源码及工程文件。

本页提供的 C、Python、STM32 和 Arduino 程序仅用于演示外部主控如何通过 Modbus RTU 操作模块,并非模块源码。

主控板适配、硬件故障排查以及用户自行修改的 GPIO、UART 初始化代码不属于示例程序支持范围。

下载示例程序

Ubuntu 用户安装下载和解压工具,然后下载示例压缩包。发布前请将 DOWNLOAD_URL 替换为实际下载链接。

sudo apt install -y wget unzip
wget https://files.waveshare.com/wiki/Modbus-RTU-Module-A/Modbus_RTU_Module_A_Demo.zip
unzip Modbus_RTU_Module_A_Demo.zip
cd Modbus_RTU_Module_A_Demo

解压后的目录结构如下:

Modbus_RTU_Module_A_Demo/
├── c/
├── python/
├── STM32/
└── Arduino/

Windows 用户可以使用浏览器下载示例程序并解压,后续进入对应平台目录即可。

开发协议请参考 Modbus RTU Module (A) 开发协议

功能概览

设备具有 2 路继电器输出、2 路数字量输入、2 路模拟电流输出和 2 路模拟量输入,各功能组的通道编号均为 12。示例库提供以下功能:

功能C、STM32PythonArduinoModbus 指令
读取或控制单路继电器read_relaywrite_relayread_relay()write_relay()readRelay()writeRelay()0x01,写 0x05
读取或控制两路继电器read_relayswrite_all_relayswrite_relaysread_relays()write_all_relays()write_relays()readRelays()writeAllRelays()writeRelays()0x01,写 0x050x0F
继电器闪开或闪闭pulse_relaypulse_relay()pulseRelay()0x05
读取单路或两路数字量输入read_digital_inputread_digital_inputsread_digital_input()read_digital_inputs()readDigitalInput()readDigitalInputs()0x02
读写单路继电器控制模式read_control_modewrite_control_moderead_control_mode()write_control_mode()readControlMode()writeControlMode()0x03,写 0x06
读写两路继电器控制模式read_control_modeswrite_control_modesread_control_modes()write_control_modes()readControlModes()writeControlModes()0x03,写 0x10
读写单路模拟电流输出read_analog_outputwrite_analog_outputread_analog_output()write_analog_output()readAnalogOutput()writeAnalogOutput()0x03,写 0x06
读写两路模拟电流输出read_analog_outputswrite_analog_outputsread_analog_outputs()write_analog_outputs()readAnalogOutputs()writeAnalogOutputs()0x03,写 0x10
读取单路或两路模拟量输入read_analog_inputread_analog_inputsread_analog_input()read_analog_inputs()readAnalogInput()readAnalogInputs()0x04
读写单路模拟输入类型read_analog_input_typewrite_analog_input_typeread_analog_input_type()write_analog_input_type()readAnalogInputType()writeAnalogInputType()0x03,写 0x06
读写两路模拟输入类型read_analog_input_typeswrite_analog_input_typesread_analog_input_types()write_analog_input_types()readAnalogInputTypes()writeAnalogInputTypes()0x03,写 0x10
读取或设置串口参数read_serial_paramwrite_serial_paramread_serial_parameters()write_serial_parameters()readSerialParameters()writeSerialParameters()0x03,写 0x06
读取或设置设备地址read_addresswrite_addressread_device_address()write_device_address()readDeviceAddress()writeDeviceAddress()0x03,写 0x06
读取软件版本read_versionread_software_version()readSoftwareVersion()0x03

完整示例只查询串口参数和设备地址,不修改通信配置。其它设备函数均会运行一次;涉及保持寄存器或线圈写入时,程序会先查询原状态,写入演示值,再次查询实际状态。

Python 示例

测试环境:Ubuntu 22.04,USB‑TO‑RS485(B)转换器

Python 示例位于 python/ 目录,使用 pymodbus 完成 Modbus RTU 通信。建议在虚拟环境中安装依赖:

sudo apt install -y python3 python3-venv python3-pip
cd python
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
初始化提示

打开 main_module_a.py,根据实际连接修改串口、波特率、超时和设备地址。示例默认串口为 /dev/ttyUSB0

SERIAL_PORT = "/dev/ttyUSB0"
SERIAL_BAUDRATE = 9600
SERIAL_TIMEOUT_SECONDS = 0.3
DEVICE_ID = 1
PRINT_FRAMES = True

示例中的主要操作如下:

# 串口总线和 Module A 设备分别初始化,同一条总线可连接多个设备。
client = ModbusSerialClient(
port=SERIAL_PORT,
baudrate=SERIAL_BAUDRATE,
bytesize=8,
parity="N",
stopbits=1,
timeout=SERIAL_TIMEOUT_SECONDS,
)
bus = ModbusRtuBus(client)
bus.connect()
device = ModbusRtuModuleA(device_id=1)

# 查询 DO1,设置为关闭,再查询实际状态。
before = device.read_relay(bus, 1)
device.write_relay(bus, 1, RELAY_OFF)
after = device.read_relay(bus, 1)

# 读取两路数字量输入和两路模拟量输入。
digital_inputs = device.read_digital_inputs(bus)
analog_inputs = device.read_analog_inputs(bus)

完整示例依次演示功能概览中的全部查询和控制函数。每一步都会打印操作名称、TX、RX 和执行结果;读取结果保存在 ModbusRtuModuleA 对象中。所有步骤仅执行一次,完成后关闭串口并退出程序。

运行完整示例:

python main_module_a.py

实例如下所示:

 Modbus RTU PWM Output 4CH Python 示例

C 示例

测试环境:Ubuntu 22.04,USB‑TO‑RS485(B)转换器

C 示例位于 c/ 目录:

  • module_a.h:数据结构、错误码和对外接口声明。
  • module_a.c:串口通信、Modbus RTU 帧组装、CRC 校验、响应检查和设备操作实现。
  • main_module_a.c:完整调用示例,并打印每次通信的 TX、RX 数据帧。
  • Makefile:编译、运行和清理命令。
初始化提示

运行前请在 main_module_a.c 中修改 MODULE_A_DEMO_PORT。Linux 可填写 /dev/ttyUSB0/dev/ttyACM0,Windows 可填写 COM6 等实际端口名称。示例不接收命令行参数,修改后需要重新执行 make

#define MODULE_A_DEMO_PORT "/dev/ttyUSB0"
#define MODULE_A_DEMO_BAUDRATE 9600u
#define MODULE_A_DEMO_TIMEOUT_MS 300u
#define MODULE_A_DEMO_ADDRESS 1u

示例中的主要操作如下:

ModbusRtuBus bus;
ModbusRtuModuleA device;

module_a_bus_open(&bus, MODULE_A_DEMO_PORT, MODULE_A_DEMO_BAUDRATE);
module_a_init(&device, MODULE_A_DEMO_ADDRESS);

/* 查询 DO1,设置为关闭,再查询实际状态。 */
device.read_relay(&device, &bus, 1u);
device.write_relay(&device, &bus, 1u, MODULE_A_RELAY_OFF);
device.read_relay(&device, &bus, 1u);

module_a_bus_close(&bus);

完整示例依次演示功能概览中的全部查询和控制函数。每一步都会打印操作名称、TX、RX 和执行结果;读取结果保存在 ModbusRtuModuleA 结构体中。所有步骤仅执行一次,完成后关闭串口并退出程序。

Linux 编译和运行:

sudo apt install -y build-essential
cd c
make
./module_a_demo

Windows 使用 MSYS2/MinGW 时执行:

cd c
mingw32-make
.\module_a_demo.exe

实例如下所示:

 Modbus RTU PWM Output 4CH C 示例

STM32 示例

示例使用的硬件:NUCLEO-F103RB 和 RS485 CAN Shield。

注意事项

板子的 GPIO 引脚请勿直接连接 RS485 接口。直连有烧坏板子 GPIO 的风险,须经过 RS485 电平转换模块接入总线。

STM32 示例工程的 RS485 和调试串口引脚如下:

通道STM32 引脚连接或用途
RS485 发送PA9 / USART1_TX连接 RS485 收发器 DI
RS485 接收PA10 / USART1_RX连接 RS485 收发器 RO
RS485 方向使能PA8 / GPIO Output高电平发送,低电平接收
调试串口发送PA2 / USART2_TX连接串口工具 RX,输出 TX、RX 报文和运行结果
调试串口接收PA3 / USART2_RX示例已初始化,当前演示命令

设备函数调用示例:

ModbusRtuBus bus;
ModbusRtuModuleA device;

ModbusRtuBusInit(&bus, &huart1, RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_SET, 300u);
ModuleA_Init(&device, 1u);

/* 查询 AO1,设置为 1000 μA,再查询实际值。 */
device.read_analog_output(&device, &bus, 1u);
device.write_analog_output(&device, &bus, 1u, 1000u);
device.read_analog_output(&device, &bus, 1u);

开发板复位后,完整示例会依次演示功能概览中的全部查询和控制函数。每一步都会通过 USART2 打印操作名称、TX、RX 和执行结果;读取结果保存在 ModbusRtuModuleA 结构体中。所有步骤仅执行一次,完成后主程序进入空闲循环,不再向模块发送控制指令。

使用 Keil MDK 编译和烧录:

  1. 双击打开 STM32/MDK-ARM/Modbus RTU Module A.uvprojx
  2. 在 Keil 中选择目标 Modbus RTU Module A,按 Rebuild 重新编译工程。
  3. 连接下载器并按下 Download 烧录程序。
     Modbus_RTU_Module_A STM32 示例下载
  4. 使用串口调试工具打开 USART2 调试串口,参数为 115200, 8N1
  5. 复位开发板,查看设备操作、TX、RX 和运行结果。

实例如下所示:

 Modbus RTU PWM Output 4CH Stm32 示例

Arduino 示例

示例使用的硬件:UNO PLUS 和 RS485 CAN Shield。

注意事项

板子的 GPIO 引脚请勿直接连接 RS485 接口。直连有烧坏板子 GPIO 的风险,须经过 RS485 电平转换模块接入总线。

示例使用的串口和引脚如下:

功能主控引脚
RS485 RXD2
RS485 TXD8
RS485 DE 和 /RED7
串口监视器115200

设备函数调用示例:

SoftwareSerial rs485(2, 8); // RX, TX
ModbusRtuBus bus(rs485, 7); // 串口和 RS485 方向控制
ModbusRtuModuleA device(1); // Module A 设备地址

/* 查询 DO1,设置为关闭,再查询实际状态。 */
device.readRelay(bus, 1u);
device.writeRelay(bus, 1u, MODULE_A_RELAY_OFF);
device.readRelay(bus, 1u);

开发板启动后,完整示例会依次演示功能概览中的全部查询和控制函数。每一步都会通过 Arduino IDE 串口监视器打印操作名称、TX、RX 和执行结果;读取结果保存在 ModbusRtuModuleA 对象中。所有步骤仅执行一次,loop() 保持为空,不会重复控制设备。

使用 Arduino IDE 编译和上传:

  1. 打开 Arduino/Modbus_RTU_Module_A/Modbus_RTU_Module_A.ino
  2. 在 Arduino IDE 中选择 Arduino Uno 或实际使用的兼容开发板,并选择对应串口。
  3. 单击“验证”,编译示例程序。
  4. 单击“上传”,将程序上传到开发板。
     Modbus_RTU_Module_A Arduino 示例下载
  5. 上传完成后打开“串口监视器”,将波特率设置为 115200
  6. 复位开发板,查看设备操作、TX、RX 和运行结果。

实例如下所示:

 Modbus RTU PWM Output 4CH Python 示例

注意事项

注意事项
  • 模块默认通信参数为 9600, N, 8, 1,默认设备地址为 1
  • 完整示例只查询串口参数和设备地址,不会修改模块通信配置。
  • 通信失败时,依次检查供电、RS485 A/B 接线、串口权限、设备地址和波特率。