Qt windows串列埠通訊
阿新 • • 發佈:2020-12-08
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; }