QT--串口读取数据并展示实时波形图

1.串口读取数据

与下位机,单片机通信少不了使用串口进行通信,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);
}

2.展示实时波形图(使用QCharts)

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--串口读取数据并展示实时波形图_第1张图片

 

我是qt小白,刚开始学习qt不久,如果有问题请大家多多指教,感谢大家阅读,觉得不错的话点个赞收藏下呗!!最后列出几个我写这个项目时遇到的问题吧!

 

1.读取到的串口数据会分段

解决方案:串口延时接收数据

处理思路:创建两个槽函数(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轴数据给曲线。

 

如果侵犯版权等问题,私聊马上删除。

你可能感兴趣的:(qt,串口通信)