赞
踩
2022.2.14更新:发现打断点调试可以实现数据同步,不打断点收到的数据时序会乱,网上有很多解决方法,因为需求限制,我使用了发送数据后Sleep(200)毫秒对该问题进行了避规。
参考:【Qt】串口通讯
本文只写实现,原理见上方参考连接,搜了很多资料都是异步通信的,需求是需要同步通信,故写此文记录。
需要依赖serialport,如图所示:
运行结果:
ui文件部署:
运行环境win10、vs2015、qt5工程目录结构:
主函数:
#include "SerialCommunication.h" #include <QtWidgets/QApplication> #include <qDebug> int main(int argc, char *argv[]) { QApplication a(argc, argv); SerialCommunication w; // 使用示例 #if 0 QByteArray str; str.append("123"); int data_size = w.PortWrite(str.data(), str.size()); int size = w.PortRead(SerialCommunication::ebpc); if (size == 0) { qDebug()<<("未接收到回复,下发数据失败!"); //return; // 如果收到正确回复继续后续操作,未收到可根据需求中断跳转 } #endif w.show(); return a.exec(); }
串口通信头文件:
#pragma once #include <QtWidgets/QWidget> #include <QSerialPort> #include <memory> #include "ui_SerialCommunication.h" class SerialCommunication : public QWidget { Q_OBJECT public: SerialCommunication(QWidget *parent = Q_NULLPTR); //! 一个串口参数类. /*! 串口相关参数. */ struct Param { QString serialPortName;//! 串口名.串口号 COM1 qint32 baudRate;//! 串口波特率. 115200 QSerialPort::DataBits dataBits;//! 数据位. 8 7 QSerialPort::Parity parity;//! 奇偶位. 校验位 none even odd QSerialPort::StopBits stopBits;//! 停止位. 1 0 }; //! 串口的初始化. void PortInit(); //! 打开串口. bool PortOpen(); //! 关闭串口. bool PortClose(); //! 发送数据. int PortWrite(char* buff, unsigned int length); // 读取数据所需枚举 例子可根据需求自由修改 enum PortReadEnum { ebpc, // 回复OK> sdpc, // 回复OK> lbpc, // 回复C oneData, // 发出一包数据回复 06为正确 }; //! 读取数据. 返回值 1为成功 0为失败 int PortRead(PortReadEnum _read_enum); // signals: // 读取数据信号. // void readyRead(QString str); protected: //! 存储监听的数据. 没有使用监听功能可以根据需求自行修改 //inline void setListenData(QByteArray& data) { m_Data += data; } //! 监听. void PortListen(); //! 清除发送buff. int clearSendBuff(); //! 清除接受buff. int clearRecvBuff(); //! 设置串口参数. int setParam(void* param); private: Ui::SerialCommunicationClass ui; QSharedPointer<QSerialPort> m_pSerialPort; // 串口通信 bool m_isOpen; // 串口通信是否打开 //QByteArray m_Data; };
串口通信实现类cpp:
#include "SerialCommunication.h" #include <QtSerialPort/QSerialPortInfo> #include <qDebug> SerialCommunication::SerialCommunication(QWidget *parent) : QWidget(parent) { ui.setupUi(this); PortInit(); connect(ui.pushButton, &QPushButton::clicked, this, &SerialCommunication::PortOpen); } void SerialCommunication::PortInit() { m_pSerialPort = QSharedPointer<QSerialPort>(new QSerialPort); //获取可以用的串口 QList<QSerialPortInfo> serialPortInfos = QSerialPortInfo::availablePorts(); for (auto one_port : serialPortInfos) { m_pSerialPort->setPort(one_port); // 在对象中设置串口 if (m_pSerialPort->open(QIODevice::ReadWrite)) // 以读写方式打开串口 { ui.serial_port_comboBox->addItem(one_port.portName()); // 添加计算机中的端口 m_pSerialPort->close(); // 关闭 } else { qDebug() << "串口打开失败,请重试"; } } // 根据QSerialPort::NoParity枚举值赋的data ui.check_bit_comboBox->addItem("None", 0); ui.check_bit_comboBox->addItem("Even", 2); ui.check_bit_comboBox->addItem("Odd", 3); } bool SerialCommunication::PortOpen() { if (ui.pushButton->text().compare(QString::fromLocal8Bit("打开串口"))==0) { ui.pushButton->setText(QString::fromLocal8Bit("关闭串口")); } else { PortClose(); ui.pushButton->setText(QString::fromLocal8Bit("打开串口")); return false; } if (m_pSerialPort->isOpen()) { return true; } bool isOpen = m_pSerialPort->open(QIODevice::ReadWrite); m_isOpen = isOpen; std::shared_ptr<Param> p = std::make_shared<Param>(); p->serialPortName = ui.serial_port_comboBox->currentText(); p->baudRate = ui.baud_rate_comboBox->currentText().toInt();//115200; p->dataBits = (QSerialPort::DataBits)ui.data_bits_comboBox->currentText().toInt();//QSerialPort::Data8; p->parity = (QSerialPort::Parity)ui.check_bit_comboBox->currentData().toInt();//QSerialPort::NoParity; p->stopBits = ui.stop_bit_comboBox->currentText().toInt() == 0 ? QSerialPort::UnknownStopBits : QSerialPort::OneStop;//QSerialPort::UnknownStopBits; setParam(p.get()); return isOpen; } bool SerialCommunication::PortClose() { m_pSerialPort->close(); m_isOpen = m_pSerialPort->isOpen(); return !m_pSerialPort->isOpen(); } int SerialCommunication::PortWrite(char* buff, unsigned int length) { int data_size = m_pSerialPort->write(buff, length); m_pSerialPort->waitForBytesWritten(10000); return data_size; } int SerialCommunication::PortRead(PortReadEnum _read_enum) { // 关键代码获取回执消息时等待三面未收到消息自动跳出循环qt自带函数无需自行实现 while (m_pSerialPort->waitForReadyRead(3000)) { QByteArray data = m_pSerialPort->readAll(); if (data.size() <= 0) return 0; switch (_read_enum) { case SerialCommunication::ebpc: case SerialCommunication::sdpc: if (std::strstr(data.data(), "OK>")) return 1; case SerialCommunication::lbpc: if (std::strstr(data.data(), "C")) return 1; case SerialCommunication::oneData: if (data.at(0) == 0x06) return 1; default: return 0; } } return 0; } void SerialCommunication::PortListen() { connect(m_pSerialPort.data(), &QSerialPort::readyRead, this, [&]() { QByteArray data = m_pSerialPort->readAll(); //setListenData(data); //缓存 //emit readyRead(data); //显示 qDebug() << data.data(); //addLogText(data.data()); }); } int SerialCommunication::clearSendBuff() { return m_pSerialPort->clear(QSerialPort::Output); } int SerialCommunication::clearRecvBuff() { return m_pSerialPort->clear(QSerialPort::Input); } int SerialCommunication::setParam(void* param) { Param* p = static_cast<Param*>(param); m_pSerialPort->setPortName(p->serialPortName); m_pSerialPort->setBaudRate(p->baudRate); m_pSerialPort->setDataBits(p->dataBits); m_pSerialPort->setParity(p->parity); m_pSerialPort->setStopBits(p->stopBits); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。