0

I am beginner in Qt. To first I would like to do application to communicate with serial device. This communication I did in thread. Sending work perfectly, but I have problem with receiving messages. The message should will be recive imediatelly after send frame. I think that problem is with m_Serial->waitForReadyRead(10)

Below I paste my piece of code:

void SerialWorker::doWork()
{
qDebug()<<"Starting worker process in Thread "<<thread()->currentThreadId();
bool abort = false;
quint8 inByte;
quint8 checksum_temp;
int numByte = 0;
int receiverStatus = RCV_ST_IDLE;
Frame *m_inFrame = nullptr;
int dataLength = 0;

QByteArray buffer_checksum;

// Serial Port Initialization
m_Serial = new QSerialPort();
m_Serial->setPortName("COM6");
m_Serial->setBaudRate(QSerialPort::Baud9600);
m_Serial->setDataBits(QSerialPort::Data8);
m_Serial->setParity(QSerialPort::NoParity);
m_Serial->setStopBits(QSerialPort::OneStop);
m_Serial->setFlowControl(QSerialPort::NoFlowControl);
m_Serial->open(QIODevice::ReadWrite);
qDebug() << "SerialPort Status: " << m_Serial->isOpen();

while(!abort)
{
    mutex.lock();
    abort = _abort;
    mutex.unlock();

    if(!m_outFrameQueue->isEmpty())
    {
        Frame *outFrame = m_outFrameQueue->dequeue();
        sendFrame(outFrame);
        delete outFrame;

    } else

    {
        if (m_Serial->waitForReadyRead(10))
        {
            QByteArray receivedData = m_Serial->readAll();

            while(receivedData.count() > 0)
            {
                inByte = quint8(receivedData[0]);
                receivedData.remove(0,1);

                    switch (receiverStatus)
                    {
                        case RCV_ST_IDLE:
                            {
                                if(inByte == Frame::FRAME_ADDR_RFiD)
                                {
                                    if (m_inFrame == nullptr)
                                        m_inFrame = new Frame();

                                    else
                                        m_inFrame->Clear();

                                    m_inFrame->AddByte(inByte);
                                    buffer_checksum.append(inByte);
                                    receiverStatus = RCV_ST_DATA_LENGTH;
                                }
                                else
                                {
                                    buffer_checksum.clear();
                                }
                            } break;

                        case RCV_ST_DATA_LENGTH:
                            {

                                dataLength = inByte;      
                                numByte = dataLength - 6; 
                                m_inFrame->AddByte(inByte);
                                buffer_checksum.append(inByte);
                                receiverStatus = RCV_ST_CMD;
                            } break;

                        case RCV_ST_CMD:
                            {
                                m_inFrame->AddByte(inByte);
                                buffer_checksum.append(inByte);
                                if(numByte > 0)
                                receiverStatus = RCV_ST_DATA;
                                else receiverStatus = RCV_ST_CODE;

                            } break;

                        case RCV_ST_DATA:
                            {
                                m_inFrame->AddByte(inByte);
                                buffer_checksum.append(inByte);
                                if (--numByte == 0)
                                    receiverStatus = RCV_ST_CODE;
                                else if (numByte < 0)
                                    receiverStatus = RCV_ST_IDLE;
                            } break;

                        case RCV_ST_CODE:
                            {
                                m_inFrame->AddByte(inByte);
                                buffer_checksum.append(inByte);
                                receiverStatus = RCV_ST_CHECKSUM_HI;
                            } break;

                        case RCV_ST_CHECKSUM_HI:
                            {
                                checksum_temp = (m_inFrame->CalculateCRC2_in(buffer_checksum) >> 8) & 0xFF;
                                if (inByte == checksum_temp)
                                {

                                    m_inFrame->AddByte(checksum_temp);
                                    receiverStatus = RCV_ST_CHECKSUM_LO;
                                }
                                else
                                {

                                    receiverStatus = RCV_ST_IDLE;
                                    m_inFrame->Clear();
                                    delete m_inFrame;
                                }
                            } break;

                        case RCV_ST_CHECKSUM_LO:
                            {

                                checksum_temp = m_inFrame->CalculateCRC2_in(buffer_checksum) & 0xFF;
                                if (inByte == checksum_temp)
                                {
                                    receiverStatus = RCV_ST_IDLE;
                                    m_inFrame->AddByte(checksum_temp);
                                    emit this->frameReceived(m_inFrame);
                                    qDebug()<< "Frame:  " << Qt::hex << m_inFrame;
                                }
                                else
                                {

                                    receiverStatus = RCV_ST_IDLE;
                                    m_inFrame->Clear();
                                    delete m_inFrame;

                                }
                            } break;
                     }

            }
        } 
    }
}
}

I checked whether the device definitely send frame, by this code

void SerialWorker::doWork()
{
qDebug()<<"Starting worker process in Thread "<<thread()->currentThreadId();

bool abort = false;
quint8 inByte;
quint8 checksum_temp;
int numByte = 0;
int receiverStatus = RCV_ST_IDLE;
Frame *m_inFrame = nullptr;
int dataLength = 0;

QByteArray buffer_checksum;

// Serial Port Initialization
m_Serial = new QSerialPort();
m_Serial->setPortName("COM6");
m_Serial->setBaudRate(QSerialPort::Baud9600);
m_Serial->setDataBits(QSerialPort::Data8);
m_Serial->setParity(QSerialPort::NoParity);
m_Serial->setStopBits(QSerialPort::OneStop);
m_Serial->setFlowControl(QSerialPort::NoFlowControl);
m_Serial->open(QIODevice::ReadWrite);
qDebug() << "SerialPort Status: " << m_Serial->isOpen();

while(!abort)
{
    mutex.lock();
    abort = _abort;
    mutex.unlock();
   
    QByteArray receivedData = m_Serial->readAll();


    if(!m_outFrameQueue->isEmpty())
    {
        Frame *outFrame = m_outFrameQueue->dequeue();
        sendFrame(outFrame);
        delete outFrame;

    } else

    {
        if (receivedData.count() > 0) {
            qDebug() <<  "something came: "<< Qt::hex << receivedData.toHex() ;
            receivedData.clear();
        }
    }
}
}

And it works. In receivedData.toHex() the receiving frame ic correct. So what is wrong with my fully soution pasted like first code ?

ienecode
  • 1
  • 1
  • FYI you can use signal-slot mechanism to read from QSerialPort asyncronously and avoid mutexes and threads altogeter https://doc.qt.io/qt-5/qtserialport-creaderasync-example.html – mugiseyebrows Oct 19 '22 at 10:02
  • 1
    Please always post a minimal example, see [mcve]. Your question is about receiving data, so all code related to processing the received data is irrelevant. – m7913d Oct 19 '22 at 11:32

1 Answers1

0

I solved my problem by creating a slot for readyRead() signal. Solution/problem is described here:

https://stackoverflow.com/a/44693193/11766659

ienecode
  • 1
  • 1