Używam QSerialport, aby odczytać z urządzenia podłączonego do portu COM na moim komputerze i wysyła znaki co pół sekundy do mojego komputera. Mogę je przeczytać z okna QDebug, więc znam prace związane z połączeniem i QT otrzymują dane.

Jednak stale czytam z portu szeregowego i odświeżam widżet etykiety na moim GUI. Etykieta staje się pusta, gdy uruchomię aplikację, myślę, że ten problem jest spowodowany przez nazwę etykiety stale odświeżającą.

Mój QSerialport jest zarządzany w konstruktorze Mainwindow, zamknięte w destructor, a odczyty są wykonywane w funkcji zwanej serialReceived (), co wierzę, że nazywa się zbyt często (lub powoduje, że etykieta)

    MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    serial = new QSerialPort(this);

    qDebug() << "nb ports: " << QSerialPortInfo::availablePorts().length();
    foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts())
    {
qDebug() << "name" << serialPortInfo.portName();
    }

    serial->setPortName("COM11");
    serial->setBaudRate(QSerialPort::Baud9600);
    serial->setDataBits(QSerialPort::Data8);
    serial->setParity(QSerialPort::NoParity);
    serial->setStopBits(QSerialPort::OneStop);
    serial->setFlowControl(QSerialPort::NoFlowControl);
    qDebug() << "is " << serial->open(QSerialPort::ReadOnly);
    qDebug() << "err " << serial->error();
    //serial->write("ok");

    // Create the signal and slot
    connect(serial, SIGNAL(readyRead()), this, SLOT(serialReceived()));
}

MainWindow::~MainWindow()
{
    delete ui;
    serial->close(); // instance is closed when mainwindow destroyed
}

void MainWindow::serialReceived()
{
    QByteArray ba;
    ba = serial->readAll();
    ui->label->setText(serial->readAll());
    qDebug()<<ba;
}
0
JCSB 25 marzec 2020, 18:34

2 odpowiedzi

Najlepsza odpowiedź
void MainWindow::serialReceived()
{
    QByteArray ba;
    ba = serial->readAll();
    ui->label->setText(serial->readAll());
    qDebug()<<ba;
}

Najpierw czytasz dane do ba, a następnie próbujesz ponownie przeczytać, ale ponieważ Readall () już przeczytaj dane, nie ma nic. Chcesz

void MainWindow::serialReceived()
{
    QByteArray ba = serial->readAll();
    ui->label->setText(ba);
    qDebug() << ba;
}
1
chehrlic 25 marzec 2020, 18:45

Wystarczy odczytać dane w dowolnym momencie, nie tylko przez sygnał readyRead. Klasa QSerialPort będzie buforować wszystkie otrzymane dane, dopóki go przeczytasz.

Możesz także dołączyć każdą otrzymaną część danych do jakiejś przewijania QPlainTextEdit. Polecam w ten sposób.

void MainWindow::serialReceived()
{
    QByteArray ba;
    ba = serial->readAll();

    ui->plainTextEdit->appendPlainText(ba);
}

Korzystanie z timera:

connect(&m_timer, &QTimer::timeout, this, &MyClass::onTimer);
...
m_timer->start(5000);
...

void MyClass::onTimer()
{
    if(serial->bytesAvailable() > 0)
    {
         QByteArray ba;
         ba = serial->readAll();
         ui->label->setText(ba);
         qDebug() << ba;  
    }
}

Możesz także tymczasowe wyłączone aktualizacje wizualne widget za pomocą QWidget :: SetUpdatesenabled ( ), ale wydaje się, że nie powinieneś przegapić części danych.

Uwaga, QIODevice (i QSerialPort jako jego Subass, również) Klasa nie gwarantuje, że pewna ilość danych będzie dostępna na zdarzeniu {x2}}. Na przykład, jeśli napisałeś 10 bajtów do portu na raz na drugim końcu, w niektórych przypadkach otrzymasz sygnał, który umożliwi mniej danych będzie dostępny w Monencie, czyli przede wszystkim przenoszone bajty.

1
Vladimir Bershov 25 marzec 2020, 23:32