Qt QSerialPort 读写

Posted

技术标签:

【中文标题】Qt QSerialPort 读写【英文标题】:Qt QSerialPort Read Write 【发布时间】:2019-04-01 06:42:07 【问题描述】:

我在读写 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();

【问题讨论】:

您的客户端是否处于回显模式或者您是否连接了 RX 和 TX? 我已经连接了 RX 和 TX @user6556709 @user6556709 我也试过用另一个软件写数据,它工作得很好,没有收到我写的东西。我在 serialPort 上做错了吗? 您很可能不需要调用flush,但这应该没有什么区别。连接我的意思是你把RX和TX连接起来了吗? (这将导致回声。)。 QSerialPort 本身不支持回显模式(您没有激活或停用它的标志),但您可以在操作系统中设置回显模式。也许它就在那里。 No rx is not connected to tx) ,我使用的是Windows 10,回显模式设置可以在哪里?? @user6556709 【参考方案1】:

首先,尝试连接从端口读取/写入时发出的不同信号。

例如检查数据是否已正确发送,根据文档您可以使用信号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);

【讨论】:

感谢您的回答。你给了我实现一些功能的好主意,但我发现问题出在另一个愚蠢的事情上。另一个设备通过“OneStop”停止位连接到串行端口,而我用“TwoStop”连接,我纠正了它并且回声已经停止。 @mohabouje 太棒了!设置该属性时 Qt 是否返回 false? @HrantNurijanyan【参考方案2】:

问题出在

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

另一台设备使用QSerialPort::StopBits::OneStop 连接到串行端口。 所以改变停止位serialPort-&gt;setStopBits(QSerialPort::StopBits::OneStop); 解决了问题,没有回声了。谢谢。

【讨论】:

以上是关于Qt QSerialPort 读写的主要内容,如果未能解决你的问题,请参考以下文章

Qt入门教程硬件编程QSerialPort串口对象

读写串口 类QSerialPort

Qt4安装使用QSerialPort

Qt5 串口类QSerialPort

Qt5 串口类QSerialPort

定时扫描串口看设备是不是连接在QT、QSerialPort