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
相关产品推荐
相关产品推荐

