STM32, C语言: sprintf写入字符串过长导致发送失败

问题描述

最近在做的一个基于HAL库的STM32项目需要从多个SPI总线设备读取数据并通过DMA从串口发送,程序如下:
(RxData为从SPI总线读取到的数据)

sprintf(tempt, "%c%c%s%c%c%s%c%c%s%c%c%s",
	format[0], format[1], (char *)RxData1,
	format[2], format[3], (char *)RxData2,
	format[4], format[5], (char *)RxData3,
	format[6], format[7], (char *)RxData4);  // 格式化输出到字符串,每个RxData数组末尾已添加\0结束符
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)&tempt, 72);

在电脑上位机观察接收,发现接收到的数据是完全错误的,而且在完成一次发送之后MCU程序卡死。

尝试解决

最初怀疑是格式化输出字符串长度过长而导致堆栈溢出,在CubeMX配置中将Heap和Stack大小改大,编译运行仍然会卡死。
由于是采用DMA发送,并且项目对性能要求较高,所以无法分别发送每组数据(因为若分别发送,则必须在每个发送间隙设置延时函数等待DMA发送完成,如果有更好的方法欢迎告诉我:-)),所以只能另想办法。

问题解决

最后,将程序改为以下形式,成功解决问题:
(使用额外的四个tempt数组暂存字符串,最后将这四个数组合并到另一个大数组再进行输出)

sprintf(tempt1, "%c%c%s", format[0], format[1], (char *)RxData1);
sprintf(tempt2, "%c%c%s", format[2], format[3], (char *)RxData2);
sprintf(tempt3, "%c%c%s", format[4], format[5], (char *)RxData3);
sprintf(tempt4, "%c%c%s", format[6], format[7], (char *)RxData4);
tempt1[18]='\0'; tempt2[18]='\0'; tempt3[18]='\0'; tempt4[18]='\0';
sprintf(tempt, "%s%s%s%s", (char *)tempt1, (char *)tempt2, (char *)tempt3, (char *)tempt4);
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)&tempt, 72);

原因不明,由于占用了双倍的内存,所以肯定不是最优解决方法,如果有高手知道还请赐教。

你可能感兴趣的:(STM32,c语言,嵌入式,单片机,物联网)