0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

printf输出重定向的方法

CHANBAEK 来源:猿来如此 I See 作者:YJer 2023-05-14 16:22 次阅读

前言

在 PC 上运行 C 语言时,prinf 输出的内容会打印在电脑显示器上,这是因为 prinf 默认的输出设备就是显示器。 而当我们在单片机上,需要通过 printf 函数将信息打印到串口,就要对 printf 函数的输出进行重定向。

printf 输出重定向的方法

printf 函数声明如下:

int printf(const char *format, ...);

printf 函数根据 format 字符串给出的格式打印输出到 stdout(标准输出)中,当然,printf 函数是不会一个字符一个字符去输出,它会调用更底层的 I/O 函数去逐个字符打印。

printf 是库函数,不同编译器对 C库的底层实现机制是不同的,因此 printf 中调用了哪个底层 I/O 函数来输出字符,需要根据当前使用的编译器来确定。

我们实现 printf 输出重定向的方法就是找到当前使用的编译器中,printf 调用了哪个底层 I/O 函数来输出字符,再改写该函数,将字符通过串口输出。

如何确定输出字符的底层 I/O 函数?

Keil 为例,点击菜单栏 Help ==> μVision Help 选项,打开帮助文档。

如果你是51单片机项目,那么使用的编译器是 Keil C51,打开的就是 C51 的帮助文档; 如果你是 ARM 单片机项目,那么使用的编译器是 Keil MDK,打开的就是 ARM 的帮助文档。

查找 printf 关键字,可以看到 C51 的 printf 底层是调用 putchar 函数实现字符输出的:

而 ARM 的 printf 函数底层是调用 fputc函数实现字符输出的:

从上述的结果可知,要想通过 printf 向串口打印调试信息,C51 单片机需要改写 putchar( ) 函数,而 ARM 单片机则需要改写 fputc( ) 函数。

C51 和 ARM 项目中,printf 输出重定向的方法是不一样的,这就是有些人把 STM32 的 printf 搬到 C51 中会出错的原因之一。

C51 重定向 printf 输出的注意事项

C51 重定向 printf 函数的输出到串口,需要改写 putchar 函数,伪代码如下:

char putchar (char ch)
{
SBUF0 = ch;
while( !(SCON0 & (1<<1)));
SCON0 &=~(1<<1);
return 0;
}

使用 printf 函数前,需要包含

51单片机重定向 printf 函数后,如果直接像 PC机或者是 32位单片机那样使用 %d 占位符打印数值,输出的数值可能是错误的,例如下面的代码输出结果可能就是不正确:

int i = 10; 
printf("%d", i);

Keil 中扩展了 b、h、l 来设置字节宽度:

  • b - 8位
  • h - 16bit (默认)
  • l - 32位

在 Keil C51中,用 printf 输出一个单字节变量时,要使用%bd,例如:

unsigned char x = 'A'; 
printf("x: %bd\\n", x);

这些内容在 Keil C51 帮助文档关于 printf 的章节中有提到:

扩展知识

不知道有没小伙伴发现,如果项目中没有重写 putchar 或 fputc 函数,直接调用 printf 也不会报错,只是 printf 打印的内容不知道输出到哪里罢了。

printf 函数里面调用了更加底层的 putchar 或 fputc 函数而没有报错,说明在 C库里面已经实现了 putchar 或 fputc 函数,那为什么我们在 C库外重新实现 putchar 或 fputc 函数时,编译器没有报重复定义的错误呢?

这是因为在 C库里,putchar 或 fputc 函数被定义成了弱函数(weak),当你定义了 putchar 或 fputc 函数,那么编译时就使用你定义的函数,否则就使用 C库中的 putchar 或 fputc 函数。

关于 C语言的弱函数相关内容,这里不再展开来讲,感兴趣的小伙伴可自行查阅相关资料

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6001

    文章

    43973

    浏览量

    620836
  • 显示器
    +关注

    关注

    21

    文章

    4737

    浏览量

    137865
  • C语言
    +关注

    关注

    180

    文章

    7530

    浏览量

    128672
  • 串口
    +关注

    关注

    14

    文章

    1483

    浏览量

    74511
  • 函数
    +关注

    关注

    3

    文章

    3868

    浏览量

    61309
