Qt windows串口通讯
Qt 串口通信SerialServer
源代码
serialserver.h
#ifndef SERIALSERVER_H
#define SERIALSERVER_H
#include <QObject>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QMessageBox>
#include <QDebug>
#include <QTimer>
class SerialServer : public QObject
{
Q_OBJECT
public:
enum SerialStatus{
connect = 0x01,
disconnect = 0x02
};
explicit SerialServer(QObject *parent = nullptr);
QStringList getAvailableSerialPort();
bool connectToDevice(QString portName);
void close();
bool serialGetResp(const QByteArray sendData,QByteArray *respData,int timeout);
private slots:
void serialRead();
void recvTimerTimeOut(void);
signals:
void serialStatusChanged(SerialStatus status);
void serialErrorOccur(QString errorMsg);
private:
QSerialPort *m_serial;
QTimer *m_serialRecvTimer;
QByteArray serialDataCache;
QByteArray serialFrameData;
bool newFrameDataRecv = false;
QString errorMsg;
QString getPortName(int index, QString keyorvalue);
QStringList availableSerialPortName;
};
#endif // SERIALSERVER_H
serialserver.cpp
#include "serialserver.h"
#include <QSettings>
#include <QTime>
#include <QCoreApplication>
#include <qt_windows.h>
SerialServer::SerialServer(QObject *parent) : QObject(parent)
{
m_serial = new QSerialPort(this);
m_serialRecvTimer = new QTimer(this);
QObject::connect(m_serial,SIGNAL(readyRead()),this,SLOT(serialRead()));
QObject::connect(m_serialRecvTimer,SIGNAL(timeout()),SLOT(recvTimerTimeOut()));
QObject::connect(m_serial,&QSerialPort::errorOccurred,[=](QSerialPort::SerialPortError error){
if(error == QSerialPort::SerialPortError::NoError) return ;
QString errMsg;
switch(error){
case QSerialPort::SerialPortError::DeviceNotFoundError :errMsg=tr("设备不存在");break;//PermissionError
case QSerialPort::SerialPortError::PermissionError :errMsg=tr("设备连接出错:已有其他软件连接该设备");break;
case QSerialPort::SerialPortError::OpenError :errMsg=tr("设备打开出错。");break;
case QSerialPort::SerialPortError::WriteError :errMsg=tr("设备通信写入发生错误,串口已关闭");break;
case QSerialPort::SerialPortError::ReadError :errMsg=tr("设备通信读取发生错误,串口已关闭");break;
case QSerialPort::SerialPortError::ResourceError :errMsg=tr("设备已拔出,串口已关闭");break;
default :errMsg = tr("未知错误:错误码")+QString::number(error);break;
}
this->errorMsg = errMsg;
m_serial->clearError();
this->close();
QMessageBox::information(NULL,"ERROR",errMsg);
});
}
bool SerialServer::serialGetResp(const QByteArray sendData, QByteArray *respData, int timeout)
{
if(!m_serial->isOpen()){
QMessageBox::information(NULL,"info","设备未连接");
return false;
}
serialDataCache.clear();
newFrameDataRecv = false;
this->m_serial->write(sendData);
QTime dieTime = QTime::currentTime().addMSecs(timeout);
while(QTime::currentTime()<dieTime){
QCoreApplication::processEvents(QEventLoop::AllEvents,100);
if(newFrameDataRecv == true){
respData->append(serialFrameData);
return true;
}
}
return false;
}
bool SerialServer::connectToDevice(QString portName)
{
if(m_serial->isOpen()) return false;
if(!availableSerialPortName.contains(portName)){
QMessageBox::information(NULL,"ERROR","串口打开错误,当前串口已被其他设备占用");
return false;
}
m_serial->setPortName(portName);
m_serial->setBaudRate(QSerialPort::Baud9600);
m_serial->setDataBits(QSerialPort::Data8);
m_serial->setParity(QSerialPort::Parity::NoParity);
m_serial->setStopBits(QSerialPort::StopBits::OneStop);
m_serial->setFlowControl(QSerialPort::NoFlowControl);
if(m_serial->open(QIODevice::ReadWrite)==true){
emit serialStatusChanged(SerialStatus::connect);
return true;
}else{
return false;
}
}
void SerialServer::close()
{
if(m_serial->isOpen()){
m_serial->clear();
m_serial->close();
emit serialStatusChanged(SerialStatus::disconnect);
}
}
void SerialServer::serialRead()
{
serialDataCache.append(m_serial->readAll());
m_serialRecvTimer->stop();
m_serialRecvTimer->start(100);
m_serialRecvTimer->setSingleShot(true);
}
void SerialServer::recvTimerTimeOut()
{
serialFrameData = serialDataCache;
serialDataCache.clear();
newFrameDataRecv = true;
}
QStringList SerialServer::getAvailableSerialPort()
{
QStringList availablePortName;
if(m_serial->isOpen()){
this->close();
}
if(m_serial != NULL){
QString path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM";
QSettings *settings = new QSettings(path, QSettings::NativeFormat);
QStringList key = settings->allKeys();
for(int i = 0;i<key.size();i++){
QString key = getPortName(i,"key");
QString value = getPortName(i,"value");
availablePortName<<value;
}
}
availableSerialPortName = availablePortName;
return availablePortName;
}
QString SerialServer::getPortName(int index, QString keyorvalue)
{
QString commresult;
HKEY hKey;
wchar_t keyname[256]; //键名数组
char keyvalue[256]; //键值数组
DWORD keysize,type,valuesize;
if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_READ, &hKey) != 0) {
QString error="Cannot open regedit!"; //无法打开注册表时返回error
return error;
}
QString keymessage;//键名
QString message;
QString valuemessage;//键值
keysize = sizeof(keyname);
valuesize = sizeof(keyvalue);
if (RegEnumValue(hKey, index, keyname, &keysize, 0, &type, (BYTE*)keyvalue, &valuesize) == 0) { //列举键名和值
for (int i=0; i<(int)keysize; i++) {
message = keyname[i];
keymessage.append(message);
}
for (int j=0; j<(int)valuesize; j++) {
if (keyvalue[j] != 0x00) {
valuemessage.append(keyvalue[j]);
}
}
if (keyorvalue == "key") {
commresult = keymessage;
}
if (keyorvalue == "value") {
commresult=valuemessage;
}
} else {
commresult = "nokey";
}
RegCloseKey(hKey);//关闭注册表
return commresult;
}

浙公网安备 33010602011771号