Qt QSerialPort Чтение Запись - PullRequest
0 голосов
/ 01 апреля 2019

У меня проблема с чтением и записью из / в QSerialPort.Я прочитал то, что я написал.Вот пример кода, который доказывает это.Может быть, мне нужно писать и читать с разных каналов.Код предоставляется ниже, спасибо.Предоставлен журнал программы с изображением.

Лог программы здесь

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>
#include <QTimer>
#include <QDebug>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    QSerialPort *serialPort;
    QTimer* sendTimer;
    QByteArray receiveDataBuffer;

private slots:
    void onReadyRead();
    void onSendDataTimeout();

};

#endif // MAINWINDOW_H

MainWindows.cpp

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      serialPort(new QSerialPort),
      sendTimer(new QTimer)
{
    sendTimer->setInterval(1000);
    serialPort->setPortName("COM5");
    serialPort->setBaudRate(QSerialPort::Baud115200);
    serialPort->setParity(QSerialPort::Parity::NoParity);
    serialPort->setDataBits(QSerialPort::DataBits::Data8);
    serialPort->setStopBits(QSerialPort::StopBits::TwoStop);
    serialPort->open(QSerialPort::OpenModeFlag::ReadWrite);

    connect(serialPort,&QSerialPort::readyRead,this,&MainWindow::onReadyRead);
    connect(sendTimer,&QTimer::timeout,this,&MainWindow::onSendDataTimeout);
    sendTimer->start();
}

MainWindow::~MainWindow()
{

}

void MainWindow::onReadyRead()
{
    receiveDataBuffer.append(serialPort->readAll());
    if (receiveDataBuffer.contains('^') && receiveDataBuffer.contains('$') && receiveDataBuffer.lastIndexOf('$') < receiveDataBuffer.lastIndexOf('^')) {
        QByteArray extractedByteArray;

        for(int i = receiveDataBuffer.lastIndexOf("$") ; i < receiveDataBuffer.lastIndexOf("^") + 1 ; i++){
            extractedByteArray.append(receiveDataBuffer[i]);
        }
        qDebug()<<"Received:"<<extractedByteArray<<endl;
        receiveDataBuffer.clear();
    }}

void MainWindow::onSendDataTimeout()
{
    qint64 result = serialPort->write("$10,0,123,123^");
    bool flush = serialPort->flush();
    result != -1 && flush ? qDebug()<<"Data sent"<<endl:qDebug()<<"Failed to send data"<<endl;
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

Ответы [ 2 ]

0 голосов
/ 02 апреля 2019

Проблема была в

    serialPort->setStopBits(QSerialPort::StopBits::TwoStop);

Другое устройство было подключено к последовательному порту с QSerialPort::StopBits::OneStop. Таким образом, изменяя стоп-биты serialPort->setStopBits(QSerialPort::StopBits::OneStop); решил проблему, и эха больше не было. Спасибо.

0 голосов
/ 01 апреля 2019

Прежде всего, попробуйте подключить различные сигналы, которые испускаются, когда вы читаете / записываете это из своего порта.

Например, для проверки правильности отправки данных, в соответствии с документацией вы можете использовать сигнал QIODevice::bytesWritten:

Сигнал испускается каждый раз, когда полезная нагрузка данных записывается в текущий канал записи устройства. Аргумент bytes устанавливается равным количеству байтов, записанных в этой полезной нагрузке.

connect(serialPort,&QSerialPort::bytesWritte, this, [](const qint64 bytes) {
    qDebug() << "Sent data: " << bytes << " bytes.";
});

Чтобы прочитать данные, как вы уже это сделали, вам нужно проверить сигнал QIODevice::readyRead:

Этот сигнал испускается один раз каждый раз, когда новые данные доступны для чтения из текущего канала чтения устройства. Он будет отправляться снова только после того, как станут доступны новые данные, например, когда новая полезная нагрузка сетевых данных поступит на сетевой сокет или когда новый блок данных будет добавлен на ваше устройство.

Что касается описанной вами проблемы, первый шаг, который необходимо сделать, - убедиться, что ваш дециив не был настроен на работу в эхо-режиме. Чтобы отключить его, вам необходимо проверить интерфейс вашего устройства.

Если это не проблема, проверьте доступные порты с помощью `QSerialPort :: availablePorts и убедитесь, что вы подключаетесь к правильному. Например, чтобы подключиться к первому порту, вы можете сделать что-то вроде этого и проверить, что конфигурация совместима с вашим устройством:

auto serialInfo = QSerialPortInfo::availablePorts();
serialPort->setPort(serialInfo[0]) 
auto ret = serialPort.open(QSerialPort::ReadWrite)
        && serialPort.setBaudRate(QSerialPort::Baud38400)
        && serialPort.setDataBits(QSerialPort::Data8)
        && serialPort.setStopBits(QSerialPort::OneStop)
        && serialPort.setParity(QSerialPort::NoParity);
qDebug() << "Port has been configured properly?: " << ret;

Если проблема не устранена, вы можете получить собственный обработчик и изменить его свойства, вызвав QSerailPort::handle().

Если платформа поддерживается и последовательный порт открыт, возвращает дескриптор собственного последовательного порта; в противном случае возвращает -1.

Последний вариант, он работает не на всех платформах. В худшем случае посмотрите официальные документы termios . Он обеспечивает низкоуровневый интерфейс, который позволяет включать / отключать режим эха.

struct termios options;
tcgetattr(file, &options);
cfmakeraw(&options);
options.c_lflag &= ~(ECHO | ECHOE); // Add or disable the flags
tcsetattr(file, TCSANOW, &options);
...