上一篇:
QT实现串口调试助手(七):字体设置面板创建及窗体间传值
串口调试工具往期相关文章
串口工具一般都会有HEX格式的收发处理,现在我们来给串口工具添上这一功能。
这主要分为两类,一类是把串口工具收到的HEX格式数据,以十六进制字符串回显到接收面板。另一类是把发送面板上的十六进制字符串,转为HEX格式数据发送出去
1、接收数据处理
原先我们已经在主界面添加了HEX发送和接收框了,没有添加的话,添加一个即可
然后更改一下原先的接收处理函数:
//填入接收数据到面板
void MainWindow::insertDataToPlain()
{
curDateTime = QDateTime::currentDateTime();
QString tempRecData = "\r\n";
if(ui->timeZoneCheckBox->isChecked())
{
tempRecData.append(curDateTime.toString("[hh:mm:ss]")).append("R:");
ui->uartReadPlain->insertPlainText(tempRecData);
if(ui->checkBoxHexR->isChecked())
{
QString ss;
for(int c :uart_rec_ss)
{
if(c>=0)
{
ss += QString(" %1")
.arg(c, 2, 16, QChar('0'));
}
else
{
ss += QString(" %1")
.arg(c+256, 2, 16, QChar('0'));
}
}
ui->uartReadPlain->insertPlainText(ss);
}
else
{
ui->uartReadPlain->insertPlainText(uart_rec_ss);
}
}
else
{
if(ui->checkBoxHexR->isChecked())
{
QString ss;
for(int c :uart_rec_ss)
{
if(c>=0)
{
ss += QString(" %1")
.arg(c, 2, 16, QChar('0'));
}
else
{
ss += QString(" %1")
.arg(c+256, 2, 16, QChar('0'));
}
}
ui->uartReadPlain->insertPlainText(ss);
}
else
{
ui->uartReadPlain->insertPlainText(uart_rec_ss);
}
}
ui->uartReadPlain->moveCursor(QTextCursor::End); //光标移动到结尾
}
重点是中间的这段处理,将接收到的数据每字节拆成字符串,比如0x30就拆成字符串“30”,再做拼接。需要注意QT接收到数据的时候是有符号类型的,会有负数,我们需要加上256把它转成正值再做字符串转换,不然转换出的字符串里就一堆FFFFFFF了。
for(int c :uart_rec_ss)
{
if(c>=0)
{
ss += QString(" %1")
.arg(c, 2, 16, QChar('0'));
}
else
{
ss += QString(" %1")
.arg(c+256, 2, 16, QChar('0'));
}
}
2、发送数据处理
因为处理发送的事件类型比较多,涉及参数也比较多(HEX、时间戳、回车换行),可以把它封装一下。
创建一个新的CPP文件,比如uart.cpp和uart.h
在文件里面添加一个发送的串口函数,如下:
#include "uart.h"
//发送串口数据
QString MainWindow::sendUartData(QString data,bool isHex,bool hasTimerStamp,bool isAT)
{
curDateTime = QDateTime::currentDateTime();
QString command = "";
QString showBuff = "";
command.append(data);
if(isAT){
command.append("\r\n");
}
if(hasTimerStamp){
QString tempStr = "\r\n"+curDateTime.toString("[hh:mm:ss]")+"S:";
showBuff = tempStr + command;
}
//HEX格式发送
if(isHex){
//将接收到的HEX格式字符串转为HEX格式原始数据
QByteArray arr;
//分析字符串格式中是否带空格
for(int i = 0;i<data.size();i++)
{
if(data[i]==' ')
continue; //跳过
int num = data.mid(i,2).toUInt(nullptr,16);
i++;
arr.append(num);
}
send_buf_len += arr.length();
//发送HEX格式原始数据
serial->write(arr);
//返回HEX格式字符串显示到串口接收面板
return showBuff;
}
//非HEX格式发送
else {
send_buf_len += data.length();
serial->write(command.toLatin1());
return showBuff;
}
}
带上发送内容、是否HEX格式、是否有时间戳、是否带回车换行这几个参数,返回值为被修改后的新的字符串,用于发送完后显示到接收面板上。
然后,修改一下之前发送串口数据的函数,主要是两个地方:
(1)串口发送面板发送数据更改
//主界面串口发送面板,按键发送数据
void MainWindow::on_sendDataButton_clicked()
{
if(ui->openSerialButton->text() == "打开串口")
{
QMessageBox::warning(NULL, "警告", "未打开可用串口,无法发送数据!\r\n\r\n");
return;
}
QString command = ui->uartWritePlain->toPlainText();
//发送数据
QString recShowData = sendUartData(command,ui->checkBoxHexS->isChecked(),
ui->timeZoneCheckBox->isChecked(),ui->changeLineCheckBox->isChecked());
if(ui->timeZoneCheckBox->isChecked())
{
ui->uartReadPlain->moveCursor(QTextCursor::End); //光标移动到结尾
ui->uartReadPlain->insertPlainText(recShowData);
ui->uartReadPlain->moveCursor(QTextCursor::End); //光标移动到结尾
}
ui->TXLenLabel->setText(QString::number(send_buf_len)+"bytes");
}
(2)命令列表面板发送数据更改
//命令菜单按键发送数据
void MainWindow::sendButtonClick(QString command,bool isChecked)
{
//未打开串口则不准发送
if(ui->openSerialButton->text() == "打开串口")
{
QMessageBox::warning(NULL, "警告", "未打开可用串口,无法发送数据!\r\n\r\n");
return;
}
//拼接数据
QString recShowData = sendUartData(command,isChecked,
ui->timeZoneCheckBox->isChecked(),ui->changeLineCheckBox->isChecked());
if(ui->timeZoneCheckBox->isChecked())
{
ui->uartReadPlain->moveCursor(QTextCursor::End); //光标移动到结尾
ui->uartReadPlain->insertPlainText(recShowData);
ui->uartReadPlain->moveCursor(QTextCursor::End); //光标移动到结尾
}
ui->TXLenLabel->setText(QString::number(send_buf_len)+"bytes");
}
和第一个稍有不同,主要是添加一个是否选择HEX格式的参数,因为一般串口工具的命令面板的HEX格式不是由主界面的check框决定的,而是列表里面的Check框决定的,所以我们要多添加一个参数。
然后,我们需要将这个HEX选项加入配置文件里,并做处理,使其每次打开不会丢失:
(1)保存HEX配置参数:
在原先配置基础上,增加一段是否选择HEX格式的内容
//命令面板相关
qint32 rowNum = ui->tableWidget->rowCount();
for(int i =0;i<rowNum;i++)
{
//保存命令内容
auto cellWidget = (ui->tableWidget->cellWidget(i, 1));
QLineEdit *lines =(QLineEdit*)cellWidget;
QString cmdVal = "cmdParam/cmd";
cmdVal.append(QString::number(i));
configIni->setValue(cmdVal,lines->text());
//保存是否选择HEX
cellWidget = (ui->tableWidget->cellWidget(i, 0));
QCheckBox *box =(QCheckBox*)cellWidget;
cmdVal = "cmdParam/hex";
cmdVal.append(QString::number(i));
configIni->setValue(cmdVal,box->isChecked());
}
(2)启动时读取HEX配置参数:
同样增加一段HEX参数选择解析,同时按键的绑定事件sendButtonClick也做了相应修改,因为添加了一个是否使用HEX的参数
for(int i=0;i<100;i++)
{
ui->tableWidget->insertRow(i);
//根据配置文件内容填充数据
//HEX格式选择
QCheckBox *box = new QCheckBox();
ui->tableWidget->setCellWidget(i,0,box);
if(configIni != NULL)
{
QString tempPara = "cmdParam/hex";
tempPara.append(QString::number(i));
box->setChecked(configIni->value(tempPara).toBool());
}
//命令文本
QLineEdit *lineOne = new QLineEdit();
if(configIni != NULL)
{
QString tempPara = "cmdParam/cmd";
tempPara.append(QString::number(i));
lineOne->setText(configIni->value(tempPara).toString());
}
ui->tableWidget->setCellWidget(i,1,lineOne);
QPushButton *button = new QPushButton();
button->setText("发送");
ui->tableWidget->setCellWidget(i,2,button);
connect(button,&QPushButton::clicked,
[=] ()
{
sendButtonClick(lineOne->text(),box->isChecked());
}
);
}
大功告成!现在无论是发送窗口,还是命令面板,HEX格式和字符串格式都可以自由收发和切换了。