当前位置:   article > 正文

Qt|串口通信之同步数据收一包发一包数据_qt串口通信的接收与发送

qt串口通信的接收与发送

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();
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

串口通信头文件:

#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;
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

串口通信实现类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;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/132972?site
推荐阅读
相关标签
  

闽ICP备14008679号