鱼C论坛

 找回密码
 立即注册
查看: 771|回复: 3

Qt实现串口数据解析

[复制链接]
发表于 2022-12-29 18:07:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
 //读取串口数据并处理
            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[TxNum]=(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[i]^CRCValue;
          }
          return CRCValue;
        }


我想基于Qt实现接收形如“0xaa 0xbb 0x长度 0x地址 0x数据 0x校验 0x55 0x66”这种格式的数据,不知道我上面写得代码哪里错了,请大家指教!!!
可以提供代码进行学习吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

使用道具 举报

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

可以参考一下你的代码吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-30 10:12:02 From FishC Mobile | 显示全部楼层
dongmei 发表于 2022-12-30 08:45
可以参考一下你的代码吗?

我没写过很相似的东西。
直觉上用 FSM 应该没有大问题。
从代码里能看出来的,可能是问题的都已经在之前的回复里了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 13:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表