PDA

View Full Version : Serial port split data



ado130
16th May 2017, 13:42
Hello,
I'm using MCU from TI MSP430FR with FTDI FT230.
Code in QT project to receive data from COM port:

connect(m_serialPort, &QSerialPort::readyRead, this, &TokozSerial::HandleReadyRead);


void TokozSerial::HandleReadyRead()
{
if(m_serialPort->bytesAvailable() > 0)
{
while (!m_serialPort->atEnd())
{
m_readData.append(m_serialPort->readAll());
}
HandleTimeout();
}
}

void TokozSerial::HandleTimeout()
{
m_serialPort->clear();
qDebug() << "RawData" << m_readData;
connect(this, &TokozSerial::HandleReady, gp_protocolUart, &ProtocolUart::HandleReady);
emit HandleReady(m_readData);
disconnect(this, &TokozSerial::HandleReady, gp_protocolUart, &ProtocolUart::HandleReady);
disconnect(this, &TokozSerial::HandleReady, 0, 0);
m_readData.clear();
}


In HandleReady I parse this data so I think it's not necessary for this problem.
My problem is that eg. every 5th or 10th (sometimes) I get two packets instead of one.
Example:
MCU send: "\xA1\x00\x00\x01\x81\xDC\xD6"
I get: "\xA1\x00\x00\x01" and then "\x81\xDC\xD6 -- HandleReadyRead called twotimes. I know that together it is correct, but I think this is not working correctly.
It's not always the same. Sometimes I get first 2 bytes, then 5, or 1-6, 6-1 ...


Thanks for any advice.

Lesiok
16th May 2017, 13:52
The serial port is just a data transfer pipe and so it works. Search the forum - the topic has been explained many times.

scgrant327
16th May 2017, 13:54
The SerialPort has no way of knowing what the start and/or end of your data packet is. It only notifies you that there is data available, which you read with the readAll() command.

You should set up a buffer to collect data into until YOU find that you have a complete data packet with your header and footer, then process it...

It's up to you to decide that you have a full data packet. The SerialPort only knows that there is data available to be read, it does not know WHAT the data is, or what it represents.

ado130
16th May 2017, 14:10
Yes, I understand this process. But I do not have any "forbidden char" and the length of received data is not always same. MCU send all data at once, so I hope I can read it all. I'm not sure why data are sometimes fine and sometimes splitted.

scgrant327
16th May 2017, 14:39
As Lesiok said... search and read.

The SerialPort is in no way guaranteed to send all data at once... no matter what the size of the data. It is up to the programmer to make sure YOU know how much data is being sent and/or what marks the beginning and end of the data.

If you truly have no way to know how much data is being transmitted, or what the beginning and end of the data is... then how can you possibly know WHAT the data is?

Lesiok
16th May 2017, 14:53
Ask uncle Google about : ISO OSI RM
Hint: serial port is the lowest layer.

ado130
16th May 2017, 14:56
Thanks. It's not entirely true, that I do not know how much data I'm expecting. I have 3-4 patterns of data packets. So I'll check the data length.
My ignorance about serial port. Thanks for explain.

Lesiok
16th May 2017, 17:44
And these packages do not have any fixed structure? If so, the protocol is incorrectly designed.

ado130
17th May 2017, 15:16
Of course not, these packages have fixed structure. I have just 3 or 4 different patterns.

oazive
18th May 2017, 10:46
I had the same Problem few days ago,
try to add special characters like crlf and append your data on a QString (or anything you want) until you recieve crlf.
QSerialPort doesn't know your frame so it only recieve data when it is available.

ado130
18th May 2017, 15:45
Yes, it is possible way to solve this problem. But I can't be sure that this special character will not be part of correct data - packet and I think, in 21th century is possible to transfer all data without any special characters at the end. I'm just saying, when I sent 20B I also get 20B. So, I changed my program to check this length and it seems working correctly.

scgrant327
22nd May 2017, 14:48
Yes, it is possible way to solve this problem. But I can't be sure that this special character will not be part of correct data - packet and I think, in 21th century is possible to transfer all data without any special characters at the end. I'm just saying, when I sent 20B I also get 20B. So, I changed my program to check this length and it seems working correctly.

In any century, it is not possible to just 'transfer all data' via a serial port without some way to verify the data on the receiving end. The way you are doing WILL fail at some point. If your do not have a starting element or an ending element (preferably both), you can never be absolutely 100% sure you have the correct data.

My advice is if you truly know the structure of the 3 or 4 patterns like you mentioned above, then you should implement code to check the received data fits into one of those patterns.

If something should happen during transmission, and a byte is dropped... or part of the packet is corrupted, then your data will be wrong...and assuming that just because you received 20 bytes that the data is good... is a very, very bad idea.

Just my 2 cents...