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

posted @ 2020-12-08 20:45  chunchun_studio  阅读(537)  评论(0)    收藏  举报