C語言中有個(gè)很好用的函數(shù):printf()。printf()是格式化輸出函數(shù),可以按照規(guī)定格式輸出消息。相信每個(gè)工程師開始學(xué)習(xí)的C語言第一課都會(huì)遇到printf(“Hello World! n”);這條語句。
在嵌入式開發(fā)中,我們調(diào)試時(shí)時(shí)常需要輸出一些調(diào)試信息,那這時(shí)候printf語句就非常有用了。但是遺憾的是,C標(biāo)準(zhǔn)庫(kù)函數(shù)中默認(rèn)的輸出設(shè)備是顯示器,所以當(dāng)我們進(jìn)行嵌入式開發(fā)的時(shí)候,是不能夠直接使用printf的。如果我們想要方便的在嵌入式開發(fā)中進(jìn)行printf操作,那么就必須重定向printf語句。
我們可以查一下C標(biāo)準(zhǔn)庫(kù)函數(shù),printf語句其實(shí)是使用了一個(gè)函數(shù)int fputc(int ch, FILE *f); 此函數(shù)原本是將字符ch打印到文件指針?biāo)赶虻奈募髦腥サ?,現(xiàn)在我們不需要打印到文件流,而是打印到串口1。我們只需要重新編寫這個(gè)函數(shù)。當(dāng)系統(tǒng)檢測(cè)到用戶編寫的fputc函數(shù)時(shí),就會(huì)調(diào)用用戶所編寫的函數(shù),而不是使用原本的fputc了。
函數(shù)如下:
注意這里需要使用到頭文件stdio.h,否則FILE類型未定義。以上是基于MDK環(huán)境下,使用MicroLib的情況下重定向printf。還有一種方法是使用半主機(jī)模式。半主機(jī)模式是ARM的一種機(jī)制,不使用microLib庫(kù),實(shí)現(xiàn)ARM應(yīng)用程序代碼的輸入/輸出請(qǐng)求傳至運(yùn)行著調(diào)試器的主機(jī),這樣就可以使用主機(jī)的顯示器和鍵盤,而不需要再ARM系統(tǒng)上搭配顯示器和鍵盤。當(dāng)然,這種做法并不常見,有興趣的同學(xué)可以自己研究一下。
如果這篇文章到這里就結(jié)束了,那么就太常規(guī)了。下面我還要講一個(gè)非常規(guī)的操作以實(shí)現(xiàn)串口輸出字符串。
Printf重定向的方法是非常常規(guī)的,但是我就是不想用,而且我還想調(diào)用一個(gè)函數(shù)就能輸出一串任意的字符串,怎么辦?我就想出了另一種寫法,先貼代碼:
乍一看,這段代碼非常簡(jiǎn)單啊,就是使用了一個(gè)指針,然后串口輸出的時(shí)候指針指向的地址不停+1啊!但是我們?cè)倏匆幌抡{(diào)用:
我們這里直接將一個(gè)字符串作為參數(shù)進(jìn)行了傳遞,編譯器報(bào)了一個(gè)警告:warning: ‘char[25]’ to parameter of type ‘uint8_t *’ (aka ‘unsigned char *’) converts between pointers to integer types with different sign。
很明顯,數(shù)據(jù)類型沖突了。但是在程序中我們將兩種方式都進(jìn)行了輸出,最后發(fā)現(xiàn)調(diào)試結(jié)果是正確的。如下圖所示。
這是為什么呢?其實(shí)也很簡(jiǎn)單,我們這里進(jìn)行了一個(gè)非法操作。當(dāng)我們調(diào)用該函數(shù)時(shí),將字符串?dāng)?shù)組作為實(shí)參,在函數(shù)定義中強(qiáng)制轉(zhuǎn)換成了一個(gè)指針。而這個(gè)指針,指向的是字符串?dāng)?shù)組的第一個(gè)地址,所以該函數(shù)運(yùn)行時(shí)就能夠正確輸出我們所編寫的字符串了。
-
顯示器
+關(guān)注
關(guān)注
21文章
4862瀏覽量
139353 -
STM32
+關(guān)注
關(guān)注
2258文章
10828瀏覽量
352490 -
ARM處理器
+關(guān)注
關(guān)注
6文章
360瀏覽量
41517 -
C語言
+關(guān)注
關(guān)注
180文章
7575瀏覽量
134090 -
調(diào)試器
+關(guān)注
關(guān)注
1文章
297瀏覽量
23568
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論