与下位机,单片机通信少不了使用串口进行通信,Qt 也提供了串口通信的类。
使用的时候在 pro 添加这句导入模块
QT += serialport
1.连接串口 第一步就是 要先获取到 可连接的所有的串口的名字
获取到串口名字列表以后,我们需要选择一个需要连接的 (自行根据选择)
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if (serial.open(QIODevice::ReadWrite))
{
portList.push_back(serial.portName());
serial.close();
}
}
2.根据串口名字 打开串口
进行初始化串口
void frmserialport::inialSerialPort() //初始化串口(串口号、波特率、数据位、停止位、流控制)
{
m_flag = 0;
QList portList;
QStringList baudList;
QStringList parityList;
QStringList dataBitList;
QStringList stopBitList;
QStringList flowList;
baudList<<"9600"<<"115200"<<"460800";
dataBitList<<"8";
parityList<<"无";
stopBitList<<"1";
flowList<<"无";
}
void frmserialport::on_btn_Open_clicked() //打开串口
{
m_pSerialPort = new QSerialPort(this);
m_pSerialPort->setPortName(ui->cbox_PortName->currentText()); //串口名
m_pSerialPort->setBaudRate(ui->cbox_BaudRate->currentText().toInt()); //波特率
switch (ui->cbox_DataBit->currentIndex()) {
case 0:
m_pSerialPort->setDataBits(QSerialPort::Data8); //数据位为8位
break;
default:
break;
}
switch (ui->cbox_Parity->currentIndex()) {
case 0:
m_pSerialPort->setParity(QSerialPort::NoParity); //无校验位
break;
default:
break;
}
switch (ui->cbox_StopBit->currentIndex()) {
case 0:
m_pSerialPort->setStopBits(QSerialPort::OneStop); //一位停止位
break;
default:
break;
}
switch (ui->cbox_Flow->currentIndex()) {
case 0:
m_pSerialPort->setFlowControl(QSerialPort::NoFlowControl); //无流控制
break;
default:
break;
}
if (!m_pSerialPort->open(QIODevice::ReadWrite)){
QMessageBox::information(this,"提示","串口连接失败");
}
else{
QMessageBox::information(this,"提示",ui->cbox_PortName->currentText() + tr("连接成功"));
ui->btn_Open->setEnabled(false);
ui->btn_Close->setEnabled(true);
ui->btn_Send->setEnabled(true);
}
connect(m_pSerialPort,&QSerialPort::readyRead,this,&frmserialport::serialReadData);
3.发送数据和清除数据
void frmserialport::on_btn_Send_clicked() //发送数据
{
QString strMessage = ui->txt_Send->toPlainText();
sendCMD(strMessage);
}
void frmserialport::on_btn_Clear_clicked() //清除
{
if (!ui->txt_Receive->toPlainText().isEmpty()){
ui->txt_Receive->clear();
ui->btn_Clear->setEnabled(false);
}
}
4.关闭串口
void frmserialport::on_btn_Close_clicked() //关闭串口
{
m_pSerialPort->clear();
m_pSerialPort->close();
delete m_pSerialPort;
m_pSerialPort = nullptr;
m_flag = 0;
ui->btn_Open->setEnabled(true);
ui->btn_Close->setEnabled(false);
ui->btn_Send->setEnabled(false);
}
1.QCharts的使用可以参考《Qt开发技术:QCharts》
链接:Qt开发技术:QCharts
2.想要绘制曲线图需要定义画布 , 线 , 轴 ,我的x轴是用实时时间所以要加多一个定时器
//绘图变量和坐标
QDateTimeAxis *axisX_aX; //用时间表示x轴
QDateTimeAxis *axisX_aY;
QDateTimeAxis *axisX_aZ;
QValueAxis *axisY_aX; //aX数据,表示y轴
QValueAxis *axisY_aY; //aY数据
QValueAxis *axisY_aZ; //aZ数据
QTimer *timer; //图表的计时器
QChart *chart;
QSplineSeries *series_aX; //数据点
QSplineSeries *series_aY;
QSplineSeries *series_aZ;
3.设置数据,定义绘图
axisX_aX->setFormat("hh:mm:ss");
axisY_aX->setRange(-3,3);
chart->addSeries(series_aX);
axisX_aX->setTickCount(10);
axisY_aX->setTickCount(10);
axisX_aX->setTitleText("实时时间");
axisY_aX->setTitleText("加速度A(G):");
series_aX->setPen(QColor(Qt::red));
axisY_aX->setLinePen(peny);
axisX_aX->setLinePen(peny);
chart->addAxis(axisX_aX , Qt::AlignBottom);
chart->addAxis(axisY_aX , Qt::AlignLeft);
series_aX->attachAxis(axisX_aX);
series_aX->attachAxis(axisY_aX);
QDateTime currentTime = QDateTime::currentDateTime(); //实时时间
chart->axisX()->setMin(QDateTime::currentDateTime().addSecs(-60*1));
chart->axisX()->setMax(QDateTime::currentDateTime().addMSecs(0));
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
series_aX->append(currentTime.toMSecsSinceEpoch() , aX); //提供x,y轴数据
最后就实现啦!
我是qt小白,刚开始学习qt不久,如果有问题请大家多多指教,感谢大家阅读,觉得不错的话点个赞收藏下呗!!最后列出几个我写这个项目时遇到的问题吧!
解决方案:串口延时接收数据
处理思路:创建两个槽函数(SLOT),当串口有数据应答时系统会给一个 readyRead()信号,用槽函数接收一个信号,并处理。在进入到这个槽函数后设置一个定时,当定时走完会有一个timeout()信号,用另一个槽函数处理定时完成后的事情。
这里感谢Humboldt大佬的思路。
//connect(timer,SIGNAL(timeout()),this,SLOT(RealtimeDataSlot())); 没有延时接受数据前的槽函数
connect(timer,SIGNAL(timeout()),this,SLOT(DrawLine()));
//connect(m_pSerialPort,&QSerialPort::readyRead,this,&frmserialport::serialReadData); //没有延时接受数据前的槽函数
//延时接收数据
connect(m_pSerialPort,SIGNAL(readyRead()),this,SLOT(on_serialReadData())); //当有数据来是显示
connect(&timer1,SIGNAL(timeout()),this,SLOT(serialReadData())); //当定时结束时进入
2.分离串口数据
我采用的是字符串分隔的方法
因为串口读取到的数据转成QString后长度是不一定的,所以用到了索引的方法解决。
QByteArray receiveData;
receiveData = m_pSerialPort->readAll();
qDebug()<<"Re:"<
成功截取到后就转成Double类型提供Y轴数据给曲线。
如果侵犯版权等问题,私聊马上删除。