STM32编程中printf函数重定向背后的原理

嵌入式系统 时间:2023-12-18来源:欧工玩转嵌入式

在C语言中,printf是一个非常好用的函数,尤其是在程序调试阶段,我们可以通printf打印变量的值来帮助查错。在学习C语言的时候我们的开发环境和运行环境都是PC机,printf函数打印到PC机的屏幕上是顺理成章的事。但当我们在做嵌入式开发时,即使目标机器上有LCD屏幕,直接使用printf函数也是观察不到结果的。这时有经验的工程师一般都会通过重定向printf函数来将printf的定向到串口,再通过USB转TTL等工具从目标主机的串口上读取数据流到电脑。

  下面先介绍在Keil中如何重定向printf的输出到USART3。实际操作很简单,总共分为3步:

1.在工程设置中开启Use MicroLIB选项:

开启Use MicroLIB选项

2.在代码中实现自定义的fputc函数,其函数原型为 int fputc(int c, FILE *stream)。printf函数底层是通过调用fputc函数来实现字符输出的,所以我们只需对fputc函数重定义即可。本例中将printf重定向到STM32的USART3,所以函数中用到的寄存器是USART3->SR:

添加自定义的fputc函数

3.最后一步,初始化USART3,使能输出。初始化函数:

USART3初始化函数

  经过以上3个步骤,STM32的USART3已经能够通过printf打印输出了,效果如下:

测试代码

printf实际输出效果

  可以看到,要想在STM32开发中实现printf重定向在操作上很简单。但其背后的原理又是什么?我们知道C语言是不支持函数重定义语法的,如果我们自己在同一作用域下定义2个同名函数编译是必然报错的。为什么我们可以重定义fputc函数而不会和函数库中原有的fputc发生冲突呢?要解释这个问题,就要引入新的概念:“强符号”、“弱符号”。在gcc编译器中使用 "__attribute__((weak)) " 修饰的函数或变量属于弱符号,否则就是强符号。关于"强符号"和"弱符号",有以下规则:

  在函数库中默认的fputc函数就是通过"__attribute__((weak)) " 修饰的弱符号函数。所以在我们重定义了fputc函数后,编译器就选择了我们定义的fputc函数进行链接。我们定义的fputc函数将字符输出到USART3,printf函数在底层调用了fputc函数,因此printf的输出便重定向到了USART3。如果你愿意,你也可以将printf函数重定向到SPI等外设输出,但由于串口使用方便,我们一般选择重定向到串口。

最后要注意一点:强弱符号的链接特性是由链接器决定的,并不是C语言语法本身的特性。所以如果使用的是不同的编译工具链,这个特性不一定存在。看到这里,想必大家已经清楚STM32编程中printf重定向背后的原理了。


关键词: STM32 编程

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章


用户评论

请文明上网,做现代文明人
验证码:
查看电脑版