QT串口类的使用,折线图绘制,导出数据到wps表格。crc校验实现

串口操作具体方法:

  首先下载QextSerial串口操作文件夹。

  构造函数将当前电脑的串口信息显示在comboBox控件上,等待选择;

foreach( const QSerialPortInfo &Info,QSerialPortInfo::availablePorts())//读取串口信息
      {
 
          QSerialPort serial;
          serial.setPort(Info);        
          if( serial.open( QIODevice::ReadWrite) )//如果串口是可以读写方式打开的
          {
              ui->comboBox_portName_first->addItem(Info.portName());//在comboBox那添加串口号
              serial.close();//然后自动关闭等待人为开启(通过那个打开串口的PushButton)
          }
      }
 

点击打开串口按钮后进行相应串口类的配置

QString portname = ui->comboBox_portName_first->currentText();
    myCom = new QextSerialPort(portname);
 
        //串口数据读取连接
        connect(myCom, SIGNAL(readyRead()), this, SLOT(readMyCom()) );
 
        // 波特率
        myCom->setBaudRate(BAUD9600);
        // 数据位
        myCom->setDataBits(DATA_8);
        // 设置校验位
        myCom->setParity(PAR_NONE);
        // 设置停止位
        myCom->setStopBits(STOP_1);
        // 设置数据流
        myCom->setFlowControl(FLOW_OFF);
 
 
        myCom->setTimeout(200);
        bool flag = myCom->open(QIODevice::ReadWrite);
        if(false == flag)
        {
            QMessageBox::warning(this,tr("Warning"),tr("串口打开失败"));
        }

折线图绘制

然后添加qcustomplot.h和qcustomplot.cpp文件  提升一个widget控件。

 static QVector<double> temp(1000),temp1(1000); //全局静态变量,设置折线图的横纵坐标
    if(num1>999){ //小于1000按原值,大于1000按1000
        num1=1000;
    }
    if(num1<1000) //小于1000直接插入
    {
        temp1[num1]=num1;
        if(ui->UNITDOSE->text()=="μSv/h")
         {
              temp[num1]=ui->DOSE->value();
         }else{
              temp[num1]=ui->DOSE->value()*1000;
         }
 
    }else{
       for(int i=0;i<999;i++) //大于1000改变最后一位,按数组前移
        {
           temp[i]=temp[i+1];
        }
       if(ui->UNITDOSE->text()=="μSv/h")
        {
            temp[999]=ui->DOSE->value();
        }else{
            temp[999]=ui->DOSE->value()*1000;
       }
    }
    num1++;
    ui->tem_plot->addGraph(); //添加折线
    QPen pen; //画笔类
    pen.setWidth(1);
    pen.setBrush(Qt::red); //折线变成红色
    ui->tem_plot->graph(0)->setPen(pen);
    //ui->tem_plot->xAxis->setLabel("时间/s");
    //ui->tem_plot->yAxis->setLabel("dose/μsv/h");
    ui->tem_plot->xAxis->setRange(0,1000); //设置x轴的横坐标范围
    ui->tem_plot->graph(0)->rescaleValueAxis(); //设置y轴自动变化
    ui->tem_plot->graph(0)->setData(temp1,temp);
    ui->tem_plot->replot();
 

设置tablewidget的数据导入excel表格中

  ui->tableWidget->setColumnCount(6);    //设置列数
     ui->tableWidget->setRowCount(10000);        //设置行数/
     ui->tableWidget->setColumnWidth(0,160);
     QStringList header;
     header<<"时间"<<"TOTAL"<<"DOSE"<<"CPS"<<"CPM"<<"温度";
     ui->tableWidget->setHorizontalHeaderLabels(header);//水平
     //自动调整宽度w
     ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
 

添加数据

    QDateTime current_date_time = QDateTime::currentDateTime();
    QString current_date = current_date_time.toString("yyyy-MM-dd hh:mm:ss ddd");
    ui->tableWidget->setItem(num,0,new QTableWidgetItem(current_date));
    ui->tableWidget->setItem(num,1,new QTableWidgetItem(QString::number(ui->TOTAL->value())+ui->UNITTOTAL->text()));
    ui->tableWidget->setItem(num,2,new QTableWidgetItem(QString::number(ui->DOSE->value())+ui->UNITDOSE->text()));
    ui->tableWidget->setItem(num,3,new QTableWidgetItem(QString::number(ui->lcdNumber_2->value())+ui->label_2->text()));
    ui->tableWidget->setItem(num,4,new QTableWidgetItem(QString::number(ui->SHOWCPM->value())+ui->UNITCPM->text()));
    ui->tableWidget->setItem(num,5,new QTableWidgetItem(QString::number(ui->lcdNumber_5->value())+ui->label->text()));
    num++;
 

导出数据到execl

