QT反向读取CAN_TEST保存的CAN帧记录数据并提取ID和DATA

一、主要任务:读取txt的CAN帧数据内容并提取ID和DATA

txt内容如下:

0        接收   0x0068ff75          0x00000110  数据帧  标准帧  0x08       00 00 00 00 00 00 00 00 
1        接收   0x0068ff7a          0x00000115  数据帧  标准帧  0x08       03 34 03 35 03 36 03 37 
2        接收   0x0068ff7f          0x00000110  数据帧  标准帧  0x08       00 00 00 00 00 00 00 00 
3        接收   0x0068ff84          0x0000012b  数据帧  标准帧  0x08       0c 08 0c 09 0c 0a 0b ef 
4        接收   0x0068ff88          0x00000115  数据帧  标准帧  0x08       02 ba 02 bb 02 bc 02 bd 
5        接收   0x0068ff8d          0x00000169  数据帧  标准帧  0x08       0b fb 0b fc 0b fd 0b fe 
6        接收   0x0068ff92          0x00000116  数据帧  标准帧  0x08       02 ba 02 bb 02 bc 02 bd 

二、前期打印效果预览

       如图:

三、实现步骤

1、建立浏览文件UI,用来查找浏览CAN记录文本。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->setWindowTitle("文件浏览");
    this->setMaximumSize(600,600);
    this->setMinimumSize(600,300);
    filename = new QLineEdit(this);
    filename->setGeometry(QRect(50,50,230,25));
    button  = new QPushButton(this);
    button->setGeometry(QRect(280,50,80,25));
    button->setText("浏览");
    connect(button,SIGNAL(clicked()),this,SLOT(showFiles()));    
}

void MainWindow:: showFiles()
{
    QString str = QFileDialog::getOpenFileName(this,"open file","/","text\
    file(*.txt);;C file(*.cpp);;All file(*.*)");
    filename->setText(str.toUtf8());
    loadFile(str);
}
/**
*功能:加载文档并转换成数据流
*/
void MainWindow::loadFile(QString filename)
{  
    QFile file(filename);
    if(file.open(QIODevice::ReadOnly|QIODevice::Text))
    {
        QTextStream textStream(&file);

        while(!textStream.atEnd())
        {
            buf = textStream.readLine();
            ParseData(buf);//解析数据函数          
        }

    } 
}

2、ParseData()函数,解析如下类型的数据,提取如类型的数据的id和data数据段

      1        接收   0x0068ff7a          0x00000115  数据帧  标准帧  0x08       03 34 03 35 03 36 03 37 

SIMPLEFRAMES MainWindow::ParseData(QString buf)
{
    QByteArray ByteBuf,ByteBuf1;
    int t,j,index;
    uint8_t RevData[8]={0};
    ByteBuf=NULL,ByteBuf1=NULL;
    uint8_t temp;
    uint32_t id_text;
    t = 0,index=0,j=0,id_text=0;
    if(buf.size()>2)
    {
        ByteBuf = buf.toLatin1();//转换为字节数组
        qDebug()<<"size="<<ByteBuf.size();
        //截取CAN帧的data数据字符串
        for (int i=ByteBuf.size()-1;i>=ByteBuf.size()-24;i--)
         {
              t = ((uint32_t)ByteBuf[i]);
              //qDebug()<<"data0="<<t;
              //转移到另一个缓存
              if((t>=48&&t<=57)||(t>=65&&t<=70)||(t>=97&&t<=102))
              {
                   //qDebug()<<"data1="<<t;
                  ByteBuf1[j++]=ByteBuf[i];
              }
         }
        temp = 0;
        //ascii至数值类型转换
        for (int i=0;i<j;i++)
        {
            t = ((uint32_t)ByteBuf1[i]);
            //ascii码值转换到0~9数值
            if((t>=48)&&(t<=57)){
                t=t-48;
            }else if((t>=65)&&(t<=70)){
                //A~F
                t=10+t-65;
            }else if((t>=97)&&(t<=102)){
                //a~f
                t=10+t-97;
            }
            //高低4位组合成u8数据
            if(i%2==0){
                temp=(uint8_t)t;
            }else{
                temp+=(uint8_t)t<<4;
                //整理顺序
                RevData[7-(index++)]=temp;
            }
        }
        //预览
        for (int i = 0;i<8;i++)
        {
            qDebug()<<"Data["<<i<<"]"<<QString::number(RevData[i],16);
        }
        temp=0;
        index=0;
        j=0;
        t=0;
        id_text=0;
        //id的数据的处理,方法同上
        for (int i=ByteBuf.size()-48;i>=ByteBuf.size()-55;i--)
        {
          ByteBuf1[j++]=ByteBuf[i];
        }
        id_text=0;
        for (int i=0;i<j;i++)
        {
            t = ((uint32_t)ByteBuf1[i]);
            if((t>=48)&&(t<=57)){
                t=t-48;
            }else if((t>=65)&&(t<=70)){
                t=10+t-65;
            }else if((t>=97)&&(t<=102)){
                t=10+t-97;
            }
            //qDebug()<<"@"<<t;
            id_text+= t<<(4*i);
        }
        //id数据预览
        qDebug()<<"CAN_ID:"<<QString::number(id_text,16);
        //can数据打包,方便调用
        can_frame.ID = id_text;
        for (int i=0;i<8;i++) {
            can_frame.data.byte[i] = RevData[i];
        }
     }
     return can_frame;
    //返回can数据值
}

四、拓展增加定时器触发读取

 1、缓存数据到QList<QString>类型的列表中并增加定时器

 mytimer = new QTimer(this);
if(file.open(QIODevice::ReadOnly|QIODevice::Text))
    {
        QTextStream textStream(&file);
        
        while(!textStream.atEnd())
        {
            buf = textStream.readLine();
            //ParseData(buf);
            if(buf.length()>1)
            {
                //数据存入到字符串列表中
                stringList.append(buf);
            }
        }
        //删除第一行列首
        stringList.removeFirst();

    } 
    //启动定时器
   if(!mytimer->isActive())
    {
        qDebug()<<"stringList.len="<<stringList.length();
        //连接定时器信号和槽函数
        connect(mytimer,SIGNAL(timeout()),this,SLOT(print()));
        mytimer->start(1000);
    }

2、槽函数的编写

void MainWindow::print()
{
     //qDebug()<<"ceshi=";

    if(cnt>=stringList.length())
    {
        //发送到列表结尾,从头开始读取
        cnt = 0;
    }
    //qDebug()<<"ceshi="<<stringList[cnt++];
    frame = ParseData(stringList[cnt++]);
    qDebug()<<"id:"<<QString::number(frame.ID,16);
    qDebug()<<"data:"<<QString::number(frame.data.byte[0],16)\
            <<QString::number(frame.data.byte[1],16)\
            <<QString::number(frame.data.byte[2],16)\
            <<QString::number(frame.data.byte[3],16)\
            <<QString::number(frame.data.byte[4],16)\
            <<QString::number(frame.data.byte[5],16)\
            <<QString::number(frame.data.byte[6],16)\
            <<QString::number(frame.data.byte[7],16);

}

3、打印模拟的效果

结束语:通过移植以上的函数,可以通过更改txt的can数据和代码中的定时器间隔时间,可以模拟硬件电路板上发的数据,从而脱离硬件环境进行关于CAN的应用软件的开发。作者水平有限,仅供备忘吧~ ~

猜你喜欢

转载自blog.csdn.net/m0_49047167/article/details/113418874
CAN