Qt 实现串口调试实用程序(下)
本文是 Qt 实现串口调试实用程序(上)的内容补充,所实现的程序以及所用环境与该文章无异。
功能补充
为接收显示区增加显示为十六进制形式的功能。要完成该功能,程序从串口接收缓冲中每读取 1 字节,就要以十六进制的格式向接收显示区追加。由于接收程序的实现是逐字节读取,因此只需要在接收时利用 sprintf()
函数把字符转换为十六进制即可。因此,假设以十六进制形式显示的复选框名称为 checkBoxHex
,接收数据的槽函数中
Recv+=QString::fromLocal8Bit(QBArecv);
应修改为:
if(ui->checkBoxHex->isChecked())
{
QString Temp;
foreach(QChar dat,QBArecv)
Recv+=Temp.sprintf("%02X ",(unsigned int)dat.unicode());
}
else Recv+=QString::fromLocal8Bit(QBArecv);
从 QSerialPort::readyRead
这一信号可以看出,QSerialPort
库在接收其所认定的一帧数据后就会发出这一信号,因此可根据需要增加接收时间戳这一功能。该功能需要下面的引入。
#include "QDateTime"
并且,在接收数据的槽函数中上述程序段之前添加
QDateTime current_date_time =QDateTime::currentDateTime();
QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss");
if(ui->checkBoxAddTS->isChecked()) Recv+=current_date+" < ";
为了让时间戳总位于行首,还需要在
else Recv+=QString::fromLocal8Bit(QBArecv);
之后添加:
if(ui->checkBoxAddTS->isChecked()) Recv+="\r\n";
以在显示一个数据帧后都追加换行符。
要实现发送数据时追加换行符的功能,只需要在发送数据按钮按下后判断相应复选框是否勾选,并在调用发送函数之前在要发送的数据后追加换行符。假设控制追加换行符的复选框名称为 checkBoxCRLF
,则在发送数据的函数中
auto TXdata=ui->sendText->toPlainText();
之后添加:
if(ui->checkBoxCRLF->isChecked())TXdata.append("\r\n");
细节优化
程序构建并运行后,串口设置中端口下拉列表是空的。这是因为程序初始化时并不会主动扫描串口,用户需要按一下“扫描串口”按钮,下拉列表才会被填充。为了让程序初始化后立即加载可用串口列表,串口按钮的 clicked()
槽函数应在 MainWindow
的构造函数的末尾被调用一次。
常用的串口波特率一般被认为是 115200 位每秒,数据位为 8 位,停止位为 1 位,校验位和流控制均不需要。在这些设置中,波特率和数据位下拉列表的首项并不是常用设置。使用方便起见,在构造函数的末尾添加改变下拉列表选项的程序段如下。
ui->baudRateBox->setCurrentIndex(9);
ui->portDataBitBox->setCurrentIndex(3);
其中传入的参数根据下拉列表的安排决定。
在串口开启后,除波特率以外的串口设置在本程序中并不希望用户修改,因此在串口开启后需要禁用对应控件,在串口关闭后重新启用。因此在开启(关闭)串口按钮的 clicked()
槽函数中
if(myserial->open(QIODevice::ReadWrite))
内,添加
ui->baudRateBox->setDisabled(true);
ui->portDataBitBox->setDisabled(true);
ui->stopbBox->setDisabled(true);
ui->parityBox->setDisabled(true);
ui->flowctlBox->setDisabled(true);
而在
if(!myserial->isOpen())
的 else 内,添加
ui->portNameBox->setEnabled(true);
ui->portDataBitBox->setEnabled(true);
ui->stopbBox->setEnabled(true);
ui->parityBox->setEnabled(true);
ui->flowctlBox->setEnabled(true);
增加接收时间戳功能在测试时常出现输出只有时间戳的空行,排查后发现该问题来源于接收函数接收到的空帧。因此在接收函数中针对增加时间戳的功能,在 Recv
字符串初始化后添加
if(QBArecv.length())
if(ui->checkBoxAddTS->isChecked()) Recv+=current_date+" < ";
且在
ui->IDC_RecvStatic->insertPlainText(Recv);
前,添加
if(QBArecv.length())
if(ui->checkBoxAddTS->isChecked()) Recv+="\r\n";
另外,使用 insertPlainText()
向 TextBrowser
追加字符串而不是 append()
是为了避免 append()
函数添加多余的换行符。但是使用这种方法,当其中的文本过多而需要滚动查看时,显示区并不会自动滚动到末尾。为了解决这一问题,应在接收显示区的 textChanged()
槽函数中添加:
ui->recvBox->moveCursor(QTextCursor::End);
使光标移动至末尾。
测试
保存并构建工程,按下运行 (Run) 按钮,程序运行后出现如图所示的界面。
端口选择了 /dev/ttyS0
,即开发板上的硬件 UART 0,其它选项均为初始化值。此时开启串口,程序会弹出如图所示的对话框,且串口不能开启。
选择事先连接到开发板的 CH340G 模块,其位于 /dev/ttyUSB0
,再次开启串口。此时串口能够开启。在发送区填写任意文本并按下发送数据,接收显示区应出现同样的内容,且 CH340G 模块上的 TX 和 RX 指示灯均应当闪烁,如下图所示。
勾选“增加接收时间戳”,再次发送数据,接收显示区如下图所示。可见同一组数据被拆分为 3 帧接收。
勾选“以十六进制显示”,再次发送数据,接收显示区如下图所示。
改变波特率至更低或者更高,再次发送数据时,接收显示区完整显示数据所需的时长有可见的变化,同时时间戳出现的次数也会变化,如下图。
按一下“清空接收区”,接收显示区变为空白;勾选 RTS 或 DTR,对应引脚变为低电平。
问题说明
在编写程序时,Qt Creator 在编辑器中显示 use of undeclared identifier 'MainWindow'
。Stack Overflow 上给出的解决方案是在帮助 (Help) -> 关于插件 (About Plugins…) 的对话框中取消勾选 ClangCodeModel
并重新启动 Qt Creator,如下图所示。
评论(0)
您还未登录,请登录后发表或查看评论