Qt接收串口字节数据并存储

接收串口数据

首先我们需要在Qt项目中对串口模块的使用做出相关的配置。(配置详情可参考Qt实现简单串口编辑器)然后制定相关的信号与槽函数来接收串口向我们发来的数据。

    //定义信号接收槽(用于接收PSD向计算机发来的数据)**************************************************************************
    connect(&mSerialPort,&QSerialPort::readyRead,
            [=]()
    {
        //接收到PSD发送来的一条数据
        QByteArray temp = mSerialPort.readAll().toHex();
        info.append(temp);
        if(info.length() == 36){
            //检查校验和
            if(checkRight(info)){
                //处理数据
                qDebug() << "success data";
                QString x = hexstrtoflo1(info,1);
                QString y = hexstrtoflo1(info,2);
                tableShow(x,y);
            }else{
                //抛弃数据
                qDebug() << "worse data";
                QString x = hexstrtoflo1(info,1);
                QString y = hexstrtoflo1(info,2);
                tableShow(x,y);
            }
        }
    });
  1. 由于串口向我们发送的为字节数据,所以我们需要使用QByteArray对数据进行接收。(QSerialPort::toHex()就是将数据以16进制转换接收),需要注意的是:串口并不会一次性发送整条数据,它可能将帧头,数据,校验位等信息分多次发送。所以我们需要进行判断,当数据量达到协议规定后方定义为一条完整的数据(当然可以根据帧头针尾来判断是否为一条合格的数据)。
  2. 拿到数据后我们需要根据协议设计来检查校验和,以此判断数据是否存在偏差。根据判断的返回值来决定存储数据还是抛弃数据。
  3. **hexstrtoflo1()**函数是用来从收到的数据中提取有用的数据信息。

接下来我们将详细描述如何提取信息,并进行转化存储。
首先我们应了解QByteArray::at()函数,用来提取相应位的数据以便于解析。

    QString checkStr = "";
    for(int i = 16;i < 24;i=i+2){
       checkStr += QString(infodata.at(i))+QString(infodata.at(i+1));
    }

我们每次取出一个字节,按协议内容依次循环取出所有字节数据并拼接为字符串。例如:需提取4字节数据,并将它们转化为浮点数进行展示。

	unsigned char byteArray[4];
    unsigned char  *pf;
    unsigned char i;   //计数器
    unsigned char j;   //计数器
    for(i = 0,j = 0;i < 8;i = i+2,j++){
        QString str = checkStr.mid(i,2);
        bool checkok;
        int checkval=str.toInt(&checkok,16);//以16进制数读入
        pf =(unsigned char*)&checkval;            /*unsigned char型指针取得浮点数的首地址*/
        byteArray[j]=*pf;     /*使用unsigned char型指针从低地址一个字节一个字节取出*/
    }

    float x = *((float*)byteArray);
    qDebug("\n%f  ",x);

我们需要将字符串中的每一个字节剥离出来,想办法将其依次存入无符号字节数组当中。首先以16进制读取为int类型(占用4字节),将其地址赋值为(unsigned char*)类型的pf,指针类型决定指针长度,赋值完成之后便可刚好取到checkval数据中四字节的首字节,也就是我们的真正的数据字节,再将他们依次读入无符号字节数组当中去进行存储。这样便可将以字符串表示的四字节转为数组进行存储。

拿到数据之后,我们仅需强制转换,便可以得到这些字节所对应的浮点数。

    float x = *((float*)byteArray);
    printf("\n%f  ",x);
  • 8
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1. 首先需要在Qt中打开串口,设置串口参数和打开串口。 ```c++ QSerialPort serialPort; serialPort.setPortName("COM1"); // 设置串口名称 serialPort.setBaudRate(QSerialPort::Baud9600); // 设置波特率 serialPort.setDataBits(QSerialPort::Data8); // 设置数据位 serialPort.setParity(QSerialPort::NoParity); // 设置校验位 serialPort.setStopBits(QSerialPort::OneStop); // 设置停止位 serialPort.setFlowControl(QSerialPort::NoFlowControl); // 设置流控制 if (serialPort.open(QIODevice::ReadWrite)) { // 打开串口 qDebug() << "Serial port opened successfully!"; } else { qDebug() << "Failed to open serial port!"; } ``` 2. 接收数据时,需要在槽函数中处理串口接收到的数据。可以通过`readyRead()`信号触发槽函数。 ```c++ connect(&serialPort, SIGNAL(readyRead()), this, SLOT(onReadyRead())); ``` ```c++ void MainWindow::onReadyRead() { QByteArray data = serialPort.readAll(); // 读取串口接收到的数据 processSerialData(data); // 处理串口接收到的数据 } ``` 3. 解析数据时,需要根据串口协议进行解析。例如,如果串口发送的数据格式为:`#id,data1,data2,data3*checksum\r\n`,则可以按照以下方式解析数据: ```c++ void MainWindow::processSerialData(QByteArray data) { static QByteArray buffer; // 静态变量,用于存储未解析的数据 buffer.append(data); // 将新接收到的数据加入到缓冲区 int startIndex = buffer.indexOf('#'); // 查找起始符号 int endIndex = buffer.indexOf('*'); // 查找校验和符号 int end2Index = buffer.indexOf('\r\n'); // 查找结束符号 if (startIndex != -1 && endIndex != -1 && end2Index != -1) { // 如果找到了起始符号、校验和符号和结束符号 if (endIndex < startIndex || end2Index < startIndex || endIndex > end2Index) { // 如果数据格式不正确 buffer.remove(0, startIndex + 1); // 从缓冲区中删除错误的数据 return; } QByteArray data = buffer.mid(startIndex + 1, endIndex - startIndex - 1); // 提取数据段 QByteArray checksum = buffer.mid(endIndex + 1, end2Index - endIndex - 1); // 提取校验和 if (verifyChecksum(data, checksum)) { // 如果校验和正确 QStringList dataList = QString(data).split(','); // 分割数据 if (dataList.size() == 4) { // 如果数据格式正确 int id = dataList.at(0).toInt(); // 提取id int data1 = dataList.at(1).toInt(); // 提取data1 int data2 = dataList.at(2).toInt(); // 提取data2 int data3 = dataList.at(3).toInt(); // 提取data3 // 处理接收到的数据 } } buffer.remove(0, end2Index + 2); // 从缓冲区中删除已经处理的数据 } } ``` 4. 校验和的计算方法可以根据具体情况而定。一般来说,校验和的计算方法为将数据段中每个字节的值相加,再取结果的低8位作为校验和。例如: ```c++ bool MainWindow::verifyChecksum(QByteArray data, QByteArray checksum) { int sum = 0; for (int i = 0; i < data.size(); i++) { sum += data.at(i); } int check = checksum.toInt(nullptr, 16); return (sum & 0xFF) == check; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值