天天看點

Qt序列槽助手相關程式含源碼

        免費安裝包與源碼檔案在文末

        Qt creater平台為我們提供了序列槽類,直接調用現成的類方法就可以實作序列槽功能。我建立了一個繼承QSerialPort的子類Serial,這樣友善調用序列槽方法。

// 引入下面兩個序列槽相關類
#include <QSerialPort>
#include <QSerialPortInfo>

class Serial : public QSerialPort
{
public:
    explicit Serial();
};
           

現将主要程式代碼介紹一下。

1.序列槽掃描函數

QStringList Serial::serialScan(void)
{
    QStringList serialPortList;

    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        this->setPort(info);
        // 若目前序列槽被打開則隻添加到清單不關閉 防止已打開序列槽時被強制關閉
        if(this->open(QIODevice::NotOpen)) {
            serialPortList.append(this->portName());
            this->close();
        } else {
            serialPortList.append(this->portName());
        }
    }
    return serialPortList;
}
           

 細心的小夥伴可能發現了上面序列槽掃描函數中不含有判斷目前序列槽是否可被讀寫的代碼↓↓↓

if(this->open(QIODevice::ReadWrite)) { xxx; }
           

将這個判斷删去是因為當我們要定時重新整理序列槽的話,此判斷會使界面卡頓,是以删去

2.序列槽打開函數

bool Serial::serialOpen(QString serialName, int baudRate)
{
    this->setPortName(serialName);
    if(this->open(QIODevice::ReadWrite)) {
        this->setBaudRate(baudRate);
        this->setDataBits(QSerialPort::Data8); //這裡是預設了資料位為8位,可改為上面傳參的方式
        this->setParity(QSerialPort::NoParity); //同上
        this->setStopBits(QSerialPort::OneStop); //同上
        this->setFlowControl(QSerialPort::NoFlowControl);
        // 下位機發送資料會響應這個槽函數
        connect(this, &QSerialPort::readyRead, this, &Serial::readData);
        // 下位機發送資料會觸發這個信号 給主界面處理資料使用
        connect(this, &QSerialPort::readyRead, this, &Serial::readSignal);
        return true;
    }
    return false;
}
           

3.讀資料/寫資料/關閉序列槽函數

// 讀資料
void Serial::readData()
{
    dataBuf = this->readAll(); // 将讀到的資料放到資料緩存區
}
// 寫資料
void Serial::sendData(QByteArray sendData)
{
    this->write(sendData);
}
// 關閉序列槽
void Serial::serialClose()
{
    this->clear();
    this->close();
}
           

4.序列槽資料接收顯示函數

void Page_one::receiveDate(void)
{
    // ASCII顯示是否選中
    if(receive_ASCII->checkState() == Qt::Checked) {
        // 停止顯示是否選中
        if(receive_stop->checkState() == Qt::Unchecked) {
            // 日志模式是否選中
            if(receive_diary->checkState() == Qt::Checked) {
                // 資料緩存區是否為空
                if(serial_main->dataBuf.isNull() == false) {
                    // 擷取目前時間
                    this->getCurrentTime();
                    dateBufTemp += currentTimer;
                    // QByteArray轉QString
                    dateBufTemp += tc->toUnicode(serial_main->dataBuf) + "\n";  // 轉中文
                    text_receive->setText(dateBufTemp);
                }
            } else {
                dateBufTemp += tc->toUnicode(serial_main->dataBuf);  // 轉中文
                text_receive->setText(dateBufTemp);
            }
        }
    } else if(receive_HEX->checkState() == Qt::Checked) {
        if(receive_stop->checkState() == Qt::Unchecked) {
            if(receive_diary->checkState() == Qt::Checked) {
                if(serial_main->dataBuf.isNull() == false) {
                    // 擷取目前時間
                    this->getCurrentTime();
                    dateBufTemp += currentTimer;
                    // 轉大寫16進制,空格隔開
                    dateBufTemp += QString(serial_main->dataBuf.toHex(' ')).toUpper() + "\n";
                    text_receive->setText(dateBufTemp);
                }
            } else {
                // 轉大寫16進制,空格隔開
                dateBufTemp += QString(serial_main->dataBuf.toHex(' ')).toUpper() + " ";
                text_receive->setText(dateBufTemp);
            }
        }
    }
}
           

5.發送資料函數

void Page_one::transmitDate(void)
{
    if(transmit_ASCII->checkState() == Qt::Checked) {
        QByteArray transmitDataTemp;
        if(transmit_newLine->checkState() == Qt::Checked) {
            // 将擷取的文本内容轉換為QByteArray類型
            transmitDataTemp = tc->fromUnicode(text_transmit->toPlainText() + "\n");
        } else {
            transmitDataTemp = tc->fromUnicode(text_transmit->toPlainText());
        }
        serial_main->sendData(transmitDataTemp);
    } else if(transmit_HEX->checkState() == Qt::Checked) {
        QByteArray transmitDataTemp;
        if(transmit_newLine->checkState() == Qt::Checked) {
            // 将擷取的文本内容轉換為QByteArray類型後再轉換為16進制并大寫
            transmitDataTemp = QByteArray::fromHex(tc->fromUnicode(text_transmit->toPlainText() + "\n")).toUpper();
        } else {
            transmitDataTemp = QByteArray::fromHex(tc->fromUnicode(text_transmit->toPlainText())).toUpper();
        }
        serial_main->sendData(transmitDataTemp);
    }
}
           

6.序列槽定時更新函數

// 序列槽定時掃描更新
    t2 = new QTimer();
    t2->start(1000);
    connect(t2, &QTimer::timeout, this, [=](){
        serialNameListOld = serialNameList;
        serialNameList = serial_main->serialScan();
        currentPortText = serial_port_C->currentText();
        // 如果上次清單和目前清單不一緻則更新端口清單
        if(serialNameListOld != serialNameList) {
            serial_port_C->clear();
            serial_port_C->addItems(serialNameList);
            serial_port_C->setCurrentText(currentPortText);
        }
        // 打開序列槽時序列槽變化 如果處于打開狀态的端口被拔出則重置序列槽狀态
        if(!serial_ONOFF_P_flag) {
            if((serial_port_C->currentText() == "") || (serial_port_C->currentText() != currentPort)) {
                serial_ONOFF_P->setText("打開序列槽");
                serial_ONOFF_L->setPixmap(QPixmap(":/IMG/OFF.png"));
                serial_ONOFF_P_flag = true;
                QMessageBox::about(this, "錯誤提示", "目前序列槽已關閉");
                serial_main->close();
            }
        }
    });
           

最終的樣子就是這樣的,基本功能也已經實作,測試能用

普通版:

Qt序列槽助手相關程式含源碼

UI版:

Qt序列槽助手相關程式含源碼

 最後将序列槽助手的安裝包和源碼給大家使用和參考:

普通版安裝包:https://download.csdn.net/download/m0_50669075/20821190

普通版源碼:https://download.csdn.net/download/m0_50669075/20821174

UI版安裝包:https://download.csdn.net/download/m0_50669075/21789587

UI版源碼:https://download.csdn.net/download/m0_50669075/21789600

繼續閱讀