前言
最近刚学了一点Qt开发上位机,尝试着做个小软件练练手。查找了很多资料,做了一个简单的串口助手,可以实现串口基本发送和接收功能,支持中文显示,还可以控制STM32开发板上的两个LED。
1.软件界面
2.主要功能:
-
启动自动搜索本机串口,或者手动点击搜索键扫描串口
-
自定义波特率
-
支持中文显示
-
支持发送新行
3.实际效果:
(GIF压缩后根本没法看。。。。)
花了大概3天时间吧,找了很多资料,功能很简单, 但想着是自己一点一点开发的,还是挺有成就感的哈!
写这篇文章是为了总结一下开发的过程和一些知识点,主要包括两部分,上位机的实现和STM32端程序的实现。
Qt上位机的实现
0.新建一个Dialog项目
新建一个Dialog项目,这3种基类的区别可以根据你的程序来确定。
1.软件UI界面的设计
使用Qt Designer添加所需要的控件,并进行合理布局,尽量每一个控件,起一个合理易懂的名字。
2.串口库的添加
pro文件添加一行:
对应的头文件包含:
3.串口自动搜索功能的实现
自动搜索本机串口,并在ComboBox中添加串口号
ui->cbb_com->clear();
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
ui->cbb_com->addItem(info.portName());
qDebug() << "串口搜索完成";
}
4.串口的配置和打开关闭
void Dialog::on_btn_uart_Ctrl_clicked()
{
if(this->ui->btn_uart_Ctrl->text() == "打开串口")
{
serial.setPortName(ui->cbb_com->currentText());
serial.setBaudRate(ui->cbb_baud->currentText().toInt());
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
if(!serial.open(QIODevice::ReadWrite))
{
QMessageBox::critical(NULL, "提示", "串口打开失败");
return;
}
qDebug() << "串口打开成功";
this->ui->btn_uart_Ctrl->setText("关闭串口");
}
else
{
serial.close();
this->ui->btn_uart_Ctrl->setText("打开串口");
}
}
5.串口发送数据
6.串口数据的接收和显示,支持中文
QT默认的编码是unicode,不能显示中文的,windows默认使用(GBK/GB2312/GB18030),使用了fromLocal8Bit()函数,实现了从Unicode到本地字符集GBK的转换,用于处理汉语显示乱码等问题
槽函数的实现:
void Dialog::serialPort_readyRead()
{
QByteArray rx_buf = serial.readAll();
if(rx_buf.endsWith("\r\n"))
{
}
QString rx_buf_tmp = QString::fromLocal8Bit(rx_buf);
qDebug() << rx_buf_tmp;
ui->tb_rx_buf->append(rx_buf_tmp);
rx_buf_tmp.clear();
rx_buf.clear();
}
connect语句:
connect(&serial, & QSerialPort::readyRead, this, &Dialog::serialPort_readyRead);
7.下拉框自定义波特率的实现
void Dialog::on_cbb_baud_currentIndexChanged(const QString &arg1)
{
if(this->ui->cbb_baud->currentIndex() == 3)
{
this->ui->cbb_baud->setItemText(3, "");
this->ui->cbb_baud->setEditable(true);
}
else
{
this->ui->cbb_baud->setItemText(3, "自定义");
this->ui->cbb_baud->setEditable(false);
}
serial.setBaudRate(ui->cbb_baud->currentText().toInt());
}
8.发送新行功能的实现
通过一个全局变量实现,发送新行按钮勾选时,标志位置1,然后发送按钮功能里,根据标志位决定是否在末尾添加换行符。
对应的槽函数实现:
void Dialog::on_cb_send_enter_clicked()
{
if(ui->cb_send_enter->isChecked())
{
send_enter_flag = true;
qDebug() << "发送新行";
}
else
{
send_enter_flag = false;
qDebug() << "不发送新行";
}
}
void Dialog::on_btn_send_clicked()
{
QByteArray tx_buf = ui->te_tx_buf->toPlainText().toUtf8();
if(send_enter_flag == true)
tx_buf += "\n";
serial.write(tx_buf);
tx_buf.clear();
}
9.只改变标签颜色
本来想着通过改变样式表的方式改变颜色
this->ui->lbe_blue->setStyleSheet("color: rgb(255, 0, 0);");
但是,实际运行时,连字体和大小都改成了默认的,有没有一种只改变颜色其他的格式不变的方法呢?还真有,如下,不过好像只支持标准颜色?
QPalette colr;
colr.setColor(QPalette::WindowText,Qt::red);
this->ui->lbe_red->setPalette(colr);
10.按钮的使能失能控制
以下两行语句效果相同,都是失能按钮功能:
this->ui->btn_led1_Ctrl->setDisabled(true);
this->ui->btn_led1_Ctrl->setEnabled(false);
11.文本显示框设置最大显示行数
this->ui->tb_rx_buf->document()->setMaximumBlockCount(10);
程序的图标、标题设置和打包发布
你不希望窗口的标题是“Dialog”吧,所以添加一个标题和一个好看的图标还是很有必要的。
1.添加标题
添加窗口标题还是很简单的,一行代码:
this->setWindowTitle("串口控制LED - By wcc ");
2.添加icon图标
-
找一个好看的图标,格式一定要是.ico,像素大小推荐128*128
-
命名为my_app.ico,名字无所谓,不要有中文就好了,放在工程目录下,即和.pro文件和.cpp文件同一个目录。
-
打开.pro文件,最底下添加一行:RC
ICONS = my
app.ico
重新编译就可以看到这种效果了。
3.程序文件的生成
构建选项改成Release版本,编译完成后,会在Release目录下生成一个.exe文件,把这个文件单独拷出来放在一个空白的文件夹里,如
D
:
\QT_Prj\Export\UART_Demo
.
exe
,可以运行试一下,会提示缺少运行所需要的dll组件
而且,这个文件如果单独拷贝到其他没有安装Qt环境的电脑上,也是不能运行的。
所以我们需要添加一些当前程序运行所需要的组件才能正常运行,但是需要添加哪些文件呢?不用担心,Qt早已经想好了,运行MinGW工具:
先进入到exe文件所在的文件夹中:
cd
/
d D
:
\QT_Prj\Export
然后输入命令:
windeployqt UART_Demo
.
exe
此时,打开exe文件所在的文件夹,可以看到Qt已经为我们添加好了,当前程序运行所需要的组件了。
这个时候,如果想给别人分享你开发好的上位机软件,就可以直接把这个文件夹拷贝给他。当然也可以安装一个
Enigma