在MDK中使用printf,需要同时重定义fputc函数和避免使用semihosting(半主机模式),标准库函数的默认输出设备是显示器,要实现在串口或LCD输出,必须重定义标准库函数里调用的与输出设备相关的函数。所以需要将printf需要调用的fputc里面的输出指向串口(重定向)。
方法1--使用微库:( 使用微库的话,不会使用半主机模式。)
选择use Microlib https://blog.csdn.net/graduation201209/article/details/79028792
1、使用微库(平台式keil-MDK),点击“魔术棒” Target标签下有个Use MicroLIB---勾选。
2、包含头文件:#include "stdio.h"
3、Printf重定向,修改fputc()函数的内容
#include "main.h"
#include "stm32f4xx_hal.h" // 添加的代码如下,进行函数重构
/* With GCC/RAISONANCE,
small printf(option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */
#ifdef __GNUC__ //gcc编译器宏定义
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */ /*上面的意思是: 如果定义了宏__GNUC__,即使用GCC编译器,则定义宏#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
如果没有定义宏__GNUC__,即不使用GCC编译器,则定义宏#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) */ //添加printf重构函数的实现部分
PUTCHAR_PROTOTYPE {
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
方法2 --使用标准库(__use_no_semihosting):
方法3 --完全代码实现:
void simp_printf(S8P fmt, ...)
{
if (g_PanelPara.bitUartPrtEn)
{
U8P str;
S32 d;
U32 u32d;
U8 buf[32];
U8 u8Len = 0x00;
U8 u8precision = 0;
va_list ap;
va_start(ap, fmt);
while (*fmt)
{
if (*fmt != '%' && (!u8Len))
{
#if PS_OS == WIN
if (*fmt == 0x0a) //enter ,newline
{
UartSendByte(0x0d);
}
#endif
UartSendByte(*fmt++);
continue;
}
switch (*++fmt)
{
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
u8Len = (*fmt) - 0x30;
continue;
case '.':
u8precision = (*(++fmt)) - 0x30;
continue;
case 'd':
case 'D':
d = va_arg(ap, int);
itoa(d, buf, 10, u8Len, u8precision);
u8Len = 0;
for (str = buf; *str; str++)
{
UartSendByte(*str);
}
break;
case 'x':
case 'X':
u32d = va_arg(ap, unsigned int);
itoa(u32d, buf, 16, u8Len, u8precision);
u8Len = 0;
for (str = buf; *str; str++)
{
UartSendByte(*str);
}
break;
/* Add other specifiers here... */
default:
UartSendByte(*fmt);
u8Len = 0;
break;
}
fmt++;
}
va_end(ap);
}
return; /* Dummy return value */
}
方法4 --标准 C 库 实现: ( vsprintf 该函数会引入一些CodeSize的损耗 )