做者:zzssdd2html
E-mail:zzssdd2@foxmail.comc++
開發環境:Qt5.12.10 + MinGW數組
實現的功能app
\r\n
)涉及的知識點ide
QSerialPort
類的使用QTimer
類的使用QPlainTextEdit
、QCheckBox
、QPushButton
、QLabel
的使用在《QT串口助手(三):數據接收》實現了接收模塊的功能,本章講解發送模塊的各個功能。函數
若勾選了HEX格式發送,那麼須要對發送框的字符進行合法判斷。這裏使用到QPlainTextEdit的textChanged信號來監測發送框數據的改變,在槽函數中對數據進行判別:ui
/*發送文本框信號槽*/ 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.this
Note: Notifier signal for property plainText.3d
這樣咱們在進行輸入時,若是包含非法字符就會有彈框提示(我這裏對','、"0x"、"0X"等字符過濾是爲了方便有時從代碼中直接複製數組數據發送):rest
經過是否勾選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.
當點擊發送按鈕時觸發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 = 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 = 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.
使用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等。