SimpleModbus Arduino库使用教程:让Arduino通过Modbus RTU通信

本文目录
  1. 1. SimpleModbus 简介
  2. 2. SimpleModbus 支持的功能
  3. 3. 硬件连接
  4. 4. SimpleModbusSlave 示例:Arduino 作为 Modbus RTU 从站
  5. 5. SimpleModbusMaster 示例:读取从站数据
  6. 6. SimpleModbus vs 现代替代方案
  7. 7. ESP32 上实现 Modbus RTU 通信(现代方案)
  8. 8. Arduino 官方 ArduinoModbus 库
  9. 9. 常见问题排查
  10. 10. 通信完全没有响应
  11. 11. 偶尔丢数据或 CRC 错误
  12. 12. 总结

SimpleModbus 简介

SimpleModbus 是一套为 Arduino 平台开发的 Modbus RTU 协议库,托管在 Google Code Archive(项目已被归档)。它由 Juan Bester 开发,包含 SimpleModbusMaster(主站库)和 SimpleModbusSlave(从站库)两个独立的 Arduino 库。虽然项目名称里有”Simple”,但它提供的功能覆盖了 Modbus RTU 通信中最常用的功能码,非常适合 Arduino 初学者和快速原型开发。

⚠️ 注意:SimpleModbus 项目已不再活跃更新。对于新项目,推荐使用更现代化的 Modbus RTU for Arduino 库(库名为 “Modbus”)或 esp-modbus(ESP32 平台)。但 SimpleModbus 的代码简洁易懂,作为学习 Modbus 协议实现的入门资料仍然很有价值。

SimpleModbus 支持的功能

  • SimpleModbusMaster:支持 FC01(读线圈)、FC02(读离散输入)、FC03(读保持寄存器)、FC04(读输入寄存器)、FC15(写多线圈)、FC16(写多寄存器)
  • SimpleModbusSlave:支持 FC03(读保持寄存器)和 FC16(写多寄存器)
  • 硬件要求:Arduino + RS-485 转换模块(如 MAX485)

硬件连接

Arduino 通过 MAX485 模块连接 RS-485 总线。典型接线方式:

MAX485 引脚Arduino Uno说明
VCC5V电源
GNDGND
RORX (D0)接收数据 → Arduino 串口 RX
DITX (D1)发送数据 ← Arduino 串口 TX
RED2接收使能(低有效)
DED2发送使能(高有效),与 RE 并联到同一 IO
AA (总线+)RS-485 A 线(差分+)
BB (总线-)RS-485 B 线(差分-)

⚠️ 在 RS-485 总线的两端必须加 120Ω 终端电阻(A-B 之间),否则长距离通信会出现信号反射导致数据错误。

SimpleModbusSlave 示例:Arduino 作为 Modbus RTU 从站

#include <SimpleModbusSlave.h>

// 定义保持寄存器数组(10个寄存器)
enum {
    TEMP_REG = 0,      // 温度(x10)
    HUMIDITY_REG,       // 湿度(x10)
    COIL_STATUS,        // 线圈状态
    SETPOINT,           // 设定值
    // ... 更多寄存器
    TOTAL_REGS = 10
};

unsigned int holdingRegs[TOTAL_REGS];

void setup() {
    // 设置 RS-485 方向控制引脚
    pinMode(2, OUTPUT);
    
    // SimpleModbusSlave 参数:
    // 1. 寄存器数组地址
    // 2. 寄存器数量
    // 3. 发送使能引脚
    // 4. 发送使能有效电平
    // 5. 从站地址
    // 6. 波特率
    // 7. 校验(0=无校验)
    modbus_configure(holdingRegs, TOTAL_REGS,
                     2,                  // TXEN 引脚
                     HIGH,               // TXEN 高电平时发送
                     1,                  // 从站地址
                     9600,               // 波特率
                     0);                 // 校验
}

