Почему у QTSerialPort заканчиваются байты внутри потока?

У меня есть тема, похожая на это. Проблема, с которой я столкнулся, заключается в том, что через несколько секунд serial_port->bytesAvailable() показывает 0 после того, как я прочитал все байты, и я думаю, что это связано с потоками, вызывающими эту проблему.

Вопрос:

Есть ли правильный способ орудия QSerialPortвнутри потока или вне потока? Что ты думаешь я должен сделать?

Код:

      USB_message_available_thread::USB_message_available_thread(QSerialPort* serial_port, J1939* j1939, uint8_t* length_of_usb_message) : serial_port(serial_port), j1939(j1939), length_of_usb_message(length_of_usb_message) {

}

void USB_message_available_thread::run(){
    while(1){
        if(serial_port->isOpen()){
            if(serial_port->bytesAvailable() >= *length_of_usb_message){
                switch(*length_of_usb_message){
                case USB_J1939_MESSAGE_BYTES_FROM_STM32:
                    Open_SAE_J1939_Listen_For_Messages(j1939);
                    break;
                case USB_MEASUREMENT_MESSAGE_BYTES_FROM_STM32:
                    break;
                case USB_NOT_READ_MESSAGES_FROM_STM32:
                    serial_port->flush(); /* Flush the USB port from bytes */
                    break;
                }
            }
        }
        msleep(10);
    }
}

/* QT includes */
#include <QThread>
#include <QSerialPort>

/* Project includes */
#include "Window/Main/UI/UI_tools/Communication/J1939/Open_SAE_J1939/Open_SAE_J1939.h"

class USB_message_available_thread : public QThread {
public:
    USB_message_available_thread(QSerialPort* serial_port, J1939* j1939, uint8_t* length_of_usb_message);
private:
    /* Constructor fields */
    QSerialPort* serial_port;
    J1939* j1939;
    uint8_t* length_of_usb_message;

    /* Logic */
    void run();
};

1 ответ

да. Темы + QSerialPort плохая комбинация.

Намного лучше использовать readyReadкак было предложено выше. Вот простой пример USB-связи с slots. Для каждого байта, который я отправляю в порт USB, функция bytesAvailable()будет вызываться напрямую, как слушатель. Но я проверяю, какой длины должно быть сообщение USB, потому что каждое сообщение USB (в моем случае) имеет разную длину.

      #include "usb_handling.h"

/* Private includes */
#include "Tools/Communication/J1939/Hardware/CAN_Network/CAN_to_USB/can_to_usb.h"
#include "../usb_message_sizes.h"
#include "../../J1939/Open_SAE_J1939/Open_SAE_J1939.h"

USB_handling::USB_handling(J1939* j1939) : j1939(j1939) {

    /* Create serial port */
    serial_port = new QSerialPort();
    serial_port_info = new QSerialPortInfo();

    /* Save serial port pointer to CAN source file */
    QT_USB_set_serial_handler(serial_port);

    /* Start a listener for every time this application got a byte, then the function bytesAvailable is going to run */
    connect(serial_port, &QSerialPort::readyRead, this, &USB_handling::bytesAvailable);
}

QStringList USB_handling::get_port_names(){
    QStringList port_names;
    QList<QSerialPortInfo> port_info = serial_port_info->availablePorts();
    for (int i = 0; i < port_info.length(); i++)
        if (port_info.at(i).isBusy() == false)
            port_names.append(port_info.at(i).portName());
    return port_names;
}

bool USB_handling::connect_to_usb(const QString& port_name, const qint32 baudrate, QSerialPort::DataBits data_bits, QSerialPort::Parity parity, QSerialPort::StopBits stop_bits, QSerialPort::FlowControl flow_control){
    serial_port->setPortName(port_name);
    serial_port->setBaudRate(baudrate);
    serial_port->setDataBits(data_bits);
    serial_port->setParity(parity);
    serial_port->setStopBits(stop_bits);
    serial_port->setFlowControl(flow_control);
    if(serial_port->open(QIODevice::ReadWrite)){
        length_of_usb_message = USB_NOT_READ_MESSAGES_FROM_STM32;
        return true;
    }else{
        return false;
    }
}

void USB_handling::disconnect_from_usb(){
    serial_port->close();
}

void USB_handling::bytesAvailable(){
    if(serial_port->bytesAvailable() >= length_of_usb_message){
        switch(length_of_usb_message){
        case USB_J1939_MESSAGE_BYTES_FROM_STM32:
            Open_SAE_J1939_Listen_For_Messages(j1939);
            break;
        case USB_MEASUREMENT_MESSAGE_BYTES_FROM_STM32:
            break;
        case USB_NOT_READ_MESSAGES_FROM_STM32:
            serial_port->flush(); /* Flush the USB port from bytes */
            break;
        }
    }
}

#ifndef USB_HANDLING_H
#define USB_HANDLING_H

/* QT includes */
#include <QObject>
#include <QSerialPort>
#include <QSerialPortInfo>

/* Project includes */
#include "../../J1939/Open_SAE_J1939/Structs.h"

class USB_handling : public QObject {
    Q_OBJECT
public:
    USB_handling(J1939* j1939);
    QStringList get_port_names();
    bool connect_to_usb(const QString& port_name, const qint32 baudrate, QSerialPort::DataBits data_bits, QSerialPort::Parity parity, QSerialPort::StopBits stop_bits, QSerialPort::FlowControl flow_control);
    void disconnect_from_usb();
    uint8_t length_of_usb_message;
private:    
    /* Constructor fields */
    J1939* j1939;

    QSerialPortInfo* serial_port_info;
    QSerialPort* serial_port;

private slots:
    void bytesAvailable();
};

#endif // USB_HANDLING_H
Другие вопросы по тегам