作者:zzssdd2
E-mail:[email protected]
一、前言
開發環境:Qt5.12.10 + MinGW
主要實作功能
- 串口引數的配置:
波特率、資料位、停止位、校驗位 - 本機串口設備的查詢與添加顯示
- 串口設備的手動更新與打開關閉
涉及的知識點
- 串口類
QSerialPort及QSerialPortInfo的使用 - 自定義波特率的實作
QComboBox下拉串列自適應文本長度顯示- 控制元件
QPushButton、QComboBox的使用

二、功能實作
下面開始逐步講解以上列舉的功能
2.1、串口設備的查詢添加
創建一個串口設備資訊串列和串口設備號串列,遍歷本機可用串口然后添加到串列中,將設備資訊串列顯示在對應的QComboBox控制元件中,設備號串列用來后面打開串口設備使用,
/* 遍歷可用串口設備 */
QStringList SerialPort_Name;
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
SerialPort_Name << info.portName()+':'+info.description();
serialDevice << info.portName();
}
/* 添加到串口設備顯示框 */
ui->SerialNum_Box->addItems(SerialPort_Name);
2.2、下拉串列自適應
此時已經將串口設備資訊添加到下拉框中了,但是下拉框此時是固定長度,如果串口設備資訊比較長則無法顯示完全(以省略號展示),那么就需要實作下拉框根據設備資訊字串長度適配功能,原理就是遍歷串列中所有設備資訊字串的長度,找出最大值然后將下拉框長度設定到能完全顯示最大長度字串,
/* 獲取最長字串 */
int maxlen = 0;
for (int index = 0; index < ui->SerialNum_Box->count(); index++)
{
if (ui->SerialNum_Box->itemText(index).length() > maxlen)
{
maxlen = ui->SerialNum_Box->itemText(index).length();
}
}
/*獲取字體磅值轉換為像素值*/
int fontsize = ui->SerialNum_Box->font().pointSize();//獲取字體的磅值
ui->SerialNum_Box->view()->setFixedWidth(fontsize * maxlen * 0.75);//設定像素值
這里涉及字體磅與像素對應關系,因為setFixedWidth函式引數單位是像素,下面列出字號不同單位對照表:
| 中文字號 | 英文字號(磅) | 毫米 | 像素 |
|---|---|---|---|
| 1英寸 | 72pt | 25.30mm | 95.6px |
| 大特號 | 63pt | 22.14mm | 83.7px |
| 特號 | 54pt | 18.97mm | 71.7px |
| 初號 | 42pt | 14.82mm | 56px |
| 小初 | 36pt | 12.70mm | 48px |
| 一號 | 26pt | 9.17mm | 34.7px |
| 小一 | 24pt | 8.47mm | 32px |
| 二號 | 22pt | 7.76mm | 29.3px |
| 小二 | 18pt | 6.35mm | 24px |
| 三號 | 16pt | 5.64mm | 21.3px |
| 小三 | 15pt | 5.29mm | 20px |
| 四號 | 14pt | 4.94mm | 18.7px |
| 小四 | 12pt | 4.23mm | 16px |
| 五號 | 10.5pt | 3.70mm | 14px |
| 小五 | 9pt | 3.18mm | 12px |
| 六號 | 7.5pt | 2.56mm | 10px |
| 小六 | 6.5pt | 2.29mm | 8.7px |
| 七號 | 5.5pt | 1.94mm | 7.3px |
| 八號 | 5pt | 1.76mm | 6.7px |
由上表可知:1inch = 72pt,那么1pt = 1 / 72(inch),我們使用的9pt字號就是9 * (1 / 72) = 1 / 8(inch).
DPI(dots per inch)表示每英寸能夠列印的格點數量(可以理解為像素點數),這個值一般默認值為96,在小字體模式下解析度是96DPI(大字體模式下解析度是120DPI),也就是說每英寸能顯示96個像素,由此可以算出我們使用的9pt字號對應像素:96dpi / (1 / 8)inch = 12px,那么1px = 9pt / 12px = 0.75pt,
添加該功能后前后對比:

