最近幫老師做的項目中使用到了QT串口筒扒,然后首先百度了一下您市,發(fā)現(xiàn)網(wǎng)上的QT串口代碼都是同一個版本。而且沒有公開源代碼,遂自己寫了個簡單的串口通信代碼翘单,并將它公布出來,一方面供有需要的人參考岭埠,另一方面記錄下來脆丁,也可以防止自己忘記了。
本項目沒有用到QT自帶的串口通信模塊稚叹,使用了第三方庫qextserialport焰薄,這個庫基本已經(jīng)滿足了串口所有的功能拿诸,而且上手也快。好了塞茅。廢話不多說了亩码,先來張效果圖吧。
這是整體效果圖野瘦,主要實現(xiàn)的是開發(fā)板和下位機通信描沟,上位機通過串口發(fā)送指令給下位機,下位機再執(zhí)行相應(yīng)的操作鞭光。本文主要講講串口通信的部分吧吏廉。
簡單來說,串口通信分為三部分:1:設(shè)置端口號和波特率等等惰许,數(shù)據(jù)位和校驗之類的一般的可以提前設(shè)定好席覆,再代碼中同樣也可以設(shè)定。2:將數(shù)據(jù)寫入串口汹买,這個時候就要分發(fā)送的是多少進(jìn)制的數(shù)據(jù)了佩伤,雖然計算機在實際存儲時是不區(qū)分進(jìn)制的。3:讀串口數(shù)據(jù)晦毙,將串口接收到的數(shù)據(jù)讀出來生巡,進(jìn)行下一步處理。后面我會把全部代碼貼出來结序,代碼經(jīng)過調(diào)試已經(jīng)可以運行了障斋。本文中具體的控件布局我就不講了,我只講講一些核心的代碼徐鹤,大家感興趣的話可以自己去跑跑我的代碼垃环,代碼中注釋非常詳細(xì),每一行都有注釋返敬,看起來不費勁遂庄。
1.設(shè)置端口和波特率
//打開串口,波特率和端口號可以通過下拉菜單進(jìn)行選擇
void uwiCMonitorPC::on_openMyComBtn_clicked()
{
QString portName = portNameComboBox->currentText(); //獲取串口名
myCom = new Win_QextSerialPort(portName,QextSerialBase::EventDriven);
//定義串口對象劲赠,并傳遞參數(shù)涛目,在構(gòu)造函數(shù)里對其進(jìn)行初始化
myCom ->open(QIODevice::ReadWrite); //打開串口
if(baudRateComboBox->currentText()==tr("38400")) //根據(jù)下拉菜單中內(nèi)容對串口進(jìn)行設(shè)置
//設(shè)置波特率
myCom->setBaudRate(BAUD38400);
else if(baudRateComboBox->currentText()==tr("115200"))
myCom->setBaudRate(BAUD115200);
//設(shè)置數(shù)據(jù)位
myCom->setDataBits(DATA_8);
//設(shè)置奇偶校驗
myCom->setParity(PAR_NONE);
//設(shè)置停止位
myCom->setStopBits(STOP_1);
myCom->setFlowControl(FLOW_OFF); //設(shè)置數(shù)據(jù)流控制,我們使用無數(shù)據(jù)流控制的默認(rèn)設(shè)置
myCom->setTimeout(500); //設(shè)置延時
connect(myCom,SIGNAL(readyRead()),this,SLOT(readMyCom()));
//信號和槽函數(shù)關(guān)聯(lián)凛澎,當(dāng)串口緩沖區(qū)有數(shù)據(jù)時霹肝,進(jìn)行讀串口操作
openMyComBtn->setEnabled(false); //打開串口后“打開串口”按鈕不可用
closeMyComBtn->setEnabled(true); //打開串口后“關(guān)閉串口”按鈕可用
sendMsgBtn->setEnabled(true); //打開串口后“發(fā)送數(shù)據(jù)”按鈕可用
O2U1->setEnabled(true);
O2U2->setEnabled(true);
O2U3->setEnabled(true);
baudRateComboBox->setEnabled(false); //設(shè)置各個組合框不可用
portNameComboBox->setEnabled(false);
}
在端口設(shè)置和波特率配置中,主要用到的控件有QComboBox塑煎,可以實現(xiàn)下拉菜單功能沫换,還沒用過這個控件的小伙伴可以自行百度下,很簡單的啦最铁。
2.寫串口數(shù)據(jù)
//發(fā)送消息
void uwiCMonitorPC::on_sendMsgBtn_clicked()
{
if(O2U1->isChecked()||O2U2->isChecked()||O2U3->isChecked())//判斷選擇的是那種功能
{
QString num;
if(O2U1->isChecked())//配置查詢
{
int table[20]={0x2e,0x2d,0x3d,0x3e,0x00,0x0d,0x01,0x00,0x00,0x00,0x00};
int *p=table;
int wCRC =CRC16(p,11);
table[11]=wCRC>>8;
table[12]=wCRC&0x00ff;
for(int i=0;i<13;i++)
num+=table[i];
}
else if(O2U2->isChecked())//地址配置
{
int table[20]={0x2e,0x2d,0x3d,0x3e,0x00,0x11,0x02,0x00,0x00,0x00,0x00,
0x00,0x0c,0x01,0x02};
table[11]=edit1->text().toInt();
int *p=table;
int wCRC =CRC16(p,15);
table[15]=wCRC>>8;
table[16]=wCRC&0x00ff;
for(int i=0;i<17;i++)
num+=table[i];
}
else if(O2U3->isChecked())//功能配置
{
int table[20]={0x2e,0x2d,0x3d,0x3e,0x00,0x0e,0x03,0x00,0x00,0x00};
if(device->currentText()==tr("投料機")) table[10]=0x01;
else if(device->currentText()==tr("增氧泵")) table[10]=0x02;
else if(device->currentText()==tr("三合一")) table[10]=0x03;
else if(device->currentText()==tr("氨 氮")) table[10]=0x04;
else if(device->currentText()==tr("氣象站")) table[10]=0x05;
else if(device->currentText()==tr("三合一和氨氮")) table[10]=0x06;
else table[10]=0x07;
table[11]=edit5->text().toInt();
int *p=table;
int wCRC =CRC16(p,12);
table[12]=wCRC>>8;
table[13]=wCRC&0x00ff;
for(int i=0;i<14;i++)
num+=table[i];
}
QByteArray outData=num.toAscii();//將16進(jìn)制數(shù)轉(zhuǎn)化為可以發(fā)送的QByteArray 數(shù)據(jù)
myCom->write(outData);//將數(shù)據(jù)寫入串口
}
數(shù)據(jù)格式轉(zhuǎn)換真心累啊讯赏,我在后面中會給大家介紹我在數(shù)據(jù)格式轉(zhuǎn)換中遇到的坑垮兑,大家可以參考,寫入數(shù)據(jù)部分漱挎,其實最主要的控件就是一個lineedit系枪,也即文本框,將要發(fā)送的數(shù)據(jù)輸入到文本框磕谅,然后讀取文本框中的內(nèi)容即可 table[11]=edit1->text().toInt();將edit1中輸入的內(nèi)容轉(zhuǎn)換成10進(jìn)制私爷,并存貯在table中,然后就可以寫入串口了怜庸,當(dāng)然怎么寫入的我們就可以不用管了当犯,你只要負(fù)責(zé)把數(shù)據(jù)準(zhǔn)備好就可以了,直接送到函數(shù) myCom->write(outData);中就可以了割疾,調(diào)用了第三方庫,很多步驟我們都省了嘉栓。
3.讀串口數(shù)據(jù)
if (myCom->bytesAvailable()<=0)
{return;}//如果沒有收到數(shù)據(jù)就返回
Sleep(100);//延時100ms確保數(shù)據(jù)可以一次讀出
QByteArray temp = myCom->readAll();//得到全部數(shù)據(jù)
QString tempDataHex=uwiCMonitorPC::ByteArrayToHexStr(temp);//字節(jié)數(shù)組變?yōu)樽址? textBrowser->insertPlainText(tempDataHex+"\n"); //返回數(shù)據(jù)顯示
讀串口部分也就是一個函數(shù) myCom->readAll();讀之前需要延時一段時間以確保串口數(shù)據(jù)可以一次接受完成宏榕。將得到的數(shù)據(jù)轉(zhuǎn)換為QString類型,然后就可以送進(jìn)去顯示了侵佃。
串口通信主要的核心部分大概就是這三部分了,調(diào)用第三方庫麻昼,主要難點就在于數(shù)據(jù)類型轉(zhuǎn)換,因為串口發(fā)送和文本框接受顯示的數(shù)據(jù)類型是不一樣的馋辈,還有發(fā)送16進(jìn)制數(shù)據(jù)時也得進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換抚芦。反正我在格式轉(zhuǎn)換上面花了很多時間,我在下篇博客中會貼出各種格式轉(zhuǎn)換的代碼迈螟,供大家參考叉抡。
對串口通信原理不了解的可以自己先去網(wǎng)上自行了解下原理,等了解原理后再寫串口程序就游潤有余了答毫,整個代碼我已經(jīng)打包好了褥民,只要用cmake編譯下就可以運行了(所有的控件都是用代碼實現(xiàn)的,沒有基于qt caeater洗搂,控件不是拖拽來的消返,當(dāng)然為了學(xué)習(xí),為了提高代碼能力耘拇,我建議不拖拽撵颊,如果在實際項目中那就不一樣了),我過會會將所有代碼上傳惫叛,有問題的歡迎留言討論倡勇。
關(guān)于我自己
一個正派但不正經(jīng)的程序員
18年計算機專業(yè)碩士畢業(yè)生,騰訊SNG部門實習(xí)生挣棕,現(xiàn)加盟快手科技 译隘,后端研發(fā)工程師一枚
喜歡技術(shù)亲桥,喜歡互聯(lián)網(wǎng)
民遙控 ,趙雷固耘、陳粒题篷、宋冬野
時不時寫篇文章,偶爾數(shù)羊厅目,其實說到底番枚,只是想和你聊聊