stm32多个串口实现printf

摘要

最近stm32一个项目需要用到串口屏,串口WiFi,和调试串口,用hal库提供的API用起来比较繁琐,所以想重定向printf,实现多个串口printf函数,用起来比较方便,所以有了这篇博客。

正题

方法一

用c库的vsnprintf函数,这个函数包含在stdio.h里


extern _ARMABI int __ARM_vsnprintf(char * __restrict /*s*/, size_t /*n*/,
                     const char * __restrict /*format*/, __va_list /*arg*/) __attribute__((__nonnull__(3)));
#if !defined(__STRICT_ANSI__) || defined(__USE_C99_ALL) || (defined(__STDC_VERSION__) && 199901L <= __STDC_VERSION__) || (defined(__cplusplus) && 201103L <= __cplusplus)
extern _ARMABI int vsnprintf(char * __restrict /*s*/, size_t /*n*/,
                     const char * __restrict /*format*/, __va_list /*arg*/) __attribute__((__nonnull__(3)));
   /*
    * is equivalent to snprintf, with the variable argument list replaced by
    * arg, which has been initialised by the va_start macro (and possibly
    * subsequent va_arg calls). The vsprintf function does not invoke the
    * va_end function.
    * Returns: the number of characters that would have been written in the
    *          array, not counting the terminating null character. As
    *          snprintf.
    */
#endif

这是keil mdk里的描述,但是我没包含微库,所以感觉其他编译器也能使用,我没试过。

下面直接给出代码

#include "stdarg.h"
#include "stdio.h"

#define APP_TX_DATA_SIZE  2048
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];


void uart_printf(UART_HandleTypeDef *huart,const char *format, ...)
{
    va_list args;
    uint32_t length;
 
    va_start(args, format);
    length = vsnprintf((char *)UserTxBufferFS, APP_TX_DATA_SIZE, (char *)format, args);
    va_end(args);
    HAL_UART_Transmit(huart,UserTxBufferFS, length,0xffff);   //只需要更改这儿就能一直到其他平台

}

测试
在这里插入图片描述在这里插入图片描述

方法二

直接找出printf的源码,或者自己写一个printf,我这里在野火的代码里找到的,直接搬过来分享,自己没测试使用,用到的时候再移植吧

static char *                 itoa                                ( int value, char * string, int radix );

/*
 * 函数名:USART2_printf
 * 描述  :格式化输出,类似于C库中的printf,但这里没有用到C库
 * 输入  :-USARTx 串口通道,这里只用到了串口2,即USART2
 *		     -Data   要发送到串口的内容的指针
 *			   -...    其他参数
 * 输出  :无
 * 返回  :无 
 * 调用  :外部调用
 *         典型应用USART2_printf( USART2, "\r\n this is a demo \r\n" );
 *            		 USART2_printf( USART2, "\r\n %d \r\n", i );
 *            		 USART2_printf( USART2, "\r\n %s \r\n", j );
 */
uint8_t buffer[2] = {0x0d,0x0a};
void USART_printf ( USART_TypeDef * USARTx, char * Data, ... )
{
	const char *s;
	int d;   
	char buf[16];

	
	va_list ap;
	va_start(ap, Data);        /*ap指向Data的下个字符*/

	while ( * Data != 0 )     // 判断是否到达字符串结束符
	{				                          
		if ( * Data == 0x5c )  //'\'
		{									  
			switch ( *++Data )
			{
				case 'r':							          //回车符
				HAL_UART_Transmit(&ESP8266_UartHandle,(uint8_t *)&buffer[0], 1, 0xFFFF);
				Data ++;
				break;

				case 'n':							          //换行符
				HAL_UART_Transmit(&ESP8266_UartHandle,(uint8_t *)&buffer[1], 1, 0xFFFF);
				Data ++;
				break;

				default:
				Data ++;
				break;
			}			 
		}
		
		else if ( * Data == '%')
		{									  //
			switch ( *++Data )
			{				
				case 's':										  //字符串
				s = va_arg(ap, const char *); //取出ap指向的指针,并把指针前进一个char *大小
				
				for ( ; *s; s++) 
				{
					HAL_UART_Transmit(&ESP8266_UartHandle,(uint8_t *)s, 1, 0xFFFF);
					while ( __HAL_USART_GET_FLAG (&ESP8266_UartHandle, USART_FLAG_TXE ) == RESET );
				}
				
				Data++;
				
				break;

				case 'd':			
					//十进制
				d = va_arg(ap, int);
				
				itoa(d, buf, 10);
				
				for (s = buf; *s; s++) 
				{
					HAL_UART_Transmit(&ESP8266_UartHandle,(uint8_t *)s, 1, 0xFFFF);
					while ( __HAL_USART_GET_FLAG (&ESP8266_UartHandle, USART_FLAG_TXE ) == RESET );
				}
				
				Data++;
				
				break;
				
				default:
				Data++;
				
				break;
				
			}		 
		}
		
		else
		{     	
			HAL_UART_Transmit(&ESP8266_UartHandle,(uint8_t *)Data, 1, 0xFFFF); 
			Data++;
		}
		
		while ( __HAL_USART_GET_FLAG (&ESP8266_UartHandle, USART_FLAG_TXE ) == RESET );
		
	}
}


/*
 * 函数名:itoa
 * 描述  :将整形数据转换成字符串
 * 输入  :-radix =10 表示10进制,其他结果为0
 *         -value 要转换的整形数
 *         -buf 转换后的字符串
 *         -radix = 10
 * 输出  :无
 * 返回  :无
 * 调用  :被USART2_printf()调用
 */
static char * itoa( int value, char *string, int radix )
{
	int     i, d;
	int     flag = 0;
	char    *ptr = string;

	/* This implementation only works for decimal numbers. */
	if (radix != 10)
	{
		*ptr = 0;
		return string;
	}

	if (!value)
	{
		*ptr++ = 0x30;
		*ptr = 0;
		return string;
	}

	/* if this is a negative value insert the minus sign. */
	if (value < 0)
	{
		*ptr++ = '-';

		/* Make the value positive. */
		value *= -1;
		
	}

	for (i = 10000; i > 0; i /= 10)
	{
		d = value / i;

		if (d || flag)
		{
			*ptr++ = (char)(d + 0x30);
			value -= (d * i);
			flag = 1;
		}
	}

	/* Null terminate the string. */
	*ptr = 0;

	return string;

} /* NCL_Itoa */

分享一篇添加链接描述

这篇博客对你有帮助,点个赞呗。

  • 8
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值