2.3、串口引數的配置
這部分功能實作串口引數的配置,主要有波特率、資料位、停止位、校驗位等,根據下拉框選擇的引數進行配置,
/* 設定波特率 */
switch (ui->Bandrate_Box->currentIndex())
{
case 0:
serial->setBaudRate(QSerialPort::Baud1200,QSerialPort::AllDirections);
break;
case 1:
serial->setBaudRate(QSerialPort::Baud2400,QSerialPort::AllDirections);
break;
case 2:
serial->setBaudRate(QSerialPort::Baud4800,QSerialPort::AllDirections);
break;
case 3:
serial->setBaudRate(QSerialPort::Baud9600,QSerialPort::AllDirections);
break;
case 4:
serial->setBaudRate(QSerialPort::Baud19200,QSerialPort::AllDirections);
break;
case 5:
serial->setBaudRate(QSerialPort::Baud38400,QSerialPort::AllDirections);
break;
case 6:
serial->setBaudRate(QSerialPort::Baud57600,QSerialPort::AllDirections);
break;
case 7:
serial->setBaudRate(QSerialPort::Baud115200,QSerialPort::AllDirections);
break;
case 8:
/*自定義波特率*/
default:
break;
}
/* 設定資料位 */
switch (ui->Databit_Box->currentIndex()) {
case 0:
serial->setDataBits(QSerialPort::Data5);
break;
case 1:
serial->setDataBits(QSerialPort::Data6);
break;
case 2:
serial->setDataBits(QSerialPort::Data7);
break;
case 3:
serial->setDataBits(QSerialPort::Data8);
break;
default:
break;
}
/* 設定停止位 */
switch (ui->Stopbit_Box->currentIndex()) {
case 0:
serial->setStopBits(QSerialPort::OneStop);
break;
case 1:
serial->setStopBits(QSerialPort::OneAndHalfStop);
break;
case 2:
serial->setStopBits(QSerialPort::TwoStop);
break;
default:
break;
}
/* 設定校驗位 */
switch (ui->Parity_Box->currentIndex()) {
case 0:
serial->setParity(QSerialPort::NoParity);
break;
case 1:
serial->setParity(QSerialPort::EvenParity);
break;
case 2:
serial->setParity(QSerialPort::OddParity);
break;
default:
break;
}
/* 設定流控制 */
serial->setFlowControl(QSerialPort::NoFlowControl);
2.4、自定義波特率
在QT的原始碼檔案qserialport.h中列舉了常用的波特率:
enum BaudRate {
Baud1200 = 1200,
Baud2400 = 2400,
Baud4800 = 4800,
Baud9600 = 9600,
Baud19200 = 19200,
Baud38400 = 38400,
Baud57600 = 57600,
Baud115200 = 115200,
UnknownBaud = -1
};
但是如果沒有列出我們用到的波特率,那么就需要實作自定義波特率(比如我以前參與的一個專案就要求串口使用500000bps波特率),實作方式就是將波特率QComboBox串列最后一項設定為自定義波特率,當使用自定義波特率時則獲取填寫的自定義值并轉換為qint32型別數值,然后將該引數設定為波特率,如下:
qint32 CustomBandrate = ui->Bandrate_Box->currentText().toUInt();
serial->setBaudRate(CustomBandrate, QSerialPort::AllDirections);
這里需要注意的是波特率串列自定義項之前的都是對應的固定波特率值,如果不是選擇自定義波特率應當設定為不可編輯狀態,只有選擇自定義波特率時才可以編輯,這里使用QComboBox的信號currentIndexChanged觸發槽函式實作該功能:如果選擇了自定義波特率,則將下拉框設為可編輯,否則設為不能編輯
/*下拉項改變信號槽:多載函式若有多種不同引數型別則使用信號槽連接時有必要指定引數型別*/
connect(ui->Bandrate_Box, QOverload<int>::of(&QComboBox::currentIndexChanged),[=](int index){
if (index == 8) {
ui->Bandrate_Box->setEditable(true);
ui->Bandrate_Box->setCurrentText(NULL);
} else {
ui->Bandrate_Box->setEditable(false);
}
});
引數配置串列完成如下:

2.5、串口打開與關閉
串口開關按鈕點擊信號對應的槽函式實作內容如下:
/*
函 數:on_SerialPortSwitch_Bt_clicked
描 述:開關串口按鍵點擊槽函式
輸 入:無
輸 出:無
*/
void Widget::on_SerialPortSwitch_Bt_clicked()
{
if (ui->SerialPortSwitch_Bt->text() == "打開")
{
/* 創建串口物件 */
serial = new QSerialPort(this);
/* 創建接收資料信號槽 */
connect(serial, &QSerialPort::readyRead, this, &Widget::SerialPortReadyRead_slot);
/* 設定串口號 */
QString dev = serialDevice.at(ui->SerialNum_Box->currentIndex());
serial->setPortName(dev);
/* 設定波特率 */
/* 設定資料位 */
/* 設定停止位 */
/* 設定校驗位 */
/* 設定流控制 */
/* 打開串口 */
if (serial->open(QIODevice::ReadWrite) != true)
{
QMessageBox::critical(this, "提示", "打開失敗");
return;
}
/*標記串口已打開*/
global_struct.isSerialOpen = true;
/*設定文本*/
ui->SerialPortSwitch_Bt->setText("關閉");
}
else
{
/*關閉并洗掉串口物件*/
serial->close();
serial->deleteLater();
/*標記串口已關閉*/
global_struct.isSerialOpen = false;
/*設定文本*/
ui->SerialPortSwitch_Bt->setText("打開");
}
}
2.6、串口設備的重繪
串口設備重繪按鈕點擊信號對應的槽函式功能實作如下:
/*
函 數:on_ComFlush_BT_clicked
描 述:串口設備重繪按鈕槽函式
輸 入:無
輸 出:無
*/
void Widget::on_ComFlush_BT_clicked()
{
ui->SerialNum_Box->clear();
FindSerialPort();
}
/*
函 數:FindSerialPort
描 述:查找串口并添加到QComboBox
輸 入:無
輸 出:無
*/
void Widget::FindSerialPort(void)
{
/* 遍歷可用串口并添加到顯示框 */
QStringList SerialPort_Name;
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
SerialPort_Name << info.portName()+':'+info.description();
serialDevice << info.portName();
}
ui->SerialNum_Box->addItems(SerialPort_Name);
/*設定下拉框串列寬度*/
int maxlen = 0;
for (int index = 0; index < ui->SerialNum_Box->count(); index++)
{
if (ui->SerialNum_Box->itemText(index).length() > maxlen)
{
maxlen = ui->SerialNum_Box->itemText(index).length();
}
}
int fontsize = ui->SerialNum_Box->font().pointSize();
ui->SerialNum_Box->view()->setFixedWidth(fontsize * maxlen * 0.75);
}
三、總結
本篇文章主要是講如何對串口引數進行配置及QComboBox等控制元件的一些基本操作,除此之外,還應該了解一定C++知識,比如類的繼承、函式多載、Lambda運算式等;還有就是應該掌握QT信號槽的使用,因為這是QT框架中非常重要的通信機制,可以說使用QT開發必然離不開信號槽的應用,
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/251323.html
標籤:嵌入式
