前言
最近在研究为什么之前搭建的Modbus RS485 IIoT系统不work,抽了个周末,debug了一下,发现Serial.write(buf, len)也许在我新买的Arduino Uno R4 Wifi上有兼容性问题,导致了Modbus protocol的CRC检测一直失败(因为传送的CRC总是不全,无奈orz,同时上传了一个Modbus-Master-Slave-for-Arduino上传了一个"Timeout" on Arduino Uno R4 Wifi due to Serial1.write(buf, len) and CRC check #75,希望能帮到各位用Arduino Uno R4 Wifi 同时又要用 RS485 Modbus RTU的人的说)。
具体问题就是Serial.write(buf, len),本应该传送前len个buf中的元素,但是只传送了len-1个,经过测试SoftwareSerial没有这个问题,但是Serial1存在。具体问题已经在uno-r4-library-compatibility中开了Serial1.write(buf, len) (FAIL) #28。
正文
1. Serial1.write(buf, len) (len = 8 只传送 7个元素)
Arduino master:
uint8_t au8Buffer[64]; void setup() { Serial.begin(9600); Serial1.begin(9600); au8Buffer[0] = 1; au8Buffer[1] = 3; au8Buffer[2] = 0; au8Buffer[3] = 1; au8Buffer[4] = 0; au8Buffer[5] = 4; au8Buffer[6] = 21; au8Buffer[7] = 22; } void loop() { Serial1.write(au8Buffer, 8); }
Arduino slave:
void setup() { Serial.begin(9600); Serial1.begin(9600); } void loop() { if(Serial1.available()) { Serial.println(Serial1.read()); } }
2. Serial1.write(buf, len) (len = 9 正好传送 8个元素)
Arduino master:
uint8_t au8Buffer[64]; void setup() { Serial.begin(9600); Serial1.begin(9600); au8Buffer[0] = 1; au8Buffer[1] = 3; au8Buffer[2] = 0; au8Buffer[3] = 1; au8Buffer[4] = 0; au8Buffer[5] = 4; au8Buffer[6] = 21; au8Buffer[7] = 22; } void loop() { Serial1.write(au8Buffer, 9); }
Arduino slave:
void setup() { Serial.begin(9600); Serial1.begin(9600); } void loop() { if(Serial1.available()) { Serial.println(Serial1.read()); } }
3. SoftwareSerial (工作正常 len = 8 就传送 8个)
Arduino master:
#include <SoftwareSerial.h> #define RX 8 #define TX 11 uint8_t au8Buffer[64]; SoftwareSerial mySerial(RX, TX); void setup() { Serial.begin(9600); //Serial1.begin(9600); mySerial.begin(9600); au8Buffer[0] = 1; au8Buffer[1] = 3; au8Buffer[2] = 0; au8Buffer[3] = 1; au8Buffer[4] = 0; au8Buffer[5] = 4; au8Buffer[6] = 21; au8Buffer[7] = 22; } void loop() { //Serial1.write(au8Buffer, 9); mySerial.write(au8Buffer, 8); }
Arduino slave:
#include <SoftwareSerial.h> #define RX 8 #define TX 11 SoftwareSerial mySerial(RX, TX); void setup() { Serial.begin(9600); Serial1.begin(9600); } void loop() { //if(Serial1.available()) { // Serial.println(Serial1.read()); //} if(mySerial.available()) { Serial.println(mySerial.read()); } }
4. 解决办法
在所有用到Serial.write(buf, len)的地方,给len手动+1。
总结
挺无奈,但是目前唯一的办法就是在所有用Serial.write(buf, len)的地方,手动给len + 1吧。 /(ㄒoㄒ)/~~
参考
[1] Modbus-Master-Slave-for-Arduino
[2] "Timeout" on Arduino Uno R4 Wifi due to Serial1.write(buf, len) and CRC check #75
[3] uno-r4-library-compatibility
[4] Serial1.write(buf, len) (FAIL) #28
Q.E.D.