李氏牛仔网站建设风,网站开发方倍工作室,常熟网站制作设计,周到的网站建设文章目录 一、功能简介二、串口助手实现2.1 创建UI2.2 扫描可用串口2.3 配置波特率2.4 配置数据位2.5 配置停止位2.6 配置校验位2.7 打开/关闭串口2.8 刷新串口2.9 发送新行2.10 串口发送2.11 串口接收显示2.12 清空接收窗口2.13 定时发送2.14 固定窗口大小 三、总结3.1 将信号… 文章目录 一、功能简介二、串口助手实现2.1 创建UI2.2 扫描可用串口2.3 配置波特率2.4 配置数据位2.5 配置停止位2.6 配置校验位2.7 打开/关闭串口2.8 刷新串口2.9 发送新行2.10 串口发送2.11 串口接收显示2.12 清空接收窗口2.13 定时发送2.14 固定窗口大小 三、总结3.1 将信号与槽函数关联3.2 优化方向 一、功能简介
最近尝试用QT实现了一个串口调试驻守于作为一个刚接触QT的小白当然是站在巨人的肩膀上完成了这个小项目。在实现过程中学习了许多内容这里简单总结一下。
本次设计的串口调试助手只实现了一些基本功能
打开/关闭串口刷新串口串口收/发定时发送清空接收窗口选择串口配置波特率数据位停止位和校验位
实现效果如下 二、串口助手实现
下面首先再明确一下功能。打开串口时会提示“串口打开成功”或者“串口打开失败”。打开成功后会禁用选择串口刷新串口配置波特率数据位停止位和校验位的功能。关闭串口后恢复使用。 由于使能和失能控件的方法比较简单就在这介绍不再单独介绍了。
失能控件
ui-控件名-setEnabled(false);使能控件
ui-控件名-setEnabled(true);2.1 创建UI
在开始程序编写前先创建UI界面。创建UI时使用的控件如果和博主的不同的话程序可能会不能直接复用需要注意一下。本项目主要用到了这些控件
QLabel 该控件是标签用来提示比如UI中的“串口”“波特率”等字样就是用的QLabel控件。QComboBox 该控件为多选下拉框。UI中可选串口号波特率数据为停止位校验位这些都是使用的该控件。双击控件可以编辑下拉框成员。QPushButton 该控件为按钮。UI中的发送打开/关闭串口等都是使用的该控件。QLineEdit QLineEdit是一个单行文本编辑器UI中定时时间输入发送内容输入框都是使用的该控件。QCheckBox QCheckBox为复选框控件UI中“定时发送”和“发送新行”使用的就是该控件。该控件可以添加一个“stateChange(int)”槽函数。可以通过int变量的值来判断复选框是否被选中。如果复选框被选中int变量的值为2未被选中int变量的值为0。QTextBroswer 该控件是一个文本阅读器UI中串口接收内容的显示用到了该控件。
2.2 扫描可用串口
扫描可用串口的方法是 // 搜索所有可用串口foreach (const QSerialPortInfo inf0, QSerialPortInfo::availablePorts()) {serialNamePortinf0.portName();}扫描可用串口用在两个地方首先是用在刚打开软件时扫描当前可用串口。扫描到可用串口后需要将可用串口号显示到UI的控件上。 // 将可用串口显示到serialBoxui-serialBox-addItems(serialNamePort);其次用到扫描可用串口的地方就是“刷新串口”按键后面会有介绍。
2.3 配置波特率
打开串口时会根据UI界面波特率的下拉框中选择的值配置波特率。配置方法是直接获取下拉框中的字符将其转换成int型变量然后配置波特率。 // toInt将baudrateBox中的字符串转换成整型数serialPort-setBaudRate(ui-baudrateBox-currentText().toInt()); // 波特率2.4 配置数据位
配置数据位时无法像配置波特率一样直接获取下拉框中的字符串转换成int型直接赋值。这里选择先将数据位下拉框内容转换成int型然后用switch语句配置数据位 // 用switch语句设置数据位switch (ui-databitBox-currentText().toInt()){case 5:serialPort-setDataBits(QSerialPort::Data5); // 5位break;case 6:serialPort-setDataBits(QSerialPort::Data6); // 6位break;case 7:serialPort-setDataBits(QSerialPort::Data7); // 7位break;case 8:serialPort-setDataBits(QSerialPort::Data8); // 8位break;default:serialPort-setDataBits(QSerialPort::Data8); // 8位break;}2.5 配置停止位
配置停止位也无法直接使用数字这里使用另一个方法。获取停止位下拉框中的字符利用if语句完成停止位的配置。 // 设置停止位直接用字符做判断if (ui-stopbitBox-currentText() 1){serialPort-setStopBits(QSerialPort::OneStop); // 1位停止位}else if (ui-stopbitBox-currentText() 1.5){serialPort-setStopBits(QSerialPort::OneAndHalfStop); // 1.5位停止位}else if (ui-stopbitBox-currentText() 2){serialPort-setStopBits(QSerialPort::TwoStop); // 2位停止位}else // 默认1位停止位{serialPort-setStopBits(QSerialPort::OneStop); // 1位停止位}2.6 配置校验位
配置校验位与配置停止位的方法相同也是使用if语句。 // 设置校验位也用if直接判断字符串if (ui-checkBox-currentText() None){serialPort-setParity(QSerialPort::NoParity); // 无校验}else if (ui-checkBox-currentText() Odd){serialPort-setParity(QSerialPort::OddParity); // 奇校验}else if (ui-checkBox-currentText() Even){serialPort-setParity(QSerialPort::EvenParity); // 偶校验}else // 默认无校验{serialPort-setParity(QSerialPort::NoParity); // 无校验}2.7 打开/关闭串口
打开串口和关闭串口使用的是同一个按钮。刚打开是按钮为“打开串口”。打开串口成功后将按钮上显示的字符修改为“关闭串口”。点击按钮时根据按钮上的字符来判断是执行打开串口还是关闭串口。实现框架如下 // 打开串口if (ui-openButton-text() 打开串口){// 打开串口}else // 关闭串口{// 关闭串口}当然也可以使用标志位实现。
打开串口和关闭串口的函数为 bool open(OpenMode mode) override;void close() override;2.8 刷新串口
刷新串口的功能是重新扫描当前可用串口然后将当前可用串口号显示到串口的下拉框中。扫描方法上面已经介绍过了需要注意的是点击刷新串口扫描完当前可用串口后需要将之前串口下拉框中的显示内容清除掉再重新显示。
// 刷新串口
void MainWindow::on_refrashButton_clicked()
{QStringList serialNamePort;// 先清除一下之前串口号中的显示内容ui-serialBox-clear();// 搜索所有可用串口foreach (const QSerialPortInfo inf0, QSerialPortInfo::availablePorts()) {serialNamePortinf0.portName();}// 将可用串口显示到serialBoxui-serialBox-addItems(serialNamePort);
}2.9 发送新行
发送新行是使用复选框实现的。在发送前会先检测是否勾选了发送新行判断方法如下 // 如果发送新行被勾选if (ui-newLineBox-isChecked()){// 发送新行}2.10 串口发送
按下“串口发送”按钮首先获取输入的内容然后根据是否需要发送新行来判断是否需要在结尾增加换行。“串口发送”按钮的槽函数如下。
// 发送按钮
void MainWindow::on_sendButton_clicked()
{// 如果发送新行被勾选if (ui-newLineBox-isChecked()){// 多行文本框用sendEdit()获取内容// QLineExit内容用text()获取内容serialPort-write(ui-sendEdit-text().toLatin1() \r\n); // 串口发送数据}else{serialPort-write(ui-sendEdit-text().toLatin1()); // 串口发送数据}
}2.11 串口接收显示
上位机需要显示串口接收到的内容。有一个reayRead信号一旦上位机接收到数据就会想应该信号。将该信号绑定到显示接收内容的槽函数一旦接收到数据就开始显示。绑定方法如下 // 将readyRead信号链接到Read_Data函数connect(serialPort, QSerialPort::readyRead, this, MainWindow::Read_Data);显示数据的槽函数如下。
// 读取接收到的数据并显示
void MainWindow::Read_Data()
{QByteArray buf;// 读取全部接收数据buf serialPort-readAll();// 如果接收内容非空if(!buf.isEmpty()){QString str ui-receiveBrowser-toPlainText();str tr(buf);ui-receiveBrowser-clear();ui-receiveBrowser-append(str);}buf.clear();
}2.12 清空接收窗口
// 清除窗口
void MainWindow::on_clearButton_clicked()
{ui-receiveBrowser-clear();
}2.13 定时发送
定时发送需要用到定时器需要先添加定时器的头文件
// 定时器头文件
#includeQTimer然后添加一个定时发送时间的类成员 // 定时发送时间间隔QTimer *timSend;将倒计时结束信号关联到串口发送槽函数 // 定时发送timSend new QTimer;timSend-setInterval(1000); // 设置默认值1000ms// 定时发送与发送按键函数关联connect(timSend,QTimer::timeout,this,[](){on_sendButton_clicked();});定时发送功能时使用复选框实现的。关于复选框上面介绍了可以根据一个int型变量的值来判断选中状态。定时发送勾选后需要失能定时时间编辑和发送按钮。取消勾选后恢复定时器时间编辑和发送按钮的使用。定时发送函数如下
// 定时发送
void MainWindow::on_timeSendBox_stateChanged(int arg1)
{// 获取复选框选中状态// 选中值为2未选中值为0if (arg1 0){// 结束计时timSend-stop();// 恢复定时时间可编辑ui-timeEdit-setEnabled(true);// 恢复发送按钮ui-sendButton-setEnabled(true);}else{// 根据设置时间开始计时timSend-start(ui-timeEdit-text().toInt());// 禁用定时时间可编辑ui-timeEdit-setEnabled(false);// 禁用发送按钮ui-sendButton-setEnabled(false);}
}2.14 固定窗口大小
为了防止窗口大小改变这里选择禁用最大化按钮固定窗口大小防止被鼠标拖动放大。程序实现方法如下 // 禁用最大化按钮setWindowFlags(windowFlags()~Qt::WindowMaximizeButtonHint);// 禁止拖动窗口大小setFixedSize(673,620);窗口大小可以在UI文件中查看选中窗口查看右侧属性栏。 三、总结
3.1 将信号与槽函数关联
之前一直使用的是右键控件选择转到槽来实现的关联。这里学习到了利用“connect”关联信号与槽函数。connect基本格式如下
connect(控件名, SIGNAL(要关联的信号), this, SLOT(槽函数));也可以像上面关联readyRead信号时那样写
connect(serialPort, QSerialPort::readyRead, this, MainWindow::Read_Data);或者像关联定时结束信号时那样写 connect(timSend,QTimer::timeout,this,[](){on_sendButton_clicked();});3.2 优化方向
正如最开始所说本文只是实现了简单的串口助手的功能后续可以优化的方向还有很多。比如
支持显示中文支持保存接收内容下方显示接收到的内容字符数增加时间戳等
但是针对本人平时的使用已经足够了因此暂时并不考虑优化后续使用过程中遇到问题再考虑。有意思的是本人使用该串口助手访问API时能够看到API返回来的中文。下图是利用WIFI模块访问心知天气API返回的数据。