收藏 人收藏

    评论

    相关推荐

    stm32系列单片机之printf重定向

    的方式有两种,重定向至UART,或者通过JTAG的SW模式将printf重定向至SWO引脚输出。首先介绍第一种,重定向至UART,这种方式我
    发表于 01-19 10:59

    如何对printf函数的输出进行重定向

    怎样去使用printf函数打印基本的显示信息呢?如何对printf函数的输出进行重定向呢?
    发表于 11-30 07:29

    STM32重定向printf方法总结

    printf函数是怎样通过串口打印信息到串口调试助手上的?怎样去编写printf重定向代码呢?
    发表于 11-30 06:21

    STM32重定向printf方法是什么?

    STM32重定向printf方法是什么?如何解决在TIMER2中printf只能打印double类型的整数部分?
    发表于 12-01 06:00

    如何重定向printf输出到串口输出

    如何重定向printf输出到串口输出呢?有哪几种方法
    发表于 12-02 06:04

    重定向printf() 函数

    ,结果是什么现象都没有。要想使用这个函数,常规方法重定向 printf() 函数,结合串口来打印到串口助手上位机。这里的重定向就非常复杂了,你需要懂
    发表于 01-11 07:01

    重定向printf输出到串口输出方法

    本文详细的介绍了如何重定向printf输出到串口输出的多种方法,包括调用MDK微库(MicroLib)的
    发表于 02-10 07:16

    重定向printf函数到串口输出方法

    本文详细的介绍了如何重定向printf输出到串口输出的多种方法,包括调用MDK微库(MicroLib)的
    发表于 02-22 08:25

    实现重定向printf()和scanf() 函数案例分析

    要想printf()和scanf() 函数工作,我们需要把printf()和scanf() 重新定向到串口中。重定向是指用户可以自己重写C 的库函数,当连接器检查到用户编写了与C 库函
    发表于 06-23 08:26 8605次阅读
    实现<b class='flag-5'>重定向</b><b class='flag-5'>printf</b>()和scanf() 函数案例分析

    如何去做单片机printf函数的重定向

    printf一样输出格式化字符。到网上一查还真有,但是大多数说的都做串口的重定向,而且说的也不是很详细,但是经过两天的研究也大概了解了怎么去做printf
    发表于 04-17 17:27 0次下载
    如何去做单片机<b class='flag-5'>printf</b>函数的<b class='flag-5'>重定向</b>

    STM32单片机IAR环境下重定向printf函数

    STM32单片机IAR环境下重定向printf函数一、引言在项目开发中,使用printf函数通过串口打印调试信息,需要对printf函数进行改写,
    发表于 12-03 10:36 15次下载
    STM32单片机IAR环境下<b class='flag-5'>重定向</b><b class='flag-5'>printf</b>函数

    【STM32Cube_09】重定向printf函数到串口输出的多种方法

    本文详细的介绍了如何重定向printf输出到串口输出的多种方法,包括调用MDK微库(MicroLib)的
    发表于 12-06 11:21 12次下载
    【STM32Cube_09】<b class='flag-5'>重定向</b><b class='flag-5'>printf</b>函数到串口<b class='flag-5'>输出</b>的多种<b class='flag-5'>方法</b>

    Keil下使用STlink重定向printf的配置

    Keil下使用STlink重定向printf的配置1. printf 重定向Keil默认下使用Micro LIB库,该库调用 fputs 实现 pr
    发表于 12-27 18:43 18次下载
    Keil下使用STlink<b class='flag-5'>重定向</b><b class='flag-5'>printf</b>的配置

    STM32单片机基础09——重定向printf函数到串口输出的多种方法

    本文详细的介绍了如何重定向printf输出到串口输出的多种方法,包括调用MDK微库(MicroLib)的
    发表于 12-27 19:22 8次下载
    STM32单片机基础09——<b class='flag-5'>重定向</b><b class='flag-5'>printf</b>函数到串口<b class='flag-5'>输出</b>的多种<b class='flag-5'>方法</b>

    如何实现Printf()接口重定向到UART

    ;。所谓的重定向,就是重新定义Printf()接口函数里调用的与输出设备相关的函数,eg:使用Printf()接口将MCU中的信息,通过串口或者Ethernet
    的头像 发表于 10-01 10:13 636次阅读
    如何实现<b class='flag-5'>Printf</b>()接口<b class='flag-5'>重定向</b>到UART