dongmei 发表于 2022-12-29 18:07:45

Qt实现串口数据解析

//读取串口数据并处理
            QByteArray temp=serial->readAll();
            QDataStream out(&temp,QIODevice::ReadWrite);
            while(!out.atEnd())
            {
                  qint8 outChar=0;
                  out>>outChar;
                  QString byte=QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0'));
                  byte=byte.toUpper();
                  
                  //协议解析状态机
                  if(state_machine==0)
                  {
                  //判断第一个帧头
                  if(byte==0xaa)
                     {
                        state_machine=1;

                      }
                     else
                      {
                        //状态机复位
                        state_machine=0;
                      }            
                   }
                   else if(state_machine==1)
                   {
                     //判断第二个帧头
                     if(byte==0xbb)
                     {
                            state_machine=2;

                     }
                     else
                     {
                            state_machine=0;
                     }
                  }
                  
                   //判断接收长度
                  else if(state_machine==2)
                  {
                      buffer+=byte;
                      bufferdatalen+=byte;
                      //接收数据计数器
                      lencnt=0;
                      //接收数据长度
                      datalen=bufferdatalen.toInt(&ok,16);
                  }
                  
                   //判断接收的地址
                   else if(state_machine==3)
                   {
                     if(byte==0x01)
                     {
                            state_machine=4;

                     }
                     else
                     {
                            state_machine=0;
                     }
                   }

//协议数据处理
                   else if(state_machine==4||state_machine==5||state_machine==6||state_machine==7)
                   {
                     //保存数据
                     frameData+=byte;
                     if(lencnt==datalen)
                     {
                           state_machine=8;
                     }
                     else
                     {
                           state_machine=7;
                           ++lencnt;
                     }
                   }
                  //进行校验
                  else if(state_machine==8)
                  {
                  TxNum=0;
                  if(buffer.isEmpty())
                  {
                        return;
                  }
                  //QByteArray temp;
                  //获取buffer数据
                  temp=QByteArray::fromHex(buffer.toLatin1().data());
                  //将数组读入
                  QDataStream out(&temp,QIODevice::ReadWrite);
                  while(!out.atEnd())
                  {
                        qint8 outchar=0;
                        //每一字节进行填充,直到结束
                        out>>outchar;
                        SendBuf=(uint8_t)(outchar &0xff);
                        TxNum++;
                  }
                  //求帧头以外所有数据的校验和
                  checkSum=(uint8_t)(Sum_Calculate(SendBuf,TxNum));
                  QString strSum=QString("%1").arg(checkSum&0xFF,2,16,QLatin1Char('0'));
                  strSum=strSum.toUpper();
                  byte=byte.toUpper();

                  if(byte==strSum)
                  {
                        state_machine=9;
                  }
                  else
                  {
                        state_machine=0;
                  }

                  }
                  //判断是否接收到帧尾结束
                  else if(state_machine==9)
                  {
                     ....


//校验函数
      uint8_t MainWindow::Sum_Calculate(uint8_t *puchMsg, uint16_t usDataLen)
      {
          uint8_t CRCValue=0;
          uint16_t i=0;
          for(i=0;i<usDataLen;i++)
          {
            CRCValue=puchMsg^CRCValue;
          }
          return CRCValue;
      }


我想基于Qt实现接收形如“0xaa 0xbb 0x长度 0x地址 0x数据 0x校验 0x55 0x66”这种格式的数据,不知道我上面写得代码哪里错了,请大家指教!!!
可以提供代码进行学习吗?

dolly_yos2 发表于 2022-12-29 19:38:18

我不知道您的 buffer 和 bufferdatalen 的细节,这部分不确定是否有问题
FSM 会不会卡在状态编号2上?似乎没有更新状态的语句
没有看懂状态编号4到6的含义以及已读数据的计数逻辑:如果 datalen 存储的就是当前包中应该读取的数据字节数量,是不是应该69行每读入一个字节先更新 lencnt 再判断是否已经读够,您的写法会不会多读一个字节?
因为没有实际做过相关的事情,我很好奇这个输入流里的数据是什么样的,是每次保证只有一组数据(从 0xaa 0xbb 开始到 0x55 0x66 结束)还是可能有多组数据、每组数据之间是否可能有随机的无效数据等等。这些细节很可能会需要在写法上有所反映,比如如果遇到 0xaa 0xaa 0xbb 开始的输入(后面是一个合法的数据组),程序会不会有问题?
很多细节都不太明晰,只能看到哪些说哪些,仅供您酌情参考

dongmei 发表于 2022-12-30 08:45:19

dolly_yos2 发表于 2022-12-29 19:38
我不知道您的 buffer 和 bufferdatalen 的细节,这部分不确定是否有问题
FSM 会不会卡在状态编号2上?似乎 ...

可以参考一下你的代码吗?

dolly_yos2 发表于 2022-12-30 10:12:02

dongmei 发表于 2022-12-30 08:45
可以参考一下你的代码吗?

我没写过很相似的东西。
直觉上用 FSM 应该没有大问题。
从代码里能看出来的,可能是问题的都已经在之前的回复里了。
页: [1]
查看完整版本: Qt实现串口数据解析