You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32通过UART向PC发送大数据时出现数据损坏问题求助

STM32F756 Nucleo数据传输异常排查求助

项目概述

基于STM32F756 Nucleo开发板实现:ADC以DMA模式读取定时器(PWM触发)采集的模拟信号,另一定时器(输入捕获)记录时间戳,两类数据分别存入大小为12000的数组,测试时捕获6500条数据,通过USART3异步发送至PC。

相关代码

CubeMX生成的USART3初始化代码

static void MX_USART3_UART_Init(void)
{
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_ODD;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
}

MCU端数据发送简化代码

uint32_t ADC1_Buffer[12000];
uint32_t Timestamp_Buffer[12000];
uint16_t LastSize = 500;
uint8_t Message = "Sending data\n";
uint8_t transmitting;
uint8_t RxBuffer;

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    transmitting = 0;
}

void Send_data(uint8_t* data, uint32_t size)
{
    uint16_t packet_size = 16;
    uint32_t noo_chunks = (size / packet_size);
    uint16_t remainder_size = 0;

    if(size > (noo_chunks * packet_size))
    {
        remainder_size = size - (noo_chunks * packet_size);
    }

    for(uint32_t i = 0; i < noo_chunks; i++)
    {
        HAL_UART_Transmit(&huart3, data+(i*packet_size), packet_size, HAL_MAX_DELAY);
    }

    if(remainder_size)
    {
        HAL_UART_Transmit(&huart3, data+(size-remainder_size), remainder_size, HAL_MAX_DELAY);
    }
}

int main(void)
{
    //Fill up the first 6500 data of both arrays here with anything
    
    //Wait till PC is ready to receive
    while(HAL_UART_Receive(&huart3, &RxBuffer, 1, HAL_MAX_DELAY) != HAL_OK);

    uint16_t DSIZE = 6000 + LastSize;

    HAL_UART_Transmit(&huart3, &Message[0], strlen(Message), 1000);
    HAL_UART_Transmit(&huart3, (uint8_t*)&DSIZE, 2, 1000);

    HAL_UART_Transmit(&huart3, &Message[0], strlen(Message), 1000);

    //HAL_UART_Transmit(&huart3, (uint8_t*)&ADC1_Buffer[0], DSIZE*4, HAL_MAX_DELAY); //Blocking
    //Send_data((uint8_t*)&ADC1_Buffer[0], DSIZE*4); //32 byte packets, no header/trailer
    transmitting = 1; //DMA flag
    HAL_UART_Transmit_DMA(&huart3, (uint8_t*)&ADC1_Buffer[0], DSIZE*4);  //DMA
    while(transmitting);  //DMA flag check

    HAL_UART_Transmit(&huart3, &Message[0], strlen(Message), 1000);

    HAL_Delay(100);

    HAL_UART_Transmit(&huart3, &Message[0], strlen(Message), 1000);

    //HAL_UART_Transmit(&huart3, (uint8_t*)&Timestamp_Buffer[0], DSIZE*4, HAL_MAX_DELAY); //Blocking
    //Send_data((uint8_t*)&Timestamp_Buffer[0], DSIZE*4); //32 byte packets
    transmitting = 1; //DMA flag
    HAL_UART_Transmit_DMA(&huart3, (uint8_t*)&Timestamp_Buffer[0], DSIZE*4); //DMA
    while(transmitting); //DMA flag check

    HAL_UART_Transmit(&huart3, &Message[0], strlen(Message), 1000);

    HAL_UART_Transmit(&huart3, &Message[0], strlen(Message), 1000);

    while(1){}
}

PC端Python接收代码

import matplotlib.pyplot as plt
import serial
import struct

com = serial.Serial()
com.port = 'COM4'
com.baudrate = 115200
com.timeout = None
com.bytesize = serial.SEVENBITS
com.parity = serial.PARITY_ODD
com.stopbits = serial.STOPBITS_ONE

trailer = bytes([0x00, 0x00, 0xc0, 0x7f])

print("Start?\n")
input()
txs = bytes([85])

com.open()
if not com.is_open:
    print("Could not connect\n")
else:
    com.write(txs)
    dsize = com.read(2)
    Dsize, = struct.unpack('H', dsize)
    print(Dsize)
    message = com.readline()
    print(message)
    vbuff = com.read(Dsize*4)
    message = com.readline()
    print(message)
    message = com.readline()
    print(message)
    tbuff = com.read(Dsize*4)
    message = com.readline()
    print(message)
    print(len(vbuff))
    print(len(tbuff))
    voltages = list(struct.unpack('{}I'.format(Dsize), vbuff))
    timestamps = list(struct.unpack('{}I'.format(Dsize), tbuff))
    
    plt.plot(timestamps, voltages, 'b-')
    plt.show()

com.close()

with open('Data.csv', 'w') as file:
    for i in range(Dsize):
        file.write("{},{}\n".format(timestamps[i], voltages[i]))

问题现象

接收的时间戳数据出现块重复丢失:前31条正确,接下来32条被前31条+第32条数据重复替换,第64-95条正确,该模式重复且后期更频繁;但ADC采样数据接收完全正常。

已做排查

  • 确认TIM2(32位,4MHz,ARR最大值)未被重置,采样1000秒内不会溢出;
  • MCU调试模式下Timestamp数组数据正确;
  • 尝试阻塞发送、分包发送、DMA发送,结果一致;
  • 换用PuTTY接收+ C代码处理日志,问题仍存在。

求助

该数据损坏的原因是什么?如何解决?

备注:实际测试中缓冲区由DMA填充,DMA为正常模式,UART传输前已停止所有DMA操作并禁用流;曾尝试将时间戳转为浮点值发送,问题依旧。


内容的提问来源于stack exchange,提问作者Abdur Rakib

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:18:11