1. 环境配置: 参考Arduino IDE上手教程完成 IDE 安装,并根据实际使用的开发板安装对应的板管理,与需要的驱动库。
2. 使用到的驱动库:
3. 使用到的硬件产品:


0x01)。Client 每秒向 Server 的保持寄存器 0x0000 写入一个递增值,再读取该寄存器并比较结果。CoreS3 的 PORT.A 使用 G1 (RX)、G2 (TX),PORT.C 使用 G18 (RX)、G17 (TX)。Unit RS485-ISO 内部支持自动收发方向控制,因此 DE/RE 引脚均设置为 -1。
#include "M5Unified.h"
#include <Wire.h>
#include <ArduinoModbus.h>
#include <ArduinoRS485.h>
constexpr uint32_t MODBUS_BAUDRATE = 115200;
constexpr uint8_t SERVER_ID = 0x01;
constexpr uint16_t REGISTER_ADDR = 0x0000;
constexpr int PORT_A_RX_PIN = 1;
constexpr int PORT_A_TX_PIN = 2;
constexpr int PORT_C_RX_PIN = 18;
constexpr int PORT_C_TX_PIN = 17;
// PORT.A uses Serial2 as the Modbus RTU Client interface.
RS485Class RS485(Serial2, PORT_A_RX_PIN, PORT_A_TX_PIN, -1, -1);
// PORT.C uses Serial1 as the Modbus RTU Server interface.
RS485Class RS485PortC(Serial1, PORT_C_RX_PIN, PORT_C_TX_PIN, -1, -1);
ModbusRTUClientClass portAClient(RS485);
ModbusRTUServerClass portCServer(RS485PortC);
uint16_t transmitValue = 0;
void modbusServerTask(void *parameter);
void showResult(uint16_t sentValue, long receivedValue);
void haltWithError(const char *message);
void setup()
{
M5.begin();
Serial.begin(115200);
delay(2000);
M5.Display.setFont(&fonts::FreeMonoBold12pt7b);
M5.Display.setTextColor(TFT_WHITE, TFT_BLACK);
M5.Display.clear();
M5.Display.println("RS485 initializing");
// Release PORT.A from I2C before using its pins for Serial2.
Wire.end();
if (!portCServer.begin(SERVER_ID, MODBUS_BAUDRATE, SERIAL_8N1)) {
haltWithError("Server init failed");
}
if (!portCServer.configureHoldingRegisters(REGISTER_ADDR, 1)) {
haltWithError("Register init failed");
}
portCServer.holdingRegisterWrite(REGISTER_ADDR, 0);
if (xTaskCreatePinnedToCore(modbusServerTask, "modbus-server", 4096,
nullptr, 2, nullptr, 0) != pdPASS) {
haltWithError("Server task failed");
}
if (!portAClient.begin(MODBUS_BAUDRATE, SERIAL_8N1)) {
haltWithError("Client init failed");
}
portAClient.setTimeout(500);
Serial.println("PORT.A Client and PORT.C Server started");
delay(100);
}
void loop()
{
++transmitValue;
bool writeSuccess = portAClient.holdingRegisterWrite(
SERVER_ID, REGISTER_ADDR, transmitValue);
long receivedValue = -1;
if (writeSuccess) {
receivedValue = portAClient.holdingRegisterRead(
SERVER_ID, REGISTER_ADDR);
}
showResult(transmitValue, receivedValue);
delay(1000);
}
void modbusServerTask(void *parameter)
{
while (true) {
portCServer.poll();
vTaskDelay(1);
}
}
void showResult(uint16_t sentValue, long receivedValue)
{
bool success = receivedValue >= 0 &&
static_cast<uint16_t>(receivedValue) == sentValue;
Serial.printf("PORT.A TX: 0x%04X, PORT.C RX/TX: 0x%04lX, %s\n",
sentValue, receivedValue, success ? "PASS" : "FAIL");
M5.Display.clear();
M5.Display.setCursor(0, 0);
M5.Display.println("Unit RS485-ISO Test");
M5.Display.println("A Client -> C Server");
M5.Display.printf("TX: 0x%04X\n", sentValue);
if (receivedValue >= 0) {
M5.Display.printf("RX: 0x%04lX\n", receivedValue);
} else {
M5.Display.println("RX: ERROR");
}
M5.Display.printf("Status: %s\n", success ? "PASS" : "FAIL");
}
void haltWithError(const char *message)
{
Serial.println(message);
M5.Display.clear();
M5.Display.setCursor(0, 0);
M5.Display.println(message);
while (true) {
delay(1000);
}
}
