串行端口的传入值有时已损坏或丢失

时间:2019-08-18 16:44:38

标签: c++ arduino

我在两个arduino nano v3板上编写了简单的蓝牙发送器和接收器。蓝牙模块通过HM-10连接到硬件串行端口。它可以工作,但是在接收方,我经常收到损坏的值,并且缺少许多值。问题出在哪里:

我是arduino的初学者。如果有可能需要深入解释。谢谢。

发射器代码:

const long waitingInterval = 20000;
unsigned long lastSend = micros();

void setup()
{
  Serial.begin(19200);
  Serial.println("Started");
}

bool delay() {
  if(micros() >= lastSend + waitingInterval) {
    lastSend = micros();
    return true;
  }

  return false;
}

void loop()
{

  if(delay()) {
    String mil = String(millis());
    String sendingText = mil + ";" + mil + ";" + mil + ".";
    Serial.println(sendingText);
  }

}

变送器串行监控器接口的输出:

10548;10548;10548.
10568;10568;10568.
10589;10589;10589.
10609;10609;10609.
10629;10629;10629.
10649;10649;10649.
10670;10670;10670.
10690;10690;10690.
10711;10711;10711.
10730;10730;10730.
10750;10750;10750.
10771;10771;10771.
10791;10791;10791.
10812;10812;10812.
10831;10831;10831.
10852;10852;10852.
10872;10872;10872.
10893;10893;10893.
10913;10913;10913.
10933;10933;10933.
10953;10953;10953.
10974;10974;10974.
10994;10994;10994.
11014;11014;11014.
11034;11034;11034.
11055;11055;11055.
11075;11075;11075.
11096;11096;11096.
11115;11115;11115.

接收方代码:


void setup() {
  Serial.begin(19200);
  Serial.println("Started");
}

void loop() {

  if(Serial.available()) {

    String incomingData = String();
    char incomingChar = Serial.read();

    if(incomingChar == '.') {
      incomingData = bufferString;
      Serial.print(bufferString);
      bufferString = String();
    } else {
      bufferString += String(incomingChar);
      return;
    }
}

接收器串行监视器接口的输出:

10548;10548;10548
10568;10568;10568
10589;10589;10589
10609;10609;10609
10629;10629;10629
106410771
10791;10791;10791
10812;10812;10812
10831;10831;10831
10852;10852;10852
10872;10872;10872
10893;10893;11034;11034;11034
11055;11055;11055
11075;11075;11075
11096;11096;11096
11115;11115;11115

1 个答案:

答案 0 :(得分:1)

一个问题就是简单地调用Serial.available()仅仅返回可在缓冲区中读取的字节数。它可能恰好是您需要的字节数,可能更少,也可能更多。因此,您可能会读取额外的数据,或者读取的数据太少或太多。更重要的是,在更高级别的传输协议中,有时在设备接收到数据之后,设备会将ACK(确认)发送回发送方,表示已准备好接收更多数据。

编辑**还应注意,有关互斥锁的注释是不正确的。互斥锁通常用于在相同设备上跨多个执行线程同步代码。关键是它们是线程堆空间中的共享资源。使用两个不同的arduino设备时,不是情况;因此,即使可以使用它们,也没有用。

对于您的代码,我建议对发送方进行以下修改:

#define MIN_TIMEOUT 3
void recieveAck(){
  bool validAck = false;
  uint8_t timeout_cnt = 0x00;
  while(timeout_cnt < MIN_TIMEOUT){
    //Wait for receiving device to respond with two bytes then send next
    char incomingBytes[2];
    Serial.readBytes(incomingBytes, 0x02);
    if(incomingBytes[0] == 0xBB && incomingBytes[1] == 0xCC)
      break;
    timeout_cnt++;
  }
}
void loop()
{

  if(delay()) {
    String mil = String(millis());
    String sendingText = mil + ";" + mil + ";" + mil + ".";
    Serial.println(sendingText);
    recieveAck();
  }
}

并发送给接收者:

#define NEXT_INC_SIZE 2 //Expects one byte at a time
void sendAck(){
  char outData[2];
  outData[0] = 0xBB;
  outData[1] = 0xCC;
  Serial.write(outData, 2); //Write the ack data
}
void loop() {
  if(Serial.available() >= NEXT_INC_SIZE){
    char incomingBytes[2];
    Serial.readByte(incomingBytes, NEXT_INC_SIZE); //Read exactly how many bytes you need
    //Do stuff with the data here....
    sendAck();
  }
}