QT串口助手(三):數據接收
作者:zzssdd2
E-mail:[email protected]
一、前言
開發環境:Qt5.12.10 + MinGW
實現的功能
- 串口數據的接收
- ascii字元形式顯示與hex字元形式顯示
- 時間戳的顯示
- 接收數據的統計與顯示
- 接收清零
涉及的知識點
QSerialPort
類的使用- 數據格式的轉換
QTime
類的使用- 控制項
QTextEdit
、QCheckBox
、QPushButton
、QLabel
的使用
二、功能實現
下面開始逐步講解以上列舉的功能實現
2.1、數據讀取
在《QT串口助手(二):參數配置》中已經實現了串口參數的配置,參數配置完成後就可以開啟串口的數據接收功能了。在QT中的QSerialPort類繼承自QIODevice類,所以可以使用QIODevice的readyRead()訊號來觸發數據的接收,在槽函數中實現數據的讀取與處理。訊號槽連接如下:
/* 接收數據訊號槽 */
connect(serial, &QSerialPort::readyRead, this, &Widget::SerialPortReadyRead_slot);
補充:
[signal]
void QIODevice::readyRead()This signal is emitted once every time new data is available for reading from the device’s current read channel. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.
readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).
Note for developers implementing classes derived from QIODevice: you should always emit readyRead() when new data has arrived (do not emit it only because there’s data still to be read in your buffers). Do not emit readyRead() in other conditions.
當有收到新數據訊號時,就會執行槽函數裡面的數據讀取功能:
/*讀取串口收到的數據*/
QByteArray bytedata = serial->readAll();
補充:
QByteArray QIODevice::readAll()
Reads all remaining data from the device, and returns it as a byte array.
This function has no way of reporting errors; returning an empty QByteArray can mean either that no data was currently available for reading, or that an error occurred.
2.2、數據轉換
若需要將接收到的數據以HEX格式顯示,則需要對接收到的數據進行以下處理:
/*將數據轉換為hex格式並以空格分隔->去掉頭尾空白字元->轉換為大寫形式*/
framedata = bytedata.toHex(' ').trimmed().toUpper();
補充:
QByteArray QByteArray::toHex(char separator) const
This is an overloaded function.
Returns a hex encoded copy of the byte array. The hex encoding uses the numbers 0-9 and the letters a-f.
If separator is not ‘\0’, the separator character is inserted between the hex bytes.
Example:
QByteArray macAddress = QByteArray::fromHex("123456abcdef"); macAddress.toHex(':'); // returns "12:34:56:ab:cd:ef" macAddress.toHex(0); // returns "123456abcdef"
This function was introduced in Qt 5.9.
QByteArray QByteArray::trimmed() const
Returns a byte array that has whitespace removed from the start and the end.
Whitespace means any character for which the standard C++
isspace()
function returnstrue
in the C locale. This includes the ASCII characters ‘\t’, ‘\n’, ‘\v’, ‘\f’, ‘\r’, and ‘ ‘.Example:
QByteArray ba(" lots\t of\nwhitespace\r\n "); ba = ba.trimmed(); // ba == "lots\t of\nwhitespace";
Unlike simplified(), trimmed() leaves internal whitespace alone.
QByteArray QByteArray::toUpper() const
Returns an uppercase copy of the byte array. The bytearray is interpreted as a Latin-1 encoded string.
Example:
QByteArray x("Qt by THE QT COMPANY"); QByteArray y = x.toUpper(); // y == "QT BY THE QT COMPANY"
2.3、添加時間戳
有時為了便於觀察數據收發時間,需要在數據前插入時間戳顯示。使用QTime類中的方法可以獲取當前系統的時間(精確到ms),對數據處理如下:
/*在數據前插入時間戳:[時:分:秒:毫秒]:RX -> 數據*/
framedata = QString("[%1]:RX -> %2").arg(QTime::currentTime().toString("HH:mm:ss:zzz")).arg(framedata);
補充:
[static]
QTime QTime::currentTime()Returns the current time as reported by the system clock.
Note that the accuracy depends on the accuracy of the underlying operating system; not all systems provide 1-millisecond accuracy.
Furthermore, currentTime() only increases within each day; it shall drop by 24 hours each time midnight passes; and, beside this, changes in it may not correspond to elapsed time, if a daylight-saving transition intervenes.
2.4、接收計數
使用一個quint32類型數據對每次接收數據長度進行累加,記錄接收數據總數,然後將數據更新到ui介面:
dataTotalRx += bytedata.length();
ui->RxCnt_label->setText(QString::number(dataTotalRx));
2.5、數據顯示
以上功能完成後將數據顯示到接收框中(為了區分不同顯示格式,做了不同的顏色顯示)。完整的數據接收功能展示如下:
/*
函 數:SerialPortReadyRead_slot
描 述:readyRead()訊號對應的數據接收槽函數
輸 入:無
輸 出:無
*/
void Widget::SerialPortReadyRead_slot()
{
QString framedata;
/*讀取串口收到的數據*/
QByteArray bytedata = serial->readAll();
/*數據是否為空*/
if (!bytedata.isEmpty())
{
if(ui->HexDisp_checkBox->isChecked())
{
/*hex顯示*/
framedata = bytedata.toHex(' ').trimmed().toUpper();
ui->Receive_TextEdit->setTextColor(QColor(Qt::green));
}
else
{
/*ascii顯示*/
framedata = QString(bytedata);
ui->Receive_TextEdit->setTextColor(QColor(Qt::magenta));
}
/*是否顯示時間戳*/
if (ui->TimeDisp_checkBox->isChecked())
{
framedata = QString("[%1]:RX -> %2").arg(QTime::currentTime().toString("HH:mm:ss:zzz")).arg(framedata);
ui->Receive_TextEdit->append(framedata);
}
else
{
ui->Receive_TextEdit->insertPlainText(framedata);
}
/*更新接收計數*/
dataTotalRxCnt += bytedata.length();
ui->RxCnt_label->setText(QString::number(dataTotalRxCnt));
}
}
演示效果如下:
補充:
QColor::QColor(Qt::GlobalColor color)
This is an overloaded function.
Constructs a new color with a color value of color.
enum Qt::GlobalColor
Qt’s predefined QColor objects:
Constant Value Description Qt::white
3
White (#ffffff) Qt::black
2
Black (#000000) Qt::red
7
Red (#ff0000) Qt::darkRed
13
Dark red (#800000) Qt::green
8
Green (#00ff00) Qt::darkGreen
14
Dark green (#008000) Qt::blue
9
Blue (#0000ff) Qt::darkBlue
15
Dark blue (#000080) Qt::cyan
10
Cyan (#00ffff) Qt::darkCyan
16
Dark cyan (#008080) Qt::magenta
11
Magenta (#ff00ff) Qt::darkMagenta
17
Dark magenta (#800080) Qt::yellow
12
Yellow (#ffff00) Qt::darkYellow
18
Dark yellow (#808000) Qt::gray
5
Gray (#a0a0a4) Qt::darkGray
4
Dark gray (#808080) Qt::lightGray
6
Light gray (#c0c0c0) Qt::transparent
19
a transparent black value (i.e., QColor(0, 0, 0, 0)) Qt::color0
0
0 pixel value (for bitmaps) Qt::color1
1
1 pixel value (for bitmaps)
2.6、清除接收
當清除接收
按鍵點擊後,會清除接收框顯示的內容以及接收計數。使用QPushButton的點擊訊號槽實現如下:
/*
函 數:on_ClearRx_Bt_clicked
描 述:清除接收按鍵點擊訊號對應的槽函數
輸 入:無
輸 出:無
*/
void Widget::on_ClearRx_Bt_clicked()
{
ui->Receive_TextEdit->clear();
ui->RxCnt_label->setText(QString::number(0));
dataTotalRxCnt = 0;
}
三、總結
本篇文章主要是講述如何對串口數據進行接收和顯示。除了上面列出的主要功能外,還需要了解各個控制項的操作方法,比如QTextEdit文本的添加、QLabel文本的設置等。還有就是QT中基本的數據類型的數據使用,比如QString、QBytArray等。