STM32F1系列HAL库配置串口通信(2)——串口重定向以及log信息格式输出

串口重定向以及log信息格式输出

之前我们提到了HAL库配置串口,但是由于我们还没有进行到中断,所以对于一些HAL库里有关串口的函数还是很难全部应用的,尽管如此,我们依然可以借助这两个函数胡作非为 加以利用。

1.串口发送数据:

HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
功能:串口发送指定长度的数据。如果超时没发送完成,则不再发送,返回超时标志(HAL_TIMEOUT)。

参数:

*UART_HandleTypeDef huart UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1
*pData 需要发送的数据
Size 发送的字节数
Timeout 最大发送时间,发送数据超过该时间退出发送
举例: HAL_UART_Transmit(&huart1, (uint8_t *)ZZX, 3, 0xffff); //串口发送三个字节数据,最大传输时间0xffff

2.中断接收数据:
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
功能:串口接收指定的长度的数据,
参数与发送函数的基本相同。
大家可以看一下这篇博主的介绍会更详细UART串口通信详解
在研究标准库的时候,使用了串口重定向,采用printf与scanf等等C语言学习时经常用到的函数,并且当我们配置好的时候,还可以利用gets,puts,getchar与putchar,十分方便,这样也减少了你重新写HAL_UART_Transmit等这些函数的时间。可为什么要重定向呢
建议大家先看一下这篇博客STM32的printf函数重定向
我们的KEIL里是有microLib库,他支持我们使用不太健全的stdio.h,这样我们就可以使用printf等上述提到的输入输出函数了,
在这里插入图片描述
不过,我们在VS里printf的内容是显示在窗口控制台里,而这样直接使用printf()函数,其打印的字符串最终不知道打印到何处。我们要做的是将调试信息打印到USART1中,所以需要对printf()函数所依赖的打印输出函数fputc()重定向
(因为MicroLib中的printf()函数打印操作依赖fputc())
在MicroLib的stdio.h中,fputc()函数的原型为:

int fputc(int ch, FILE* stream)

此函数原本是将字符ch打印到文件指针stream所指向的文件流去的,现在我们不需要打印到文件流,而是打印到串口1。
利用HAL_UART_Transmit打印到串口1

int fputc(int ch, FILE *f)
{
uint8_t temp[1] = {ch};
HAL_UART_Transmit(&huart1, temp, 1, 2);//huart1需要根据你的配置修改
return ch;
}

相应的,fgets也可以重定向

int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

别忘了添加stdio.h

/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
注意加在begin与end之间,否则报错

这样就可以使用printf,gets,puts等函数了,这里给大家举个栗子:
main函数内初始化str字符数组

char str[100];

while(1)里添加

		gets(str);
		printf("三句话,让我听了%s\r\n",str);

编译无误后运行
在这里插入图片描述
(这里记得勾选发送新行!)
也可以试试这些!

char ch;
while1{
        ch=getchar();
		putchar(ch);
	//	gets(str);
	//	scanf("%s",str);
}

个性化输出

除此以外,介绍个小网站Text to ASCII Art Generator (TAAG)
在最中间的方框输入你想要的文字,设置Font,一行一行复制到printf中
在这里插入图片描述
比如我这里设置Crads字体,输出adidas,

//		    printf(".------..------..------..------..------..------.\r\n");
//				printf("|A.--. ||D.--. ||I.--. ||D.--. ||A.--. ||S.--. |\r\n");
//				printf("| (\\/) || :/\\: || (\\/) || :/\\: || (\\/) || :/\\: |\r\n");
//				printf("| :\\/: || (__) || :\\/: || (__) || :\\/: || :\\/: |\r\n");		
//				printf("| '--'A|| '--'D|| '--'I|| '--'D|| '--'A|| '--'S|\r\n");
//				printf("`------'`------'`------'`------'`------'`------'\r\n");		
//		    printf("---------------------------------------------------\r\n");

注意红线,你只需在前加\,变为转义字符即可
效果如下:
在这里插入图片描述

利用条件编译,可变参数宏实现log信息格式输出

了解c语言的都应该知道,条件编译,如下

#define LOG 1

#if LOG
printf("[info]main.c:");
#endif

他的意思就是说,if判断LOG(即为1),那么执行printf语句,如果我们去掉1或者整句去掉,就不会执行#if与#endif之间的语句。

可变参数宏也很好理解

#ifdef USER_MAIN_DEBUG
#define user_main_printf(format, ...) printf( format "\r\n", ##__VA_ARGS__)
#else
#define user_main_printf(format, ...)
#endif

如果我们定义了USER_MAIN_DEBUG,那么就#define user_main_printf(format, …)为printf( format “\r\n”, ##_VA_ARGS),
否则执行#define user_main_printf(format, …),这句相当于把这句直接废掉,因为他定义成了一个空白,什么都没有。
而这句printf( format “\r\n”, ##_VA_ARGS),相当于把你在user_main_printf(“111222”)中,111222后加了\r\n。
这个是我无意中听到B站一个大佬讲的可变参数宏知道的。
利用这个,我在主函数中直接写user_main_info(“我想写的东西”);就会显示:[\tmain]info:我想写的东西

#define USER_MAIN_DEBUG 1
#ifdef USER_MAIN_DEBUG
#define user_main_printf(format, ...) printf( format "\r\n", ##__VA_ARGS__)
#define user_main_info(format, ...) printf("[\tmain]info:" format "\r\n", ##__VA_ARGS__)
#define user_main_debug(format, ...) printf("[\tmain]debug:" format "\r\n", ##__VA_ARGS__)
#define user_main_error(format, ...) printf("[\tmain]error:" format "\r\n",##__VA_ARGS__)
#else
#define user_main_printf(format, ...)
#define user_main_info(format, ...)
#define user_main_debug(format, ...)
#define user_main_error(format, ...)
#endif

注意这个只在C99当中成立,C89会报错。当我需要打印串口信息的时候,define 一个 USER_MAIN_DEBUG, 在我不需要时将
其注释。
之后再讲串口中断吧。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值