功能介绍
HI,大家好,今天给大家分享一个最近做的小项目,一个使用QT实现类似串口调试助手功能的作品。不过相对于常见的串口调试助手,增加了波形显示的功能。波形显示部分借鉴了这篇博客链接: link.非常感谢这位大佬,写得很详细。还有也借鉴了一些其他博主的经验,非常感谢。
代码实现
首先在工程文件.pro中添加serialport和charts,就可以使用QT集成的串口和图表绘制的功能函数
QT += core gui serialport charts
接着对UI界面进行一个简单的设计
在Widget构造函数中添加以下代码`
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QStringList serialNamePort;
serialPort = new QSerialPort(this);
connect(serialPort,SIGNAL(readyRead()),this,SLOT(serilaPortReadyRead_Slot())); /*手动关联读取函数*/
/*获取存在的串口名*/
foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) {
serialNamePort<<info.portName();
}
ui->seialCb->addItems(serialNamePort);
/*关联定时器和绘图函数*/
timer = new QTimer(this);
connect(timer , SIGNAL(timeout()) , this , SLOT(DrawLine()));
}
串口初始化以及绘图初始化函数的调用(包括了定时器初始化,定时器用于绘制数据的动态更新)
/*串口初始化配置*/
void Widget::on_openBT_clicked()
{
QSerialPort::BaudRate baudRate;
QSerialPort::DataBits dataBits;
QSerialPort::StopBits stopBits;
QSerialPort::Parity checkBits;
/*波特率*/
if(ui->baundrateCb->currentText() == "9600")
{
baudRate = QSerialPort::Baud9600;
}
else if(ui->baundrateCb->currentText() == "115200")
{
baudRate = QSerialPort::Baud115200;
}
/*数据位*/
if(ui->dataCb->currentText() == "6")
{
dataBits = QSerialPort::Data6;
}
else if(ui->dataCb->currentText() == "7")
{
dataBits = QSerialPort::Data7;
}
else if(ui->dataCb->currentText() == "8")
{
dataBits = QSerialPort::Data8;
}
/*停止位*/
if(ui->stopCb->currentText() == "1")
{
stopBits = QSerialPort::OneStop;
}
else if(ui->stopCb->currentText() == "1.5")
{
stopBits = QSerialPort::OneAndHalfStop;
}
else if(ui->stopCb->currentText() == "2")
{
stopBits = QSerialPort::TwoStop;
}
/*校验位*/
if(ui->checkCb->currentText() == "none")
{
checkBits = QSerialPort::NoParity;
}
//设置
serialPort->setPortName(ui->seialCb->currentText());
serialPort->setBaudRate(baudRate);
serialPort->setDataBits(dataBits);
serialPort->setStopBits(stopBits);
serialPort->setParity(checkBits);
if(serialPort->open(QIODevice::ReadWrite) == true)
{
QMessageBox::information(this,"提示","成功");
}
else
{
QMessageBox::critical(this,"提示","失败");
}
//画图初始化
initDraw();
timer->start(); //初始化定时器
timer->setInterval(1000);
}
画图初始化函数
/*画图初始化*/
void Widget::initDraw()
{
QPen peny(Qt::darkRed , 3 , Qt::SolidLine , Qt::RoundCap , Qt::RoundJoin);
chart = new QChart();
series = new QSplineSeries();
axisX = new QDateTimeAxis();
axisY = new QValueAxis();
chart->legend()->hide(); //隐藏图例
chart->addSeries(series); //将线添加到chart中
axisX->setTickCount(10); //设置x坐标轴格数
axisY->setTickCount(5); //设置y坐标轴格数
axisX->setFormat("hh:mm:ss"); //设置显示格式
axisY->setMin(0); //设置y轴范围
axisY->setMax(1000);
axisX->setTitleText("T"); //设置x轴名称
axisY->setLinePenColor(QColor(Qt::darkBlue)); //设置坐标轴颜色样式
axisY->setGridLineColor(QColor(Qt::darkBlue));
//axisY->setGridLineColor(QColor(Qt::darkBlue));
axisY->setGridLineVisible(false); //设置y轴网格不显示
axisY->setLinePen(peny);
axisX->setLinePen(peny);
chart->addAxis(axisX , Qt::AlignBottom); //设置坐标轴位于chart中的位置
chart->addAxis(axisY , Qt::AlignLeft);
series->attachAxis(axisX); //把数据添加到坐标轴上
series->attachAxis(axisY);
axisY->setTitleText("Y");
//把chart显示到窗口上
ui->widget->setChart(chart);
ui->widget->setRenderHint(QPainter::Antialiasing); //设置抗锯尺
}
串口接收槽函数,下位机发送格式需为 abc数据\r\n 才能正常接收
/*串口接收槽函数*/
void Widget::serilaPortReadyRead_Slot()
{
QString num;
QString recv_buf; //接收缓存
QString buf;
int recv_pos = 0; //移位
recv_buf = QString(serialPort->readAll()); //接收数据
buf = recv_buf.mid(4);
if( recv_buf.indexOf("abc") != -1) //判断是否有abc
{
num=recv_buf.mid(recv_pos,recv_buf.length()); //截取出字符大小
recv_pos=num.indexOf("\r\n"); //找出数据尾部标志的recv_pos值
num=num.mid(3,recv_pos-3); //截取数据
number=num.toInt(); //将char型数据转为int型数据
qDebug()<<number;
}
}
串口发送槽函数,发送格式为字符发送+发送新行
/*串口发送槽函数*/
void Widget::on_sendBt_clicked()
{
QByteArray Data_1 = ui->sendEdit->text().toUtf8();
Data_1.append("\r\n");
serialPort->write(Data_1);
}
画图函数
/*画图函数*/
void Widget::DrawLine()
{
QDateTime currentTime = QDateTime::currentDateTime(); //设置坐标轴显示范围
chart->axisX()->setMin(QDateTime::currentDateTime().addSecs(-60*1)); //系统当前时间的前一秒
chart->axisX()->setMax(QDateTime::currentDateTime().addMSecs(0)); //系统当前时间
series->append(currentTime.toMSecsSinceEpoch() , number); //将数据在坐标轴中画成曲线
}
经过测试,能够正常收发并显示数据。