modbus 写多个保持寄存器时遇到的问题 已解决


#include 
#include 
#include 
#define RX_PIN      13
#define TX_PIN      15
RS485Class RS485(Serial2, RX_PIN, TX_PIN,-1,-1);
uint16_t msg[3] = {0x0041,0x0042,0x0043}; 
void setup() {
  M5.begin(true,true,true);
  if (!ModbusRTUClient.begin(9600, SERIAL_8E1)) {
        Serial.println("Failed to start Modbus RTU Client!");
        return;
  }
  ModbusRTUClient.beginTransmission(0x01,HOLDING_REGISTERS,1,3);
  int i=3;
  uint16_t *p = msg;
  while(i){
    if(!ModbusRTUClient.write(*p)){
      Serial.println(ModbusRTUClient.lastError());
      return;
    }
    p++;
    i--;
  }
  ModbusRTUClient.endTransmission();
}
void loop() {
}

设置的从站id是1,可是modbus slave软件的记录里收到的从站地址(即第一个字节)却是不对的,如下

 正确的应该是01 10 00 01 00 03 06 00 41 00 42 00 43  6A AF,从站id为1时最后的校验码是6A AF

尝试将波特率调整为115200,这时前几字节数据也不对,如下

 第一个字节变成了00,然后是正确的从站id等数据

 在仅使用holdingRegisterWrite()函数写单个寄存器时,这种情况也出现了(起初我以为写单个寄存器时没有首字节异常的问题),下面是代码及记录

#include 
#include 
#include 
#define RX_PIN      13
#define TX_PIN      15
RS485Class RS485(Serial2, RX_PIN, TX_PIN,-1,-1);
uint16_t x = 0;
int i = 5;
void setup() {
  M5.begin(true,true,true);
  if (!ModbusRTUClient.begin(9600, SERIAL_8E1)) {
        Serial.println("Failed to start Modbus RTU Client!");
        return;
  }
}
void loop() {
  if(!ModbusRTUClient.holdingRegisterWrite(1,1,x)){
    Serial.print("Failed to write holdingRegister! ");
    Serial.println(ModbusRTUClient.lastError());
  }
  x++;
  i--;
  if(i == 0){
    ModbusRTUClient.end();
    return;
  }
  delay(1000);
}

所以解决这类问题的方法就是先发一帧无用的数据,再发有效的数据

我试着直接向串口写16进制数据,发现收到的数据中第一个字节仍然不对

#include 
#define RX_PIN      13
#define TX_PIN      15

int i = 8;
uint8_t s[8] = {0x02,0x06,0x00,0x04,0x13,0x88,0xC5,0x6E};
uint8_t *p = s;
void setup() {
  M5.begin(true,true,true);
  Serial2.begin(9600, SERIAL_8E1, RX_PIN, TX_PIN);
}
void loop() {
  while(i){
    Serial2.write(*p);
    p++;
    i--;
  }
  delay(1000);
}

 直接向串口写字符数据

电脑端收到的数据仍然有问题

#include 
#define RX_PIN      13
#define TX_PIN      15

int i = 5;
char *s = "hello";

void setup() {
  M5.begin(true,true,true);
  Serial2.begin(9600, SERIAL_8E1, RX_PIN, TX_PIN);
}
void loop() {
  while(i){
    Serial2.write(*s);
    s++;
    i--;
  }
  delay(1000);
}

但是从电脑端向485设备写数据,设备端收到的却与发送的数据完全一致,可正常显示在IotBase的屏幕上

解决方法很简单 在设备初始化后加个延时就好

相关