Keil重定义fputc函数实现通过串口实现printf格式化输出

        printf的格式化输出可以输出一下几种格式化类型:

      %a(%A)     浮点数、十六进制数字和p-(P-)记数法(C99)
      %c             字符
      %d             有符号十进制整数
      %f              浮点数,.xf表示保留几位小数
      %e(%E)     浮点数指数输出[e-(E-)记数法]
      %g(%G)     浮点数不显示无意义的0
      %i              有符号十进制整数(%d)
      %u             无符号十进制整数
      %o             八进制整数 
      %x(%X)      十六进制整数
      %p             内存地址
      %s             字符串
      %%            "%"

       其中%#x等,即加入#号表示会有格式存在(单位),如打印16进制会自动加上0x...

        printf函数就是通过一次一次调用fputc函数完成对字符的格式化输出,调用一次就输出1字节ASCII码值。

        printf为默认屏幕输出,而sprintf为标准的输出流,sprintf(char * p,format[a,b,c,])可以选择格式化输出到哪个内存当中,再通过其他方式读取出来,如LCD\OLED屏幕显示格式化的实时数据。

本文章介绍两种方法:

1.1第一种:使用微库

        如下图所示,使用keil的微库。

                使用微库可直接重定义fputc即可,其中fputc可加入预编译条件来选择哪个串口来进行printf输出,实际需求按如下代码修改即可:

/* MDK下需要重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
    while ((UART1->STATUS & (1<<1)) == 0);     /* 等待上一个字符发送完成 */
 
    UART1->TDR = (uint8_t)ch;             /* 将要发送的字符 ch 写入到DR寄存器 */
    return ch;
}

1.2不使用微库:使用半主机模式

        不使用微库代码较为复杂,如下所示:

/******************************************************************************************/
/* 加入以下代码, 支持printf函数, 而不需要选择use MicroLIB */

#if 1

#if (__ARMCC_VERSION >= 6010050)            /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t");  /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t");   

#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)

struct __FILE
{
    int handle;
    /* Whatever you require here. If the only file you are using is */
    /* standard output using printf() for debugging, no file handling */
    /* is required. */
};

#endif

/* 不使用半主机模式,至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */
int _ttywrch(int ch)
{
    ch = ch;
    return ch;
}

/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{
    x = x;
}

char *_sys_command_string(char *cmd, int len)
{
    return NULL;
}


/* FILE 在 stdio.h里面定义. */
FILE __stdout;

/* MDK下需要重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
    while ((UART1->STATUS & (1<<1)) == 0);     /* 等待上一个字符发送完成 */

    UART1->TDR = (uint8_t)ch;             /* 将要发送的字符 ch 写入到DR寄存器 */
    return ch;
}
#endif
/******************************************************************************************/

        可加入条件编译实现通过宏定义定义使用哪一个串口作为printf的输出

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值