一、前言
本文将介绍在IDE工具中如何将printf函数重定向至串口输出,printf函数是经典的一个控制台字符打印函数,最大的优点是可以很方便的进行各种格式化输出操作,比如字符、字符串、整型、浮点型等内容格式化输出。printf 函数默认输出设备是显示器,如果要实现在串口或者 LCD 上显示,必须重定义标准库函数里调用的与输出设备相关的函数。比如使用 printf 输出到串口, 需要将 fputc 里面的输出指向串口,这一过程就叫重定向。
二、Keil串口重定向,使用微库MicroLib
使用CubeMX生成基本Keil项目工程,使能串口外设1,波特率设为115200bps
![1727700661531846.png ~`EZ_]}[)ZJARZUVG`L]C}C.png](http://uphotos.eepw.com.cn/1709346044/pics/1727700661531846.png)
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);
}
#endifwhile循环体加入测试代码
/* 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基本项目工程,工程结构如下
![1727702525559058.png `LH]KTRLPB[44A`651%%~84.png](http://uphotos.eepw.com.cn/1709346044/pics/1727702525559058.png)
在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默认不支持浮点数格式化
![1727702608186887.png WB6YWZB@`F]ETE1PO_TN]OO.png](http://uphotos.eepw.com.cn/1709346044/pics/1727702608186887.png)
CubeIDE做如下设置

在弹出界面找到settings

点击+号添加如下标志
-u _printf_float
![1727703026475789.png ZEVUA}R8I]UFNVXF{2[J2B0.png](http://uphotos.eepw.com.cn/1709346044/pics/1727703026475789.png)
保存设置并关闭当前小窗口。编译程序无误,重新烧录固件至开发板
![1727703132969481.png G0])TD)VT7HL2N)Q$TZ)0(A.png](http://uphotos.eepw.com.cn/1709346044/pics/1727703132969481.png)
字符串、浮点数可以正确打印出来
我要赚赏金