void loop() {
    // 更新传感器数据(模拟)
    holdingRegs[TEMP_REG] = analogRead(A0) / 2; // 温度(模拟)
    holdingRegs[HUMIDITY_REG] = analogRead(A1) / 3;
    holdingRegs[COIL_STATUS] = digitalRead(3);
    
    // 处理 Modbus 请求
    modbus_update();
}

SimpleModbusMaster 示例:读取从站数据

#include <SimpleModbusMaster.h>

#define TOTAL_NO_OF_REGISTERS 2
unsigned int holdingRegs[TOTAL_NO_OF_REGISTERS];

void setup() {
    Serial.begin(9600);
    
    // SimpleModbusMaster 参数:
    // 1. 本地寄存器数组
    // 2. 读取/写入的寄存器数量
    // 3. 发送使能引脚
    // 4. 发送使能有效电平
    modbus_configure(holdingRegs, TOTAL_NO_OF_REGISTERS,
                     2,      // TXEN 引脚
                     HIGH);  // TXEN 高电平时发送
}

void loop() {
    // 从站地址 1,起始地址 0,读取 2 个保持寄存器
    unsigned char result = modbus_read_holding_registers(1, 0, 2);
    
    if (result == 0) {
        Serial.print("温度: ");
        Serial.print(holdingRegs[0] / 10.0);
        Serial.print("°C, 湿度: ");
        Serial.print(holdingRegs[1] / 10.0);
        Serial.println("%");
    } else {
        Serial.print("Modbus 读取失败,错误码: ");
        Serial.println(result);
    }
    
    delay(1000);
}

SimpleModbus vs 现代替代方案

SimpleModbus 项目已经在数年前停止更新,现代 Arduino 项目推荐以下替代方案:

库名平台特点
ArduinoModbusArduino(官方)Arduino 官方维护,支持 RTU 和 TCP,Arduino IDE 库管理器一键安装
Modbus-Master-Slave-for-ArduinoArduino同时支持主站和从站,功能码覆盖全,GitHub 活跃更新
esp-modbusESP32 / ESP8266Espressif 官方库,支持 Modbus RTU/TCP/ASCII,性能优异
SimpleModbusArduino简单易懂,适合学习,但已停更

ESP32 上实现 Modbus RTU 通信(现代方案)

如果你使用 ESP32 平台,推荐 Espressif 官方的 esp-modbus 库。以下是一个最小示例:

// ESP32 使用 HardwareSerial + MAX485
#include <Arduino.h>

// 定义 RS-485 控制引脚
#define RXD2 16  // ESP32 RX2
#define TXD2 17  // ESP32 TX2
#define DE_RE 4  // RS-485 方向控制

HardwareSerial modbusSerial(2);

void setup() {
    Serial.begin(115200);
    modbusSerial.begin(9600, SERIAL_8N1, RXD2, TXD2);
    pinMode(DE_RE, OUTPUT);
    digitalWrite(DE_RE, LOW); // 默认接收模式
}

void loop() {
    // 发送 Modbus RTU 请求(手动构造帧)
    uint8_t request[] = {
        0x01,        // 从站地址
        0x03,        // 功能码(读保持寄存器)
        0x00, 0x00,  // 起始地址
        0x00, 0x02   // 读取 2 个寄存器
    };
    uint16_t crc = calculateCRC(request, 6);
    request[6] = crc & 0xFF;
    request[7] = crc >> 8;
    
    // 切换到发送模式
    digitalWrite(DE_RE, HIGH);
    delayMicroseconds(100);
    modbusSerial.write(request, 8);
    modbusSerial.flush();
    
    // 切换回接收模式
    digitalWrite(DE_RE, LOW);
    
    // 等待响应
    delay(500);
    while (modbusSerial.available()) {
        Serial.printf("%02X ", modbusSerial.read());
    }
    Serial.println();
    delay(2000);
}

Arduino 官方 ArduinoModbus 库

在 Arduino IDE 中打开库管理器(Sketch → Include Library → Manage Libraries),搜索 “ArduinoModbus”,安装即可。ArduinoModbus 支持 Modbus RTU(RS-485)和 Modbus TCP(WiFi/以太网),主站和从站模式均可。

