IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> stm32多个串口实现printf -> 正文阅读

[嵌入式]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 */

分享一篇添加链接描述

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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 17:13:27  更:2021-07-31 17:13:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 9:26:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码