數(shù)據(jù)源是組態(tài)軟件的核心靈魂,少了數(shù)據(jù)源,組態(tài)就是個(gè)花架子沒卵用,一般數(shù)據(jù)源有三種方式獲取,串口、網(wǎng)絡(luò)、數(shù)據(jù)庫,至于數(shù)據(jù)規(guī)則是什么,這個(gè)用戶自己指定,本設(shè)計(jì)器全部采用第一個(gè)字節(jié)作為數(shù)據(jù)來演示。
串口通信在大量的工業(yè)控制領(lǐng)域用的最多,就因?yàn)榉€(wěn)定兩個(gè)字,長(zhǎng)期霸占了幾十年的通信規(guī)則,現(xiàn)在還有大量的工業(yè)控制設(shè)備使用的就是串口通信,Qt5以后封裝了串口通信的類,不過據(jù)說不大好用,也不大穩(wěn)定,本人在早期的Qt版本比如Qt5.3時(shí)代用過幾次,是有點(diǎn)莫名其妙的問題,后面索性就不在用自帶的了,而是用的第三方開源的qextserialport,主要還是因?yàn)楸救俗鲞^的硬件設(shè)備上面大量的還是Qt4.8的Qt版本,沒法用Qt5,還沒升級(jí)到Qt5可能也是考慮到穩(wěn)定性的原因。
1. 自動(dòng)加載插件文件中的所有控件生成列表,默認(rèn)自帶的控件超過120個(gè)。
2. 拖曳到畫布自動(dòng)生成對(duì)應(yīng)的控件,所見即所得。
3. 右側(cè)中文屬性欄,改變對(duì)應(yīng)的屬性立即應(yīng)用到對(duì)應(yīng)選中控件,直觀簡(jiǎn)潔,非常適合小白使用。
4. 獨(dú)創(chuàng)屬性欄文字翻譯映射機(jī)制,效率極高,可以非常方便拓展其他語言的屬性欄。
5. 所有控件的屬性自動(dòng)提取并顯示在右側(cè)屬性欄,包括枚舉值下拉框等。
6. 支持手動(dòng)選擇插件文件,外部導(dǎo)入插件文件。
7. 可以將當(dāng)前畫布的所有控件配置信息導(dǎo)出到xml文件。
8. 可以手動(dòng)選擇xml文件打開控件布局,自動(dòng)根據(jù)xml文件加載控件。
9. 可拉動(dòng)滑動(dòng)條、勾選模擬數(shù)據(jù)復(fù)選框、文本框輸入,三種方式來生成數(shù)據(jù)應(yīng)用所有控件。
10. 控件支持八個(gè)方位拉動(dòng)調(diào)整大小,自適應(yīng)任意分辨率,可鍵盤上下左右微調(diào)位置。
11. 打通了串口采集、網(wǎng)絡(luò)采集、數(shù)據(jù)庫采集三種方式設(shè)置數(shù)據(jù)。
12. 代碼極其精簡(jiǎn),注釋非常詳細(xì),可以作為組態(tài)的雛形,自行拓展更多的功能。
13. 純Qt編寫,支持任意Qt版本+任意編譯器+任意系統(tǒng)。
void frmData::initServer() { //實(shí)例化串口類,綁定信號(hào)槽 com=new QextSerialPort(QextSerialPort::EventDriven, this); connect(com, SIGNAL(readyRead()), this, SLOT(readDataCom())); //實(shí)例化網(wǎng)絡(luò)通信客戶端類,綁定信號(hào)槽 tcpClient=new QTcpSocket(this); connect(tcpClient, SIGNAL(readyRead()), this, SLOT(readDataClient())); //實(shí)例化網(wǎng)絡(luò)通信服務(wù)端類,綁定信號(hào)槽 tcpSocket=NULL; tcpServer=new QTcpServer(this); connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); //開啟定時(shí)器讀取數(shù)據(jù)庫采集數(shù)據(jù) timer=new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(readDataDb())); timer->setInterval(1000); } void frmData::on_btnOpenCom_clicked() { if (ui->btnOpenCom->text()=="打開") { com->setPortName(App::PortName); bool ok=com->open(QIODevice::ReadWrite); if (ok) { com->setBaudRate((BaudRateType)App::BaudRate); setEnable(ui->btnOpenCom, false); ui->btnOpenCom->setText("關(guān)閉"); } } else { com->close(); setEnable(ui->btnOpenCom, true); ui->btnOpenCom->setText("打開"); } } void frmData::readDataCom() { QByteArray data=com->readAll(); if (data.length() <=0) { return; } //默認(rèn)取第一個(gè)字節(jié)解析,可以自行更改 quint8 value=data.at(0); ui->txtValue->setText(QString::number(value)); append(1, data.toHex()); }
1. 超過150個(gè)精美控件,涵蓋了各種儀表盤、進(jìn)度條、進(jìn)度球、指南針、曲線圖、標(biāo)尺、溫度計(jì)、導(dǎo)航條、導(dǎo)航欄,flatui、高亮按鈕、滑動(dòng)選擇器、農(nóng)歷等。遠(yuǎn)超qwt集成的控件數(shù)量。
2. 每個(gè)類都可以獨(dú)立成一個(gè)單獨(dú)的控件,零耦合,每個(gè)控件一個(gè)頭文件和一個(gè)實(shí)現(xiàn)文件,不依賴其他文件,方便單個(gè)控件以源碼形式集成到項(xiàng)目中,較少代碼量。qwt的控件類環(huán)環(huán)相扣,高度耦合,想要使用其中一個(gè)控件,必須包含所有的代碼。
3. 全部純Qt編寫,QWidget+QPainter繪制,支持Qt4.6到Qt5.12的任何Qt版本,支持mingw、msvc、gcc等編譯器,支持任意操作系統(tǒng)比如windows+linux+mac+嵌入式linux等,不亂碼,可直接集成到Qt Creator中,和自帶的控件一樣使用,大部分效果只要設(shè)置幾個(gè)屬性即可,極為方便。
4. 每個(gè)控件都有一個(gè)對(duì)應(yīng)的單獨(dú)的包含該控件源碼的DEMO,方便參考使用。同時(shí)還提供一個(gè)所有控件使用的集成的DEMO。
5. 每個(gè)控件的源代碼都有詳細(xì)中文注釋,都按照統(tǒng)一設(shè)計(jì)規(guī)范編寫,方便學(xué)習(xí)自定義控件的編寫。
6. 每個(gè)控件默認(rèn)配色和demo對(duì)應(yīng)的配色都非常精美。
7. 超過130個(gè)可見控件,6個(gè)不可見控件。
8. 部分控件提供多種樣式風(fēng)格選擇,多種指示器樣式選擇。
9. 所有控件自適應(yīng)窗體拉伸變化。
10. 集成自定義控件屬性設(shè)計(jì)器,支持拖曳設(shè)計(jì),所見即所得,支持導(dǎo)入導(dǎo)出xml格式。
11. 自帶activex控件demo,所有控件可以直接運(yùn)行在ie瀏覽器中。
12. 集成fontawesome圖形字體+阿里巴巴iconfont收藏的幾百個(gè)圖形字體,享受圖形字體帶來的樂趣。
13. 所有控件最后生成一個(gè)動(dòng)態(tài)庫文件(dll或者so等),可以直接集成到qtcreator中拖曳設(shè)計(jì)使用。
14. 目前已經(jīng)有qml版本,后期會(huì)考慮出pyqt版本,如果用戶需求量很大的話。
15. 自定義控件插件開放動(dòng)態(tài)庫使用(永久免費(fèi)),無任何后門和限制,請(qǐng)放心使用。
16. 目前已提供26個(gè)版本的dll,其中包括了qt5.12.3 msvc2017 32+64 mingw 32+64 的。
17. 不定期增加控件和完善控件,不定期更新SDK,歡迎各位提出建議,謝謝!
18. Qt入門書籍推薦霍亞飛的《Qt Creator快速入門》《Qt5編程入門》,Qt進(jìn)階書籍推薦官方的《C++ GUI Qt4編程》。
19. 強(qiáng)烈推薦程序員自我修養(yǎng)和規(guī)劃系列書《大話程序員》《程序員的成長(zhǎng)課》《解憂程序員》,受益匪淺,受益終生!
最近在學(xué)習(xí)qt,邊學(xué)邊寫,最近自己寫了個(gè)串口調(diào)試助手和網(wǎng)絡(luò)調(diào)試助手,在此做個(gè)串口調(diào)試助手開發(fā)的分享和記錄。
主要功能:串口數(shù)據(jù)收發(fā)、顯示,定時(shí)發(fā)送,接收數(shù)據(jù)保存、文件發(fā)送,定時(shí)更新串口列表和異常檢測(cè),不同編碼、進(jìn)制轉(zhuǎn)換等。
QT實(shí)現(xiàn)串口通信主要是利用QT自帶的串口類和函數(shù),在.pro文件中添加"QT +=serialport",然后在項(xiàng)目文件中包含頭文件(#include QSerialport),我們就可以在項(xiàng)目中使用QSerialPort來讀取和發(fā)送串口數(shù)據(jù)了。
主要過程:實(shí)例化串口——>搜索可用串口——>打開串口——>設(shè)置串口參數(shù)——>讀取數(shù)據(jù)或發(fā)送數(shù)據(jù)。
新建串口調(diào)試助手的項(xiàng)目,由于QT還沒玩熟,這里就直接使用QT Designer進(jìn)行ui界面的繪制和布局。布局過程不再贅述,根據(jù)自己的需要放置適當(dāng)?shù)目丶纯桑詈脤?duì)控件對(duì)象也重命名一下,完成布局后的最終效果如圖:
下面對(duì)主要的幾個(gè)過程和程序做個(gè)說明,具體過程就不再貼出來了,了解大概過程后就可以根據(jù)個(gè)人需要來新增其他功能了。
1、 首先對(duì)界面的按鈕、組合選擇框等控件進(jìn)行一些初始化(更改背景、顏色這些也可以直接通過QT Designer ui界面右鍵點(diǎn)擊控件,通過“改變樣式表”等來設(shè)置)。
2、實(shí)例化對(duì)象,關(guān)聯(lián)一些信號(hào)和槽信號(hào)。在這里,我們使用foreach函數(shù)來搜索和解析目前該P(yáng)C上可用的端口信息,然后把解析出來的端口添加到組合選擇框里面,后面就可以去從下拉框選擇要打開的串口了。主要代碼如下:
//查找可用的串口
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
QSerialPort SerialPort;
SerialPort.setPort(info); //解析串口信息
if (SerialPort.open(QIODevice::ReadWrite))
{
SerialPortName.push_back(SerialPort.portName());
SerialPort.close();
}
}
//把端口添加到組合框
for (int i=0; i < SerialPortName.size(); ++i)
{
ui->SelectCOM_comboBox>addItem(SerialPortName.at(i));
}
3、打開和設(shè)置串口
在這里,我使用點(diǎn)擊按鈕來觸發(fā)打開串口事件,在打開按鈕的槽函數(shù)中進(jìn)行串口打開就可以。打開以后進(jìn)行串口參數(shù)的設(shè)置,如波特率、校驗(yàn)位、停止位等。這些參數(shù)從界面的設(shè)置讀取,這里給出主要代碼,參數(shù)直接指定,從窗口獲取參數(shù)也是同理,只是需要從ui界面獲取參數(shù)。
** 這里要注意:務(wù)必要先打開串口,然后在進(jìn)行參數(shù)設(shè)置,否則很有可能出現(xiàn)讀取不到數(shù)據(jù)的情況。(很明顯的特征就是,串口設(shè)備拔掉插上,打開串口也讀不到數(shù)據(jù)或者亂碼,拿其他軟件打開讀一下數(shù)據(jù),再切回自己的程序也就可以讀到數(shù)據(jù))。**
SerialPort->setPortName(SelectCOM_comboBox->currentText()); //獲取串口端口號(hào)
if(!(SerialPort->isOpen())) //串口沒有打開
{
if (!SerialPort->open(QIODevice::ReadWrite))
{
QMessageBox::information(this, "提示", "串口連接失敗,請(qǐng)檢查設(shè)備是否正確連接");
}
else
{
//QMessageBox::information(this, "提示", SelectCOM_comboBox->currentText() + tr("連接成功"));
SerialPort->setBaudRate(115200); //設(shè)置波特率115200
SerialPort->setDataBits(QSerialPort::Data8); //8位數(shù)據(jù)位
SerialPort->setParity(QSerialPort::NoParity); //無校驗(yàn)位
SerialPort->setStopBits(QSerialPort::OneStop); //1位停止位
SerialPort->setFlowControl(QSerialPort::NoFlowControl); //默認(rèn)無流控
SerialPort->clearError();
SerialPort->clear();
//關(guān)聯(lián)串口數(shù)據(jù)讀取槽函數(shù)
connect(SerialPort, &QSerialPort::readyRead, this, &setDialog::slot_serialReadData);
//關(guān)聯(lián)串口連接異常處理槽函數(shù)
connect(SerialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error), this, &setDialog::handleSerialError);
}
}
4 、讀取數(shù)據(jù)
串口有數(shù)據(jù)發(fā)過來時(shí)會(huì)觸發(fā)串口讀信號(hào)(readyRead),所以讀數(shù)據(jù)就要將readyRead綁定到讀取槽函數(shù),然后直接使用串口的readAll()或者readData()等函數(shù)來讀取串口數(shù)據(jù)就可以,讀到的數(shù)據(jù)根據(jù)需要進(jìn)行轉(zhuǎn)碼,然后進(jìn)行顯示、保存等操作。主要代碼如下:
綁定信號(hào)和槽:connect(SerialPort, &QSerialPort::readyRead, this, &setDialog::slot_serialReadData);
QByteArray receiveDate;
QTextCodec *tc=QTextCodec::codecForName("GBK"); //編碼轉(zhuǎn)換,必須轉(zhuǎn)換編碼,否則亂碼
while(!SerialPort->atEnd()){
receiveDate=SerialPort->readAll();
}
if (!receiveDate.isEmpty())
{
QString strBuf=tc->toUnicode(receiveDate); //編碼轉(zhuǎn)換,必須轉(zhuǎn)換編碼,否則亂碼
COMRXtextBrowser->append(strBuf);
}
receiveDate.clear();
5、發(fā)送數(shù)據(jù)
要發(fā)送串口數(shù)據(jù)也很簡(jiǎn)單,使用write()函數(shù)即可,前提是串口要先打開和設(shè)置好參數(shù)。下面是主要代碼:
QTextCodec *gbk=QTextCodec::codecForName("GBK");
//從Ui文本輸入框讀取數(shù)據(jù)
QString strSendMessage=ui->Send_textEdit->toPlainText();
if(ui->TXHex_checkBox->isChecked())
{
strSendMessage=hexToString(strSendMessage); //hex格式轉(zhuǎn)化為Qstring
}
if(ui->TXEnter_checkBox->isChecked()) //添加換行/回車
{
strSendMessage+="\r\n";
}
QByteArray sendBytes;
sendBytes.append(gbk->fromUnicode(strSendMessage)); //編碼轉(zhuǎn)換,必須轉(zhuǎn)換編碼,否則亂碼
if(SerialPort->isWritable())
{
SerialPort->write(sendBytes);
TXCounter+=sendBytes.size();
ui->TXCountlabel->setText(tr("TX:%1").arg(TXCounter));
}
else{
QMessageBox::information(this,"Tip","串口未打開!");
}
6、 關(guān)閉串口
關(guān)閉串口可以手動(dòng)通過點(diǎn)擊按鈕關(guān)閉或者在窗口關(guān)閉時(shí)去關(guān)閉串口,為避免出現(xiàn)異常,窗口關(guān)閉時(shí)把串口也關(guān)閉了。關(guān)閉串口也很簡(jiǎn)單,使用close()函數(shù)就可以。代碼如下:
if(SerialPort->isOpen())
{
SerialPort->close();
ui->SeralOperat_pushButton->setText(tr("打開串口"));
QMessageBox::information(this,"提示","串口連接斷開");
}
7、其他
串口還有很多功能,這里就不一一列舉,需要可以去QT助手搜索有哪些方法,如何使用等。
最終實(shí)現(xiàn)效果如圖:
1、在工程文件.pro中要添加QT +=serialport,否則編譯會(huì)報(bào)錯(cuò)
2、串口要先打開,然后進(jìn)行參數(shù)設(shè)置,否則容易出現(xiàn)讀取不到數(shù)據(jù)的情況
3、 串口數(shù)據(jù)讀取的數(shù)據(jù)需要進(jìn)行轉(zhuǎn)碼(尤其是和硬件平臺(tái)通信時(shí)),否則中文字符會(huì)亂碼
4、在對(duì)ui控件進(jìn)行操作前,務(wù)必要先執(zhí)行設(shè)置ui函數(shù)(ui->setupUi(this)),否則執(zhí)行會(huì)出錯(cuò)。
寫的調(diào)試軟件還有定時(shí)更新串口列表,保存接收數(shù)據(jù),發(fā)送文件,定時(shí)發(fā)送等功能,在此不一一詳述了。我把完整源碼奉上,需要參考的伙伴可以直接下載源碼,注釋寫的也很清楚。
源碼請(qǐng)?jiān)谫Y源頁下載:
https://mp-new.csdn.net/mp_download/manage/download/UpDetailed
關(guān)于如何把自己寫的程序打包成軟件,請(qǐng)參考:
https://mp-new.csdn.net/mp_blog/creation/editor/116641563
本人也是剛學(xué)習(xí)QT,歡迎大家交流、留下寶貴意見。