串行通信,关于缓冲处理的困惑

时间:2014-05-21 11:13:12

标签: c++ arduino buffer

我正在尝试使用arduino进行一些基本的加速数据输出。我目前面临的问题是我对如何处理通过串口发送的数据缺乏基本的了解。 首先是我简单的arduino程序:

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    sendData();
  }

}

void sendData() {
      // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    writeBuffer[0] = '<';
    writeBuffer[1] = lowByte(ax);
    writeBuffer[2] = highByte(ax);
    writeBuffer[3] = lowByte(ay);
    writeBuffer[4] = highByte(ay);
    writeBuffer[5] = lowByte(az);
    writeBuffer[6] = highByte(az);
    writeBuffer[7] = '>';

    Serial.write(writeBuffer, 8);         
    //Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF));
    //Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF));
    //Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF));

    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
}

这是我的c ++代码:

Serial* SP = new Serial("COM5");    // adjust as needed

    if (SP->IsConnected())
        printf("We're connected!\n");

    char incomingData[8] = "";          // don't forget to pre-allocate memory
    //printf("%s\n",incomingData);
    int dataLength = 8;
    int readResult = 0;

    while (SP->IsConnected())
    {
        readResult = SP->ReadData(incomingData, dataLength);
        //printf("Bytes read: (-1 means no data available) %i\n", readResult);

        if (readResult < 8 || incomingData[0] != '<' || incomingData[7] != '>') {
            continue;
        }

        char low = incomingData[1];
        char high = incomingData[2];

        int ax = (high << 8 | low);

        low = incomingData[3];
        high = incomingData[4];

        int ay = (high << 8 | low);

        low = incomingData[5];
        high = incomingData[6];

        int az = (high << 8 | low);

        printf("ax: %i, ay: %i, az: %i\n", ax, ay, az); 

        //Sleep(500);
    }
    return 0;

这就是read函数的工作原理:

int Serial::ReadData(char *buffer, unsigned int nbChar)
{
    //Number of bytes we'll have read
    DWORD bytesRead;
    //Number of bytes we'll really ask to read
    unsigned int toRead;

    //Use the ClearCommError function to get status info on the Serial port
    ClearCommError(this->hSerial, &this->errors, &this->status);

    //Check if there is something to read
    if (this->status.cbInQue > 0)
    {
        //If there is we check if there is enough data to read the required number
        //of characters, if not we'll read only the available characters to prevent
        //locking of the application.
        if (this->status.cbInQue > nbChar)
        {
            toRead = nbChar;
        }
        else
        {
            toRead = this->status.cbInQue;
        }

        //Try to read the require number of chars, and return the number of read bytes on success
        if (ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL) && bytesRead != 0)
        {
            return bytesRead;
        }

    }

    //If nothing has been read, or that an error was detected return -1
    return -1;

}

现在您可以看到我用两个标记“&lt;”标记我的串行输出和“&gt;”。客户端的问题是我不知道如何确保我真的只读取这些块。我怎么知道一个完整的块是否到达?我是否必须首先将所有数据读入缓冲区然后进行处理?如果我这样做,我如何处理不完整的块(在整个块发送之前从读取创建)?我很困惑这个概念是如何运作的。也许有人可以解释这个问题是如何得到解决的? 非常感谢!

1 个答案:

答案 0 :(得分:0)

关于从常规串行端口读取数据,通过普通串行电缆,最重要的是要了解串行端口CAN丢失或损坏的数据。

在您的情况下,它可能非常不可能,接近不可能 - 您可能处于低波特率,不经常发送,短电缆等等。但在一般情况下,它开始变得有可能在某些时候你和#39;将获得损坏的数据。

因此,我尝试读取该数据包的方式是一个小型状态机,它只会丢弃地板上的损坏数据包:

  • 删除字符,直到收到&#39;&lt;&#39;
  • 最多可以在缓冲区中接收6个字符。
  • 如果下一个字符是&gt;,则处理该消息。
  • 重置缓冲区指针并重新开始。