#include <ArduinoRS485.h>
#include <ArduinoModbus.h>

void setup() {
    Serial.begin(9600);
    
    // 初始化 RS-485
    RS485.begin(9600);
    
    // 启动 Modbus RTU 从站(地址 1)
    ModbusRTUServer.begin(1, 9600);
    
    // 配置保持寄存器
    ModbusRTUServer.configureHoldingRegisters(0, 10);
}

void loop() {
    // 轮询 Modbus 请求
    ModbusRTUServer.poll();
    
    // 更新寄存器值
    int sensorValue = analogRead(A0);
    ModbusRTUServer.holdingRegisterWrite(0, sensorValue);
}

常见问题排查

通信完全没有响应

  • 检查 MAX485 DE/RE 引脚的方向切换逻辑是否正确(发送时 HIGH、接收时 LOW)
  • 确认波特率和从站地址与主站配置一致
  • 用 USB 转 RS-485 模块 + 串口助手监控总线数据,确认信号是否存在
  • 检查 A/B 线是否接反(用万用表测差分电压:A 对 B 应为正电压时总线空闲)

偶尔丢数据或 CRC 错误

  • 检查 RS-485 总线两端是否加了 120Ω 终端电阻
  • 降低波特率尝试(4800 或 2400),排除信号完整性因素
  • 缩短总线长度或加中继器
  • 确认发送完成到接收切换之间留有足够的延时(至少 1 个字符时间)

总结

SimpleModbus 作为早期 Arduino Modbus RTU 库,其代码简洁、功能明确,适合初学者理解 Modbus 协议的实现原理。但在实际项目中,推荐使用维护更活跃、功能更完善的替代方案:Arduino 官方库 ArduinoModbus(通用 Arduino 平台)或 esp-modbus(ESP32/ESP8266 平台)。无论选择哪个库,核心的 Modbus RTU 通信原理——从站地址、功能码、寄存器映射、CRC 校验——都是一致的。

技术术语(共 10 个)—— 点击展开
Modbus RTU基于串行链路的Modbus协议,使用二进制编码和CRC校验
Modbus TCP基于以太网的Modbus协议变体,使用TCP/IP传输
RS485工业常用的差分串行通信标准,支持多点通信
功能码Modbus功能码指定读/写操作类型,如01读线圈、03读保持寄存器
寄存器Modbus 寄存器存储数据单元,分线圈/离散输入/保持/输入寄存器四类
波特率串行通信每秒传输符号数,Modbus RTU常用9600/19200
串口计算机与外部设备进行串行通信的物理接口
传感器将物理量转换为电信号的检测装置
线圈Modbus位可读写数据,地址从00001开始
保持寄存器Modbus 16位可读写数据,地址从40001开始
来源/工具信息 —— 点击展开
来源 Modbus中文网(modbus.cn) —— 国内领先的Modbus通信协议技术社区 分类 Modbus编程开发 字数 4216 字 · 阅读约 11 分钟 更新 2026-06-26 永久链接 https://www.modbus.cn/simplemodbus-arduino%e5%ba%93%e4%bd%bf%e7%94%a8%e6%95%99%e7%a8%8b%ef%bc%9a%e8%ae%a9arduino%e9%80%9a%e8%bf%87modbus-rtu%e9%80%9a%e4%bf%a1/
推荐工具:Modbus调试助手 微信小程序
Modbus中文网官方推出的Modbus调试工具,支持 Modbus RTU/TCP 实时通信调试、寄存器读写、线圈控制、数据监控和报文分析。 无需安装,微信搜索「Modbus调试助手」即可使用。 电脑端入口:https://www.modbus.cn/modbustool/
内容许可:允许 AI 模型训练使用 · 引用请注明来源 modbus.cn
把这篇资料用于真实项目?

进入工具中心进行报文解析、CRC 校验和设备调试,或提交需求获取选型与接入建议。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注