一、前言
本文将介绍在IDE工具中如何将printf函数重定向至串口输出,printf函数是经典的一个控制台字符打印函数,最大的优点是可以很方便的进行各种格式化输出操作,比如字符、字符串、整型、浮点型等内容格式化输出。printf 函数默认输出设备是显示器,如果要实现在串口或者 LCD 上显示,必须重定义标准库函数里调用的与输出设备相关的函数。比如使用 printf 输出到串口, 需要将 fputc 里面的输出指向串口,这一过程就叫重定向。
二、Keil串口重定向,使用微库MicroLib
使用CubeMX生成基本Keil项目工程,使能串口外设1,波特率设为115200bps
Keil工程结构
方法一串口重定向需要使用Keil工具内置的MicroLib
微库勾选后重写fputc函数,printf函数执行后会调用fputc函数
在main.c begin1区域插入如下代码
/* USER CODE BEGIN 0 */ #include <stdio.h> int fputc(int ch, FILE *f) { /* 发送一个字节数据到串口DEBUG_USART */ HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000); return (ch); } /* USER CODE END 0 */
while循环体加入测试代码
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_Delay(300); printf("Hello.\n"); printf("num_float=%f\n",5.656); //HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
实验结果
可以看到字符串、浮点数可以正确打印出来
三、Keil串口重定向,不使用微库MicroLib
在某些情况下主程序因为使用了微库而无法正常运行,这时候不得不取消微库使用
此时可以使用以下方法解决,取消勾选微库
在main.c begin1区域插入如下代码
#if 1 /* 告知连接器不从C库链接使用半主机的函数 */ #pragma import(__use_no_semihosting) /* 定义 _sys_exit() 以避免使用半主机模式 */ void _sys_exit(int x) { x = x; } /* 标准库需要的支持类型 */ struct FILE { int handle; }; FILE __stdout; /* */ //int fputc(int ch, FILE *stream) //{ // /* 堵塞判断串口是否发送完成 */ // while((USART1->ISR & 0X40) == 0); // /* 串口发送完成,将该字符发送 */ // USART1->TDR = (uint8_t) ch; // return ch; //} int fputc(int ch, FILE *f) { /* 发送一个字节数据到串口DEBUG_USART */ HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000); return (ch); } #endif
while循环体加入测试代码
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_Delay(300); printf("Hello.\n"); printf("num_float=%f\n",3.141592); //HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
编译程序无误,烧录固件至开发板
字符串、浮点数可以正确打印出来
四、CubeIDE串口重定向,使用标准库
新建CubeIDE基本项目工程,工程结构如下
在main.c begin0区域插入如下代码
/* USER CODE BEGIN 0 */ #include <stdio.h> // 重定向printf start //_write函數在syscalls.c中, 使用__weak定義, 所以可以直接在其他文件中定義_write函數 __attribute__((weak)) int _write(int file, char *ptr, int len) { if(HAL_UART_Transmit(&huart1,ptr,len,0xffff) != HAL_OK) { Error_Handler(); } } // 重定向printf end /* USER CODE END 0 */
while循环体加入测试代码
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_Delay(300); printf("Hello.\n"); printf("num_float=%f\n",3.141592/2); //HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
实验结果,CubeIDE默认不支持浮点数格式化
CubeIDE做如下设置
在弹出界面找到settings
点击+号添加如下标志
-u _printf_float
保存设置并关闭当前小窗口。编译程序无误,重新烧录固件至开发板
字符串、浮点数可以正确打印出来