这个项目是18年初寒假开始的,初始想法是利用寒假时间学习Qt开发并且顺便把毕业设计做出来,后来毕业设计做出来了,这个项目也完成了,然后又投入了二战,所以分享开发的过程的Blog却一直没有时间写,现在收到了录取通知,又想起这个事情,可能思绪不太连贯了,但我还是想把这个事情坐下来。
创建串口调试界面
串口调试器的主要需求:
- 显示来自串口接收到的信息;
- 向串口发送中断;
- 配置串口。
根据需求设计UI界面
其中界面的设计主要用到了Qlabel
、QTextEdit
、QCamboBox
、QPushButton
,其中较为复杂的应该是QTextEdit组件的输出格式控制。
配置串口
由于Qt5内置了串口类,所以我们可以通过直接调用类方法进行串口的配置,这真的是一件十分Nice的事情,之前我也有通过Keil开发过C51的串口模块,相比较而言真的是能省不少心。
当用户通过LogIn界面登陆进入串口界面时,此时程序已经开始查找当前可用串口,显示在端口号处。
//查找可用的串口
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
ui->combox->addItem(serial.portName());
serial.close();
}
}
//设置波特率下拉菜单默认显示第三项
ui->baudrate->setCurrentIndex(3);
//关闭发送按钮的使能
// ui->openport->setEnabled(false);
qDebug()<<tr("界面设定成功!");
打开串口
点击打开串口,系统自动读取用户所设置的串口配置,这里需要注意的是虽然有校验位选项,但是我没有使用,所以直接使用了serial->setParity(QSerialPort::NoParity)
。从逻辑上来讲,当用户以当前设置打开了串口,设置变不能再更改了,所以在点击打开串口后,应将QCamboBox
关闭使能,然后将QPushButton
的文字内容改成“关闭串口”。
serial = new QSerialPort;
//设置串口名
serial->setPortName(ui->combox->currentText());
//打开串口
serial->open(QIODevice::ReadWrite);
serialInfo = serialInfo + "Mode: ReadWrite" + '\n';
//设置波特率
serial->setBaudRate(ui->baudrate->currentText().toInt());
//设置数据位数
switch(ui->databit->currentIndex())
{
case 5: serial->setDataBits(QSerialPort::Data5); break;
case 6: serial->setDataBits(QSerialPort::Data6); break;
case 7: serial->setDataBits(QSerialPort::Data7); break;
case 8: serial->setDataBits(QSerialPort::Data8); break;
default: break;
}
serialInfo = serialInfo + "Data Bit: " + ui->databit->currentText() + '\n';
//设置奇偶校验
switch(ui->conparebit->currentIndex())
{
case 0: serial->setParity(QSerialPort::NoParity); break;
default: break;
}
serialInfo = serialInfo + "Conpare Bit" + ui->conparebit->currentText() + '\n';
//设置停止位
switch(ui->stopbit->currentIndex())
{
case 1: serial->setStopBits(QSerialPort::OneStop); break;
case 2: serial->setStopBits(QSerialPort::TwoStop); break;
default: break;
}
serialInfo = serialInfo + "Stop Bit" + ui->stopbit->currentText() + '\n';
//设置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);
serialInfo = serialInfo + "FlowControl: No flow control." + '\n';
//关闭设置菜单使能
ui->combox->setEnabled(false);
ui->baudrate->setEnabled(false);
ui->databit->setEnabled(false);
ui->conparebit->setEnabled(false);
ui->stopbit->setEnabled(false);
ui->openport->setText(tr("关闭串口"));
ui->send->setEnabled(true);
//连接信号槽
QObject::connect(serial, &QSerialPort::readyRead, this, &usr::Read_Data);
log("[usr.cpp]-[on_openport_clicked()]: System Start.");
log("[usr.cpp]-[on_openport_clicked()]" +'\n' + serialInfo);
发送中断并获取当前光照强度
发送中断是获取数据的最基本的方式,获取实时数据或者定时获取数据归根结底都是基于发送中断于定时发送中断实现的。得益于Qt5串口类的封装,发送中断变得很简洁。
//向单片机发送check
void usr::sendchk()
{
QString chk = "check";
serial->write(chk.toLatin1());
log("[usr.cpp]-[sendchk()]: CHECK has been sent.");
}
定时监控
通过定时的向串口发送中断获取信息,来起到监控数据的功能。
void usr::on_startAutoControl_clicked()
{
if(token == false)
{
qDebug()<<tr("token == false");
ui->startAutoControl->setText(tr("暂停监控"));
qDebug()<<tr("暂停监控");
token = true;
qDebug()<<tr("token赋值为true");
on_autoControlSwitch_stateChanged(Qt::Checked);
log("[usr.cpp]-[on_startAutoControl_clicked()]: Auto Control has been started.");
}
else if(token == true)
{
qDebug()<<tr("token == true");
ui->startAutoControl->setText(tr("开始监控"));
qDebug()<<tr("开始监控");
token = false;
qDebug()<<tr("token赋值为false");
on_autoControlSwitch_stateChanged(Qt::Unchecked);
log("[usr.cpp]-[on_startAutoControl_clicked()]: Auto Control has been stopped.");
}
}
定时功能使用了QTimer类
,并且通过槽函数机制链接到sendchk()函数
给串口发送中断。
//开启自动监控
void usr::on_autoControlSwitch_stateChanged(int arg1)
{
if(arg1 == Qt::Checked)
{
qDebug()<<tr("timer == checked"); //设置定时器
timer = new QTimer(this);
timer->setInterval(20000); //设置时间间隔
connect(timer,SIGNAL(timeout()),this,SLOT(sendchk())); //链接槽函数
qDebug()<<tr("Timer has been inited!");
timer->start(1000); //开始
log("[usr.cpp]-[on_autoControlSwitch_stateChanged]: QTimer has been started.");
}
if(arg1 == Qt::Unchecked)
{
qDebug()<<tr("arg1 == unchecked");
timer->stop(); //暂停定时器
qDebug()<<tr("已暂停定时器");
log("[usr.cpp]-[on_autoControlSwitch_stateChanged]: QTime