如何在STM32上实现printf函数输出到串口

背景

printf是学习C语言时常用的函数,可以将想要显示的数字、字符串等显示在屏幕上

但单片机没有屏幕,于是便希望将结果输出到串口

本文提供两种实现方案(传统的printf函数重定向和DMA实现printf)

printf函数重定向

printf的底层操作实际上就是使用fputc函数一个一个输出字符到屏幕上,所以我们只需要将fputc函数进行修改,使其功能变为通过串口输出一个字符即可实现printf的重定向

具体代码如下

int fputc(int ch,FILE *f)
{
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
	return ch;
}

随后在main函数里面调用printf函数即可,方法与C语言完全一致

DMA实现

DMA能够大大提升串口的传输速度,既然能够实现printf的重定向,能否和DMA结合,在调用方便的基础上,提高传输速度呢?

仿造printf重定向

如果简单地对上面的代码进行替换,改成下面这种形式

int fputc(int ch,FILE *f)
{
	HAL_UART_Transmit_DMA(&huart1,(uint8_t*)&ch,1);	  
	return ch;
}

这个时候如果你想使用这个新的printf输出“Hello world!”

那么你会发现串口只会一直输出H,串口助手接到的就会是HHHHH…

这是因为DMA传输的速度取决于串口发送的速度,在串口发送H的时候,后面的ello world!都会调用fputc函数,而这时DMA仍然在进行H的发送,所以导致最后只发送了一个H

如果在fputc函数里面加上一句延时,例如HAL_Delay(1),就又可以正常地进行工作

但是这和我们之前使用DMA的目的背道而驰,所以需要采用新的解决方案

构建新函数

构造如下函数,调用即可实现使用DMA输出到串口

void USART1_DMA_printf(const char *format,...)
{
	uint16_t len;
	va_list args;	
	va_start(args,format);
	len = vsnprintf((char*)UartTxBuf,sizeof(UartTxBuf)+1,(char*)format,args);
	va_end(args);
	HAL_UART_Transmit_DMA(&huart1, UartTxBuf, len);
}

作者:zeandon

物联沃分享整理
物联沃-IOTWORD物联网 » 如何在STM32上实现printf函数输出到串口

发表回复