前言
在 PC 上運(yùn)行 C 語(yǔ)言時(shí),prinf 輸出的內(nèi)容會(huì)打印在電腦顯示器上,這是因?yàn)?prinf 默認(rèn)的輸出設(shè)備就是顯示器。 而當(dāng)我們?cè)?a target="_blank">單片機(jī)上,需要通過(guò) printf 函數(shù)將信息打印到串口,就要對(duì) printf 函數(shù)的輸出進(jìn)行重定向。
printf 輸出重定向的方法
printf 函數(shù)聲明如下:
int printf(const char *format, ...);
printf 函數(shù)根據(jù) format 字符串給出的格式打印輸出到 stdout(標(biāo)準(zhǔn)輸出)中,當(dāng)然,printf 函數(shù)是不會(huì)一個(gè)字符一個(gè)字符去輸出,它會(huì)調(diào)用更底層的 I/O 函數(shù)去逐個(gè)字符打印。
printf 是庫(kù)函數(shù),不同編譯器對(duì) C庫(kù)的底層實(shí)現(xiàn)機(jī)制是不同的,因此 printf 中調(diào)用了哪個(gè)底層 I/O 函數(shù)來(lái)輸出字符,需要根據(jù)當(dāng)前使用的編譯器來(lái)確定。
我們實(shí)現(xiàn) printf 輸出重定向的方法就是找到當(dāng)前使用的編譯器中,printf 調(diào)用了哪個(gè)底層 I/O 函數(shù)來(lái)輸出字符,再改寫(xiě)該函數(shù),將字符通過(guò)串口輸出。
如何確定輸出字符的底層 I/O 函數(shù)?
以 Keil 為例,點(diǎn)擊菜單欄 Help ==> μVision Help 選項(xiàng),打開(kāi)幫助文檔。
如果你是51單片機(jī)項(xiàng)目,那么使用的編譯器是 Keil C51,打開(kāi)的就是 C51 的幫助文檔; 如果你是 ARM 單片機(jī)項(xiàng)目,那么使用的編譯器是 Keil MDK,打開(kāi)的就是 ARM 的幫助文檔。
查找 printf 關(guān)鍵字,可以看到 C51 的 printf 底層是調(diào)用 putchar 函數(shù)實(shí)現(xiàn)字符輸出的:

而 ARM 的 printf 函數(shù)底層是調(diào)用 fputc函數(shù)實(shí)現(xiàn)字符輸出的:

從上述的結(jié)果可知,要想通過(guò) printf 向串口打印調(diào)試信息,C51 單片機(jī)需要改寫(xiě) putchar( ) 函數(shù),而 ARM 單片機(jī)則需要改寫(xiě) fputc( ) 函數(shù)。
C51 和 ARM 項(xiàng)目中,printf 輸出重定向的方法是不一樣的,這就是有些人把 STM32 的 printf 搬到 C51 中會(huì)出錯(cuò)的原因之一。
C51 重定向 printf 輸出的注意事項(xiàng)
C51 重定向 printf 函數(shù)的輸出到串口,需要改寫(xiě) putchar 函數(shù),偽代碼如下:
char putchar (char ch)
{
SBUF0 = ch;
while( !(SCON0 & (1<<1)));
SCON0 &=~(1<<1);
return 0;
}
使用 printf 函數(shù)前,需要包含
51單片機(jī)重定向 printf 函數(shù)后,如果直接像 PC機(jī)或者是 32位單片機(jī)那樣使用 %d 占位符打印數(shù)值,輸出的數(shù)值可能是錯(cuò)誤的,例如下面的代碼輸出結(jié)果可能就是不正確:
int i = 10;
printf("%d", i);
Keil 中擴(kuò)展了 b、h、l 來(lái)設(shè)置字節(jié)寬度:
- b - 8位
- h - 16bit (默認(rèn))
- l - 32位
在 Keil C51中,用 printf 輸出一個(gè)單字節(jié)變量時(shí),要使用%bd,例如:
unsigned char x = 'A';
printf("x: %bd\\n", x);
這些內(nèi)容在 Keil C51 幫助文檔關(guān)于 printf 的章節(jié)中有提到:

擴(kuò)展知識(shí)
不知道有沒(méi)小伙伴發(fā)現(xiàn),如果項(xiàng)目中沒(méi)有重寫(xiě) putchar 或 fputc 函數(shù),直接調(diào)用 printf 也不會(huì)報(bào)錯(cuò),只是 printf 打印的內(nèi)容不知道輸出到哪里罷了。
printf 函數(shù)里面調(diào)用了更加底層的 putchar 或 fputc 函數(shù)而沒(méi)有報(bào)錯(cuò),說(shuō)明在 C庫(kù)里面已經(jīng)實(shí)現(xiàn)了 putchar 或 fputc 函數(shù),那為什么我們?cè)?C庫(kù)外重新實(shí)現(xiàn) putchar 或 fputc 函數(shù)時(shí),編譯器沒(méi)有報(bào)重復(fù)定義的錯(cuò)誤呢?
這是因?yàn)樵?C庫(kù)里,putchar 或 fputc 函數(shù)被定義成了弱函數(shù)(weak),當(dāng)你定義了 putchar 或 fputc 函數(shù),那么編譯時(shí)就使用你定義的函數(shù),否則就使用 C庫(kù)中的 putchar 或 fputc 函數(shù)。
關(guān)于 C語(yǔ)言的弱函數(shù)相關(guān)內(nèi)容,這里不再展開(kāi)來(lái)講,感興趣的小伙伴可自行查閱相關(guān)資料。
-
單片機(jī)
+關(guān)注
關(guān)注
6076文章
45500瀏覽量
670665 -
顯示器
+關(guān)注
關(guān)注
22文章
5147瀏覽量
144420 -
C語(yǔ)言
+關(guān)注
關(guān)注
183文章
7644瀏覽量
145651 -
串口
+關(guān)注
關(guān)注
15文章
1620瀏覽量
82872 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4417瀏覽量
67550
發(fā)布評(píng)論請(qǐng)先 登錄
stm32系列單片機(jī)之printf重定向
STM32重定向printf的方法總結(jié)
STM32重定向printf的方法是什么?
重定向printf() 函數(shù)
重定向printf輸出到串口輸出的方法
重定向printf函數(shù)到串口輸出的方法
實(shí)現(xiàn)重定向printf()和scanf() 函數(shù)案例分析
單片機(jī)printf重定向的函數(shù)免費(fèi)下載
51單片機(jī)printf重定向
單片機(jī)printf( )重定向到串口
【STM32Cube_09】重定向printf函數(shù)到串口輸出的多種方法
Keil下使用STlink重定向printf的配置
STM32單片機(jī)基礎(chǔ)09——重定向printf函數(shù)到串口輸出的多種方法
如何實(shí)現(xiàn)Printf()接口重定向到UART
printf輸出重定向的方法
評(píng)論