单片机的printf重定向串口输出调试信息
猿来如此ISee 2023-03-31

前言


在 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 - 8bit

  • h - 16bit (默认)

  • l  - 32bit


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

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


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



声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 相关技术文库
  • 单片机
  • 嵌入式
  • MCU
  • STM
下载排行榜
更多
评测报告
更多
广告