QString fileName = QFileDialog::getSaveFileName(this, tr("Save File")," ",tr("file (*.csv)"));
        if (!fileName.isEmpty())
        {
            QFile file(fileName);
            bool ret = file.open( QIODevice::Truncate | QIODevice::WriteOnly);
            if(!ret)
                return;
 
            QTextStream stream(&file);
            QString conTents;
            QHeaderView * header = ui->tableWidget->horizontalHeader() ;
            if (header)
            {
                for ( int i = 0; i < header->count(); i++ )
                {
                    QTableWidgetItem *item = ui->tableWidget->horizontalHeaderItem(i);
                    if (!item)
                    {
                        continue;
                    }
                    conTents += item->text() + ",";
                }
                conTents += "\n";
            }
 
            for ( int i = 0 ; i < ui->tableWidget->rowCount(); i++ )
            {
                for ( int j = 0; j < ui->tableWidget->columnCount(); j++ )
                {
 
                    QTableWidgetItem* item = ui->tableWidget->item(i, j);
                    if ( !item )
                        continue;
                    QString str = item->text();
                    str.replace(","," ");
                    conTents += str + ",";
                }
                conTents += "\n";
            }
            stream << conTents;
            file.close();
        }

crc校验运用

获得crc校验值

//获得CRC16值
//puchMsg:要校验的数组
//usDataLen:数组长度
quint16 MainWindow::crc16ForModbus(const QByteArray &data)
{
    static const quint16 crc16Table[] =
    {
        0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
        0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
        0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
        0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
        0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
        0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
        0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
        0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
        0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
        0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
        0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
        0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
        0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
        0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
        0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
        0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
        0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
        0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
        0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
        0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
        0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
        0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
        0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
        0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
        0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
        0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
        0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
        0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
        0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
        0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
        0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
        0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
    };
 
    quint8 buf;
    quint16 crc16 = 0xFFFF;
 
    for ( auto i = 0; i < data.size(); ++i )
    {
        buf = data.at( i ) ^ crc16;
        crc16 >>= 8;
        crc16 ^= crc16Table[ buf ];
    }
 
    return crc16;
}

调用方法

 QString zhuji = ui->baihao->currentText(); 
 
    QByteArray data;
    data=("020200000010");
    data[1]=zhuji[0].toLatin1();
    qDebug()<<data[1];
    auto data1 = QByteArray::fromHex(data); //QBytearray数据类型变成16进制
    auto crc16ForModbus = MainWindow::crc16ForModbus( data1 );//计算一串16进制数据的crc校验码
    qDebug() << "crc16ForModbus:"   << crc16ForModbus   << QString::number( crc16ForModbus, 16 );
    QString str=QString::number(crc16ForModbus, 16 );
    int len = str.length();
    if(len%2 == 1)   //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
    {
           str = str.insert(0,'0'); //insert(int position, const QString & str)
    }
    qDebug()<<str;
    data[12]=str[2].toLatin1(); //QString变成QByteArray类型;
    data[13]=str[3].toLatin1(); 
    data[14]=str[0].toLatin1();
    data[15]=str[1].toLatin1();
    qDebug()<<data;
    data=QByteArray::fromHex(data); //将QString类型变成16进制发送到串口
    myCom->write(data);//发送到串口

//位解析

QString MainWindow:: splitPath(QString c)
{
 
    int length = c.length();
    const char * p = c.toLocal8Bit().data();
    char n;
    QString q;
 
    if(length == 2){
 
        n=*p;
        QString qs0= findBinary(n);
 
        n=*(p+1);
        QString qs1= findBinary(n);
 
        q = qs1+qs0;
    }else{
 
        n=*p;
        QString qs0= findBinary(n);
 
        n=*(p+1);
        QString qs1= findBinary(n);
 
        n=*(p+2);
        QString qs2= findBinary(n);
 
        n=*(p+3);
        QString qs3= findBinary(n);
 
        q = qs1+qs0+qs3+qs2;
    }
 
    qDebug() << q;
    return q;
}
 
QString MainWindow::findBinary(char c)
{
    QString qs;
 
    switch (c)
    {
    case '0':
        qs = "0000";
        break;
    case '1':
        qs = "1000";
        break;
    case '2':
        qs = "0100";
        break;
    case '3':
        qs = "1100";
        break;
    case '4':
       qs = "0010";
        break;
    case '5':
       qs = "1010";
        break;
    case '6':
       qs = "0110";
        break;
    case '7':
       qs = "1110";
        break;
    case '8':
       qs = "0001";
        break;
    case '9':
       qs = "1001";
        break;
    case 'a':
        qs = "0101";
        break;
    case 'b':
       qs = "1101";
        break;
    case 'c':
       qs = "0011";
        break;
    case 'd':
       qs = "1011";
        break;
    case 'e':
       qs = "0111";
        break;
    case 'f':
       qs = "1111";
        break;
    default:
        break;
    }
 
    return qs;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值