一、程序简介
基于qt框架的串口通信助手小工具。在基础的通信调试功能基础上,添加了:发送文件,保存成文件;数据滤波;数据波形显示,对一个数据的分析,可同时显示多个波形。通过Linguist生成的qm文件进行中英文一键切换,通过全局的qss文件设置界面颜色风格。通过配置注册表来读取上次运行配置的一些初始设置进行初始化。
其中加载qss文件的文章联接http://t.csdnimg.cn/XaNAv。
二、辅助工具
借用虚拟串口工具VSPD7.2,模拟COM1、COM2连接串口,并将两端口连接,COM1发COM2收,COM2发COM1,从而方便进行软件功能测试。
三、程序展示
1、基本功能
基本功能借鉴了xcom。
.基础收发功能
可系统编码收发,16进制收发,定时发送,时间戳换行显示。
收到消息的处理槽函数源码:
/**
* @brief 处理接收数据槽
* @author LiDonglin
* @date 20240707
*/
void MainWindow::readData() {
QByteArray data = serial.readAll();
QString text = QString::fromLocal8Bit(data.constData());
readSize += text.size();
/* 处理接收到的数据 */
ui->label_3->setText(QString::number(readSize));
if(ui->checkBox_12->isChecked())//16进制显示
{
QString hexStr = data.toHex().toUpper();
QString initialStrTemp = setFilteringDialog.getInitialStr();
initialStrTemp.remove(" ");
for(int i = 0;i<initialStrTemp.size();++i)//校验是否为字头
{
if(initialStrTemp[i]!=hexStr[i])return;
}
QString outDate;//去掉字头,将有用数据传给波形显示窗口
int l = std::min(hexStr.size()-initialStrTemp.size(),(long long)setFilteringDialog.getLine());
for(int i = initialStrTemp.size();i<initialStrTemp.size()+l;++i)
{
outDate.push_back(hexStr[i]);
}
emit valueChanged(outDate);
switch(setFilteringDialog.getModle())
{
case 1:
break;
case 2:
for(int i = 0;i<initialStrTemp.size();++i)//添加字头
{
ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
ui->textBrowser->insertPlainText(hexStr[i]); // 在光标位置插入文本
if(i%2 == 1)
{
ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
ui->textBrowser->insertPlainText(" "); // 在光标位置插入文本
}
}
break;
}
for(int i = initialStrTemp.size();i<initialStrTemp.size()+setFilteringDialog.getLine()*2;++i)
{
if(i == hexStr.size())break;
ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
ui->textBrowser->insertPlainText(hexStr[i]); // 在光标位置插入文本
if(i%2 == 1)
{
ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
ui->textBrowser->insertPlainText(" "); // 在光标位置插入文本
}
}
}
else//系统编码显示
{
ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
ui->textBrowser->insertPlainText(text); // 在光标位置插入文本
}
if(ui->checkBox_13->isChecked())//时间戳换行
{
QDateTime currentDateTime = QDateTime::currentDateTime();
ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
ui->textBrowser->insertPlainText(currentDateTime.toString("[yyyy-MM-dd HH:mm:ss]")+"\r\n"); // 在光标位置插入文本
}
}
发送消息的处理槽函数源码:
/**
* @brief 16进制或普通发送工具
* @param 要发送的数据
* @param 是否16进制发送
* @author LiDonglin
* @date 202407010
*/
void MainWindow::is16OutTool(QString text,bool is)
{
/* 更新已发送数据量 */
writeSize += text.size();
ui->label_4->setText(QString::number(writeSize));
if(is)//16进制发送
{
QStringList strList = text.split(' ', Qt::SkipEmptyParts);
for(const auto&it:strList)
{
bool ok;
int value = it.toInt(&ok,16);
QByteArray outdate;
outdate.append(static_cast<char>(value));
serial.write(outdate);
}
}
else//系统编码发送
{
serial.write(text.toLocal8Bit());
}
}
/**
* @brief 发送数据槽
* @author LiDonglin
* @date 20240707
*/
void MainWindow::on_pushButton_5_clicked()
{
QString text = ui->textEdit->toPlainText();
is16OutTool(text,ui->checkBox_2->isChecked());
}
程序视频演示:
串口助手基础功能展示
.多条记忆发送
可同时发送多条指令,可进行文件导入导出。
记忆导入导出处理源码:
/**
* @brief 导出记忆槽
* @author LiDonglin
* @date 20240710
*/
void MainWindow::on_pushButton_12_clicked()
{
QString filePath = ReadFile.getOpenFileName(this,textDialogDio,"./","txt(*.txt*)");
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
QTextStream out(&file);
for(int i = 0;i<OutLints.size();++i)
{
QString line = OutLints[i]->text();
if(line.size() == 0)
{
out << "&nullptr&\n"; // 写入一行文本,并添加换行符
}
else
{
out << line << "\n"; // 写入一行文本,并添加换行符
}
}
file.close();
}
/**
* @brief 导入记忆槽
* @author LiDonglin
* @date 20240710
*/
void MainWindow::on_pushButton_13_clicked()
{
QString filePath = ReadFile.getOpenFileName(this,textDialogDio,"./","txt(*.txt*)");
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return;
}
QTextStream in(&file);
// 逐行读取文件内容
int i = 0;
while (!in.atEnd()) {
QString line = in.readLine();
if(line == "&nullptr&")
{
++i;
continue;
}
OutLints[i++]->setText(line);
}
}
视频展示:
串口助手记忆发送功能展示
.文件io
文件读写函数源码:
/**
* @brief 发送文件
* @author LiDonglin
* @date 20240708
*/
void MainWindow::on_pushButton_9_clicked()
{
QFile file(readTextPath);
// 尝试以只读和文本模式打开文件
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "无法打开文件进行读取:" << file.errorString();
return;
}
QTextStream in(&file);
// 逐行读取文件内容
long long value = 0;
long long h = file.size();
while (!in.atEnd()) {
QString line = in.readLine()+"\r\n";
serial.write(line.toLocal8Bit());
value += line.size();
ui->progressBar->setValue((int)(value*300/h));
readSize += line.size();
ui->label_3->setText(QString::number(readSize));
}
ui->progressBar->setValue(100);
// 完成读取后,关闭文件
file.close();
}
/**
* @brief 保存窗口文件
* @author LiDonglin
* @date 20240710
*/
void MainWindow::on_pushButton_11_clicked()
{
QFile file(writeTextPath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
QTextStream out(&file);
ui->progressBar_2->setValue(50);
out << ui->textBrowser->toPlainText();
ui->progressBar_2->setValue(100);
file.close();
}
程序视频演示:
串口助手文件io展示
2、其他功能
.数据波形显示功能
弹出窗口,在窗口上设置解析规则,在规则先用波形图显示解析内容,可同时显示多个窗口。
数据更新显示处理函数源码:
/**
* @brief 信息更新处理槽
* @param 主窗口发送的数据
* @author LiDonglin
* @date 202407017
*/
void DisplayDialog::getDate(QString date)
{
QList<int> nums;
for(int i = 0;i<date.size();++i)//转化数组为字节数字列表
{
int num;
if(i % 2 == 0)
{
if(date[i]>='0'&&date[i]<='9')
{
num = (date[i].unicode()-'0')*16;
}
else
{
num = (date[i].unicode()-'A'+10)*16;
}
}
else
{
if(date[i]>='0'&&date[i]<='9')
{
num += (date[i].unicode()-'0');
}
else
{
num += (date[i].unicode()-'A'+10);
}
nums.push_back(num);
}
}
if(nums.size()<ui->spinBox_4->value()+1)//数据筛选合法性保证
{
ui->spinBox_4->setValue(ui->spinBox_4->value()+1);
}
if(ui->spinBox_4->value()<ui->spinBox_3->value())
{
ui->spinBox_3->setValue(ui->spinBox_4->value());
}
showNum = 0;
for(int i = ui->spinBox_4->value(),j = 0;i>=ui->spinBox_3->value();--i,++j)
{
showNum += nums[i]*std::pow(256,j);
}
}
/**
* @brief 开启关闭串通信
* @param 新选中的选项的文本内容
* @author LiDonglin
* @date 20240707
*/
void MainWindow::on_pushButton_clicked(bool checked)
{
if(!checked)
{
serial.close();
disconnect(&serial, &QSerialPort::readyRead, this, &MainWindow::readData);
ui->pushButton->setText(noStr);
ui->pushButton_5->setEnabled(false);
}
else
{
if(serial.open(QIODevice::ReadWrite))
{
connect(&serial, &QSerialPort::readyRead, this, &MainWindow::readData);
ui->pushButton->setText(offStr);
ui->pushButton_5->setEnabled(true);
}
else
{
QErrorMessage *errorMessage = new QErrorMessage(this);
errorMessage->setModal(true);
QString tempString = serial.portName()+OpenFailedStr;
errorMessage->setWindowTitle(OpenFailedStr1);
errorMessage->showMessage(tempString);
}
}
}
/**
* @brief 处理接收数据槽
* @author LiDonglin
* @date 20240707
*/
void MainWindow::readData() {
QByteArray data = serial.readAll();
QString text = QString::fromLocal8Bit(data.constData());
readSize += text.size();
/* 处理接收到的数据 */
ui->label_3->setText(QString::number(readSize));
if(ui->checkBox_12->isChecked())//16进制显示
{
QString hexStr = data.toHex().toUpper();
emit valueChanged(hexStr);
for(int i = 0;i<readSize;++i)
{
if(i == hexStr.size())break;
ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
ui->textBrowser->insertPlainText(hexStr[i]); // 在光标位置插入文本
if(i%2 == 1)
{
ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
ui->textBrowser->insertPlainText(" "); // 在光标位置插入文本
}
}
}
else//系统编码显示
{
ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
ui->textBrowser->insertPlainText(text); // 在光标位置插入文本
}
if(ui->checkBox_13->isChecked())//时间戳换行
{
QDateTime currentDateTime = QDateTime::currentDateTime();
ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
ui->textBrowser->insertPlainText(currentDateTime.toString("[yyyy-MM-dd HH:mm:ss]")+"\r\n"); // 在光标位置插入文本
}
}
程序视频演示:
串口助手波形显示功能展示
.一键切换加载的qss样式文件及qm语言
程序视频演示:
串口助手样式语言切换展示
.注册表保存状态
注册表保存上传运行程序时设置的样式表及语言状态,程序运行时读取状态。
关键代码:
/**
* @brief 注册表初始化并获取注册表当前配置
* @brief 程序的控制中心的引用
* @author LiDonglin
* @date 20240716
*/
void settingsInit(QApplication& a)
{
QSettings settings("HKEY_CURRENT_USER\\Software\\LDLsQtApp", QSettings::NativeFormat);
QString Value = settings.value("translator").toString();// 获取语言配置
/* 配置语言 */
if (Value == "") {//第一次运行程序,初始化注册表
settings.setValue("translator", "0");
} else {
if(Value == "1")
{
if(g_translator.load(":/Qm/en.qm"))
{
qApp->installTranslator(&g_translator);
}
}
}
/* 配置样式表 */
Value = settings.value("qss").toString();// 获取样式表配置
if (Value == "") {//第一次运行程序,初始化注册表
settings.setValue("qss", "0");
QFile file(":/qss/day.qss"); // 注意路径是从资源文件的根开始的
if (file.open(QFile::ReadOnly)) {
QTextStream stream(&file);
QString styleSheet = stream.readAll();
a.setStyleSheet(styleSheet);
file.close();
}
} else {
if(Value == "0")//白
{
QFile file(":/qss/day.qss");
if (file.open(QFile::ReadOnly)) {
QTextStream stream(&file);
QString styleSheet = stream.readAll();
a.setStyleSheet(styleSheet);
file.close();
}
}
else if(Value == "1")//黑
{
QFile file(":/qss/night.qss");
if (file.open(QFile::ReadOnly)) {
QTextStream stream(&file);
QString styleSheet = stream.readAll();
a.setStyleSheet(styleSheet);
file.close();
}
}
else if(Value == "2")//天蓝
{
QFile file(":/qss/skyBlue.qss");
if (file.open(QFile::ReadOnly)) {
QTextStream stream(&file);
QString styleSheet = stream.readAll();
a.setStyleSheet(styleSheet);
file.close();
}
}
}
}
程序视频演示:
串口助手注册表展示
四、开源说明
.gitee仓库链接:
git@gitee.com:LDLmcu/uart-assistant.git
.UartAssistantApp:
动态库打包发布文件。