前言
最近在研究为什么之前搭建的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.