作者:zzssdd2
E-mail:[email protected]
一、前言
開發環境:Qt5.12.10 + MinGW
實作的功能
- 串口資料的發送
- ascii字符與hex字符的相互轉換
- 自動追加回車換行符(
\r\n) - 發送資料的統計與顯示
- 發送清零
- 定時發送
涉及的知識點
QSerialPort類的使用- 資料格式的轉換
QTimer類的使用- 控制元件
QPlainTextEdit、QCheckBox、QPushButton、QLabel的使用

二、功能實作
在《QT串口助手(三):資料接收》實作了接收模塊的功能,本章講解發送模塊的各個功能,
2.1、字符判斷
若勾選了HEX格式發送,那么需要對發送框的字符進行合法判斷,這里使用到QPlainTextEdit的textChanged信號來監測發送框資料的改變,在槽函式中對資料進行判別:
/*發送文本框信號槽*/
connect(ui->Send_TextEdit, &QPlainTextEdit::textChanged, this, [=](){
//獲取發送框字符
SendTextEditStr = ui->Send_TextEdit->document()->toPlainText();
if (SendTextEditStr.isEmpty())
{
return;
}
//勾選hex發送則判斷是否有非法hex字符
if (ui->HexSend_checkBox->isChecked())
{
char ch;
bool flag = false;
uint32_t i, len;
//去掉無用符號
SendTextEditStr = SendTextEditStr.replace(' ',"");
SendTextEditStr = SendTextEditStr.replace(',',"");
SendTextEditStr = SendTextEditStr.replace('\r',"");
SendTextEditStr = SendTextEditStr.replace('\n',"");
SendTextEditStr = SendTextEditStr.replace('\t',"");
SendTextEditStr = SendTextEditStr.replace("0x","");
SendTextEditStr = SendTextEditStr.replace("0X","");
//判斷資料合法性
for(i = 0, len = SendTextEditStr.length(); i < len; i++)
{
ch = SendTextEditStr.at(i).toLatin1();
if (ch >= '0' && ch <= '9') {
flag = false;
} else if (ch >= 'a' && ch <= 'f') {
flag = false;
} else if (ch >= 'A' && ch <= 'F') {
flag = false;
} else {
flag = true;
}
}
if(flag) QMessageBox::warning(this,"警告","輸入內容包含非法16進制字符");
}
//QString轉QByteArray
SendTextEditBa = SendTextEditStr.toUtf8();
});
[signal]void QPlainTextEdit::textChanged()This signal is emitted whenever the document's content changes; for example, when text is inserted or deleted, or when formatting is applied.
Note: Notifier signal for property plainText.
這樣我們在進行輸入時,如果包含非法字符就會有彈框提示(我這里對','、"0x"、"0X"等字符過濾是為了方便有時從代碼中直接復制陣列資料發送):

2.2、資料轉換
通過是否勾選HEX發送判斷使用ascii格式還是hex格式發送資料,使用QCheckBox的stateChanged信號對勾選狀態進行檢測,然后在對應的槽函式中進行資料格式的轉換,
/*HEX發送chexkBox信號槽*/
connect(ui->HexSend_checkBox,&QCheckBox::stateChanged,this,[=](int state){
if (SendTextEditStr.isEmpty())
{
return;
}
//asccii與hex轉換
if (state == Qt::Checked)
{
//轉換成QByteArray -> 轉換成16進制數,按空格分開 -> 轉換為大寫
SendTextEditBa = SendTextEditBa.toHex(' ').toUpper();
ui->Send_TextEdit->document()->setPlainText(SendTextEditBa);
}
else
{
//從QByteArray轉換為QString
SendTextEditStr = SendTextEditBa.fromHex(SendTextEditBa);
ui->Send_TextEdit->document()->setPlainText(SendTextEditStr);
}
});
[signal]void QCheckBox::stateChanged(int state)This signal is emitted whenever the checkbox's state changes, i.e., whenever the user checks or unchecks it.
state contains the checkbox's new Qt::CheckState.

