QT Creator读取STM32数据时自动拆分字符串的原因排查
串口接收数据拆分问题的解决方案
问题原因
串口通信属于字节流传输,底层不会保证一次发送的数据能被一次性完整接收。哪怕STM32一次性发送完所有内容,QT的readAll()也只能读取到当前串口缓冲区中已有的部分字节,剩余数据会触发下一次readyRead信号。
你的QT代码存在两个关键问题:
- 每次接收数据就调用
textEdit->clear(),然后用当前收到的片段覆盖显示,导致只保留最后一次收到的部分内容 - 没有对接收的数据进行缓存和分帧处理,无法拼接拆分的数据包
解决方案
1. 修改QT代码,添加缓存与分帧逻辑
首先在MainWindow类中添加一个成员变量用于缓存未处理的数据:
// 在mainwindow.h的private区域添加 QByteArray m_receivedBuffer;
然后修改readData函数,改为缓存数据并按换行符(需要STM32配合添加)分割完整帧:
void MainWindow::readData() { QByteArray newData = COMPORT->readAll(); qDebug() << "Received Data Size:" << newData.size(); // 将新收到的数据追加到缓存 m_receivedBuffer.append(newData); // 循环处理所有完整的行(以换行符为结束标志) while (m_receivedBuffer.contains('\n')) { int newlinePos = m_receivedBuffer.indexOf('\n'); // 提取完整的一行内容 QString completeLine = QString::fromUtf8(m_receivedBuffer.left(newlinePos + 1)).trimmed(); // 从缓存中移除已处理的部分 m_receivedBuffer.remove(0, newlinePos + 1); // 方式1:追加显示所有历史数据 ui->textEdit->append(completeLine); // 方式2:只显示最新的两行温度数据(替换原有内容) // QStringList lines = ui->textEdit->toPlainText().split('\n'); // lines.append(completeLine); // if (lines.size() > 2) lines.removeFirst(); // ui->textEdit->setText(lines.join('\n')); qDebug() << "Processed Line:" << completeLine; } }
2. 优化STM32发送代码,添加结束符
在STM32发送数据时,给每一行内容添加换行符\n,方便QT识别完整的帧:
char buffer[16]; // 扩大缓冲区以容纳温度字符串 if (input == '1') { // 测试字符串添加换行符 sprintf(buffer, "Test\n"); HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), 200); // 温度数据发送示例(每行加换行) // sprintf(buffer, "%.2f °C\n", temp1); // HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), 200); // sprintf(buffer, "%.2f °C\n", temp2); // HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), 200); }
注意:原STM32代码中
sprintf语句末尾缺少分号,需要补上。
关键说明
- 缓存机制解决了数据拆分的问题,所有收到的字节会被暂存,直到出现结束符(换行)才会处理完整内容
- 换行符作为帧结束标志是串口通信中最常用的分帧方式,你也可以根据需求自定义其他标志(如
\r\n\r\n表示一组数据结束)
内容的提问来源于stack exchange,提问作者min_een
相关产品推荐
相关产品推荐

