#include <M5Stack.h> #include <ArduinoModbus.h> #include <ArduinoRS485.h> #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 <M5Stack.h> #include <ArduinoModbus.h> #include <ArduinoRS485.h> #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 <M5Stack.h> #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 <M5Stack.h> #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的屏幕上
解決方法很簡單 在設備初始化后加個延時就好