2.3、手動發送
當點擊發送按鈕時觸發QPushButton的點擊信號,在對應的槽函式中將發送框的資料按照選定格式發送出去,程式主體如下:
/*
函 數:on_Send_Bt_clicked
描 述:發送按鍵點擊槽函式
輸 入:無
輸 出:無
*/
void Widget::on_Send_Bt_clicked()
{
if (isSerialOpen != false)
{
/*將發送框資料發送*/
SerialSendData(SendTextEditBa);
}
else
{
QMessageBox::information(this, "提示", "串口未打開");
}
}
QpushButton繼承自QAbstractButton,關于按鍵點擊信號的描述:
[signal]void QAbstractButton::clicked(bool checked = false)This signal is emitted when the button is activated (i.e., pressed down then released while the mouse cursor is inside the button), when the shortcut key is typed, or when click() or animateClick() is called. Notably, this signal is not emitted if you call setDown(), setChecked() or toggle().
If the button is checkable, checked is true if the button is checked, or false if the button is unchecked.
/*
函 數:SendData
描 述:串口發送資料
輸 入:無
輸 出:無
*/
void Widget::SerialSendData(QByteArray baData)
{
if (baData.isEmpty() != true)
{
/*是否加回車換行*/
if (ui->AddNewLine_Box->isChecked())
{
baData.append("\r\n");
}
if (ui->HexSend_checkBox->isChecked()) // hex發送
{
/*獲取hex格式的資料*/
baData = https://www.cnblogs.com/zzssdd2/archive/2021/01/30/baData.fromHex(baData);
/*發送hex資料*/
serial->write(baData);
/*是否顯示時間戳*/
if (ui->TimeDisp_checkBox->isChecked())
{
QString strdata = baData.toHex(' ').trimmed().toUpper();
ui->Receive_TextEdit->setTextColor(QColor("blue"));
ui->Receive_TextEdit->append(QString("[%1]TX -> ").arg(QTime::currentTime().toString("HH:mm:ss:zzz")));
ui->Receive_TextEdit->setTextColor(QColor("black"));
ui->Receive_TextEdit->insertPlainText(strdata);
}
}
else //ascii發送
{
/*發送ascii資料*/
serial->write(baData);
/*是否顯示時間戳*/
if (ui->TimeDisp_checkBox->isChecked())
{
QString strdata = https://www.cnblogs.com/zzssdd2/archive/2021/01/30/QString(baData);
ui->Receive_TextEdit->setTextColor(QColor("red"));
ui->Receive_TextEdit->append(QString("[%1]TX -> ").arg(QTime::currentTime().toString("HH:mm:ss:zzz")));
ui->Receive_TextEdit->setTextColor(QColor("black"));
ui->Receive_TextEdit->insertPlainText(strdata);
}
}
//移動游標到末尾
ui->Receive_TextEdit->moveCursor(QTextCursor::End);
//更新發送計數
serialDataTotalTxCnt += baData.length();
ui->TxCnt_label->setText(QString::number(serialDataTotalTxCnt));
}
else
{
QMessageBox::warning(this, "警告", "資料為空");
}
}
如果勾選了顯示時間戳則在每次資料發送后將資料填充到接收框進行顯示;代碼中對發送的不同格式資料進行了不同顏色的標記;發送后對發送計數框進行更新,
QSerialPort繼承自QIODevice,串口發送資料就是使用QIODevice類的write方法:
qint64 QIODevice::write(const QByteArray&byteArray)
This is an overloaded function.
Writes the content of byteArray to the device. Returns the number of bytes that were actually written, or -1 if an error occurred.

2.4、定時發送
使用QT中的定時器QTimer按照設定的時間對發送框資料進行自動發送,呼叫定時器的超時信號來觸發槽函式中的發送操作:
/*定時發送定時器*/
TimerSend = new QTimer(this);
/*定時器超時信號槽*/
connect(TimerSend, &QTimer::timeout, this, [=](){
SerialSendData(SendTextEditBa);
});
[signal]void QTimer::timeout()This signal is emitted when the timer times out.
Note: This is a private signal. It can be used in signal connections but cannot be emitted by the user.
當定時發送被勾選后,會觸發QCheckBox的stateChanged信號來設定時間、開啟定時器:
/*
函 數:on_TimeSend_checkBox_stateChanged
描 述:定時發送框勾選信號對應槽函式
輸 入:無
輸 出:無
*/
void Widget::on_TimeSend_checkBox_stateChanged(int arg1)
{
int time;
/*判斷串口是否打開*/
if (false == isSerialOpen)
{
if (ui->TimeSend_checkBox->isChecked())
{
QMessageBox::information(this, "提示", "串口未打開");
}
return;
}
/*判斷是否有資料*/
if (ui->Send_TextEdit->document()->isEmpty() == true)
{
if (ui->TimeSend_checkBox->isChecked())
{
QMessageBox::warning(this, "警告", "資料為空");
}
return;
}
/*判斷勾選狀態*/
if (arg1 == Qt::Checked)
{
/*獲取設定時間*/
time = ui->TimeSend_lineEdit->text().toInt();
if (time > 0) {
TimerSend->start(time);
} else {
QMessageBox::warning(this, "警告", "時間必須大于0");
}
ui->TimeSend_lineEdit->setEnabled(false);
}
else
{
/*停止發送*/
TimerSend->stop();
ui->TimeSend_lineEdit->setEnabled(true);
}
}
[slot]void QTimer::start(int msec)Starts or restarts the timer with a timeout interval of msec milliseconds.
If the timer is already running, it will be stopped and restarted.
If singleShot is true, the timer will be activated only once.
[slot]void QTimer::stop()Stops the timer.

三、總結
本章主要講解資料的發送與格式轉換,除了要知道各控制元件的信號槽應用之外,還應該對QT中資料型別的一些操作方法有所了解,比如上面的代碼中使用到的一些QString、QByteArray的常用資料操作方法:QString::replace、QString::at、QString::toUtf8、QByteArray::toHex、QByteArray::fromHex等,
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/254654.html
標籤:其他
下一篇:STM32 IIC詳解
