当前位置:   article > 正文

Qt6串口通信(实时接收数据、刷新串口号)_qt串口通信代码

qt串口通信代码

目录

一、打开串口

二、发送数据

三、接收数据

四、关闭串口


串口通信大致分为四个部分:打开串口、发送数据、接收数据、关闭串口,总的来说并不难,本文是结合qml界面实现完整功能,以下是部分代码:

CMake:

  1. find_package(Qt6 REQUIRED COMPONENTS SerialPort)
  2. target_link_libraries(mytarget PRIVATE Qt6::SerialPort)

qmake:

 QT += serialport

一、打开串口

  1. //连接串口
  2. bool SerialPort::connectSerial(QString port)
  3. {
  4. qint32 baud_rate = 9600; //自定义波特率
  5. m_serial.setPortName(port); //设置串口名称
  6. m_serial.setBaudRate(baud_rate); //设置波特率
  7. m_serial.setDataBits(QSerialPort::Data8); //设置数据位8
  8. m_serial.setParity(QSerialPort::NoParity); //校验位设置为0
  9. m_serial.setStopBits(QSerialPort::OneStop); //停止位设置为1
  10. m_serial.setFlowControl(QSerialPort::NoFlowControl); //设置为无流控制
  11. m_serial.setReadBufferSize(1); //设置内部读缓冲区的大小(如果不设置默认最大是4096字节)
  12. if(!m_serial.open(QIODevice::ReadWrite))
  13. {
  14. qDebug() << "Serial port open error!";
  15. return false;
  16. }
  17. qDebug() << "Serial port open success!";
  18. return true;
  19. }

注意:

1.函数传参port为需要打开的串口号,用一个下拉框接收识别到的所有串口号并实时刷新,参考如下代码:

新建一个serialportmanager.h文件

  1. #ifndef SERIALPORTMANAGER_H
  2. #define SERIALPORTMANAGER_H
  3. #include <QObject>
  4. #include <QSerialPortInfo>
  5. #include <QTimer>
  6. class SerialPortManager : public QObject
  7. {
  8. Q_OBJECT
  9. Q_PROPERTY(QStringList availablePorts READ availablePorts NOTIFY availablePortsChanged)
  10. public:
  11. explicit SerialPortManager(QObject *parent = nullptr) : QObject(parent)
  12. {
  13. updateAvailablePorts();
  14. // 定期检查可用串口列表
  15. m_timer.setInterval(1000); // 每秒检查一次
  16. connect(&m_timer, &QTimer::timeout, this, &SerialPortManager::updateAvailablePorts);
  17. m_timer.start();
  18. }
  19. QStringList availablePorts() const
  20. {
  21. return m_availablePorts;
  22. }
  23. signals:
  24. void availablePortsChanged();
  25. private:
  26. void updateAvailablePorts()
  27. {
  28. m_availablePorts.clear();
  29. const QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
  30. for (const QSerialPortInfo &portInfo : ports) {
  31. m_availablePorts.append(portInfo.portName());
  32. }
  33. emit availablePortsChanged();
  34. }
  35. private:
  36. QStringList m_availablePorts;
  37. QTimer m_timer;
  38. };
  39. #endif // SERIALPORTMANAGER_H

在main.cpp里实例化

  1. #include <QApplication>
  2. #include <QQmlApplicationEngine>
  3. #include <QQmlContext>
  4. #include "serialport.h"
  5. #include "serialportmanager.h"
  6. ...
  7. ...
  8. ...
  9. QQmlApplicationEngine engine;
  10. SerialPortManager serialPortManager;
  11. engine.rootContext()->setContextProperty("SerialPortManager", &serialPortManager);

