Serial message received partially

Asked by At

I try to receive serial message from device, it seems like readyRead() signal is activated after 1, 2 or more chars that appeared on serial buffer.

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{

ui->setupUi(this);

timerTx = new QTimer(this);
timerTx->setInterval(100);

timer.start();
serialRx = new QSerialPort(this);

serialRx->setPortName("COM5"); 
serialRx->setBaudRate(QSerialPort::Baud9600);
serialRx->setParity(QSerialPort::NoParity);
serialRx->setDataBits(QSerialPort::Data8);
serialRx->setStopBits(QSerialPort::OneStop);
serialRx->setFlowControl(QSerialPort::NoFlowControl);

serialTx = new QSerialPort(this);

serialTx->setPortName("COM3"); 
serialTx->setBaudRate(QSerialPort::Baud9600);
serialTx->setParity(QSerialPort::NoParity);
serialTx->setDataBits(QSerialPort::Data8);
serialTx->setStopBits(QSerialPort::OneStop);
serialTx->setFlowControl(QSerialPort::NoFlowControl);

connect(serialRx, SIGNAL(readyRead()), this, SLOT(serialReceive()));
connect(timerTx, SIGNAL(timeout()), this, SLOT(serialSend()));
connect(ui->pushButton, SIGNAL(clicked()), timerTx, SLOT(start()));

}

void MainWindow::serialReceive()
{
QByteArray baRx, num, numOfMs;

qint64 time_ms;
baRx = serialRx -> readAll();

qDebug() << baRx;

time_ms = timer.elapsed();

counterRecDev++;
num = QByteArray::number(counterRecDev);
numOfMs = QByteArray::number(time_ms);

ui->receiveWindow->insertPlainText(num + "\t" + baRx + " \t " + numOfMs + 
"\n" );
ui->receiveWindow -> moveCursor(QTextCursor::End);
}

I send "@Test$" message via serial port but I receive that: "@" "T" "est" "%" other time: "@" "T" "es" "t" "%"

Could you tell me please how to solve it? Maybe the problem is that i use readyRead() signal?

Best regars.

2 Answers

0
Emir Cesovic On Best Solutions

Using readyRead() is OK, but you need to check, in your code, that all of the expected data is received, before processing it. This is usually done by having start and stop characters in the messages and checking that received data contains both before processing(looks like you are already using "@" and "$ for this). And, since reading from QSerialPort will clear its buffer, you will also need to buffer received data in your code untill it is ready to be processed. You could do something like this:

QByteArray rxBuffer;
void MainWindow::serialReceive()
{
   rxBuffer.append(serialRx -> readAll());
   while(rxBuffer.contains("@") && rxBuffer.contains("$")) {
      QByteArray message;

      // Discard any data preceding message start character
      rxBuffer = rxBuffer.right(rxBuffer.length() - rxBuffer.indexOf("@"));

      // Take first complete message from the buffer
      message = rxBuffer.left(rxBuffer.indexOf("$") + 1);

      // Remove extracted message from buffer
      rxBuffer = rxBuffer.right(rxBuffer.length() - rxBuffer.indexOf("$") - 1);

      // Your code here

   }
}
0
Mike On

I've ran into problems with QSerialPort recieving messages over multuple readyRead signals. Having an accumulation buffer may to the trick for you, but you will need either a start or end identifier.