在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的損耗 )