qml的下拉框代码

  1. import QtCharts 2.15
  2. ...
  3. //串口下拉框
  4. ComboBox{
  5. id: portComboBox
  6. width: 80
  7. height: 40
  8. font.family: "楷体"
  9. model: SerialPortManager.availablePorts
  10. //设置默认选中的串口号
  11. onModelChanged: {
  12. if (SerialPortManager.availablePorts.length > 0)
  13. currentIndex = 0;
  14. }
  15. // 更新串口列表槽函数
  16. Connections {
  17. target: SerialPortManager
  18. function onAvailablePortsChanged() {
  19. // 更新串口列表
  20. portComboBox.model = SerialPortManager.availablePorts;
  21. }
  22. }
  23. }

2.m_serial.setReadBufferSize(1)设置内部读缓冲区的大小,一般不需要设置,在下面实时接收数据再详细解释这里为什么设置成1;

二、发送数据

  1. //串口发送
  2. void SerialPort::sendData()
  3. {
  4. // 构造协议数据
  5. QByteArray protocolData;
  6. protocolData.append('\x01');
  7. protocolData.append('\x11');
  8. protocolData.append('\x02');
  9. protocolData.append('\x22');
  10. protocolData.append('\x03');
  11. // 计算并添加异或校验位
  12. quint8 checksum = xorChecksum(protocolData);
  13. protocolData.append(checksum);
  14. // 发送协议数据
  15. qint64 bytesWritten = m_serial.write(protocolData);
  16. if (bytesWritten == -1) {
  17. qDebug() << "Failed to write data to serial port:" << m_serial.errorString();
  18. }
  19. qDebug() << "发送字节数:" << bytesWritten;
  20. }
  21. //计算异或校验位
  22. quint8 SerialPort::xorChecksum(QByteArray processedData)
  23. {
  24. quint8 checksum = 0;
  25. for (int i = 0; i < processedData.size(); ++i) {
  26. checksum ^= processedData.at(i);
  27. }
  28. return checksum;
  29. }

串口发送直接使用write()函数就行,不过串口通信一般需要做校验,以上代码是奇偶校验的一个方法,最终应该会发送一串16进制的数:01 11 02 22 03 33

三、接收数据

在构造函数里建立信号和槽

  1. // 读取串口数据
  2. connect(&m_serial, SIGNAL(readyRead()), this, SLOT(receiveData()));
  1. //接收数据
  2. void SerialPort::receiveData()
  3. {
  4. receivedData.append(m_serial.readAll());
  5. ...
  6. 数据处理
  7. ...
  8. 数据处理完后可以用receivedData.clear()把缓冲区清除
  9. ...
  10. }

如果串口设置了内部读缓冲区的大小为1,即m_serial.setReadBufferSize(1),这样每来一个字节数据就会触发一次readyRead()信号,这个方法对于需要接收一段完整协议来说非常适用。反之,只会触发一次readyRead()信号,readAll()就会把全部数据协议读出来,且最多4096个字节,超出的话会直接丢掉。所以当接收数据量多的时候推荐设置内部读缓冲区大小,这样不但数据不会丢失,而且响应速度也会更快。

四、关闭串口

  1. //关闭串口
  2. void SerialPort::closeSerial()
  3. {
  4. if(m_serial.isOpen())
  5. {
  6. m_serial.close();
  7. }
  8. }

以上就是串口通信的主要部分代码,下面附带一下.h文件给予参考:

  1. #ifndef SERIALPORT_H
  2. #define SERIALPORT_H
  3. #include <QObject>
  4. #include <QDebug>
  5. #include <QCoreApplication>
  6. #include <QSerialPort>
  7. #include <QSerialPortInfo>
  8. #include <QDataStream>
  9. class SerialPort : public QObject
  10. {
  11. Q_OBJECT
  12. public:
  13. explicit SerialPort(QObject *parent = nullptr);
  14. ~SerialPort();
  15. quint8 xorChecksum(QByteArray processedData);
  16. bool connectSerial(QString port);
  17. void sendData();
  18. void closeSerial();
  19. public slots:
  20. void receiveData();
  21. private:
  22. QSerialPort m_serial;
  23. QByteArray receivedData;
  24. };
  25. #endif // SERIALPORT_H
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/132958
推荐阅读
相关标签
  

闽ICP备14008679号