STM32的printf函式重定向
在前面學習了STM32的串列埠程式設計,通過USART1向計算機的串列埠除錯助手列印資料,或者接收計算機串列埠除錯助手的資料,接下來我們可以實現STM32工程上的printf()函數了,方便用於程式開發中除錯資訊的列印。
1. 法1:使用MicroLIB庫
1.1 KEIL-MDK中的Use MicroLIB選項
在MDK開發環境中,
MicroLib是預設c庫的備選庫,它可裝入少量記憶體中,與嵌入式應用程式配合使用,且這些應用程式不在作業系統中執行。 MicroLib進行了高度優化以使程式碼變得很小,功能比預設c庫少,不具備某些ISO c特性,部分庫函式的執行速度也比較慢,如記憶體拷貝函式memcpy()。 MicroLib與預設c庫之間的主要差異在網上有許多文章都有寫到,這裡摘抄記錄: (1)MicroLib 不符合 ISO C 庫標準。 不支援某些 ISO 特性,並且其他特性具有的功能也較少。 (2)MicroLib 不符合 IEEE 754 二進位制浮點演算法標準。 (3)MicroLib 進行了高度優化以使程式碼變得很小。 (4)無法對區域設定進行配置。 預設 C 區域設定是唯一可用的區域設定。 (5)不能將 main() 宣告為使用引數,並且不能返回內容。 (6)不支援 stdio,但未緩衝的 stdin、stdout 和 stderr 除外。 (7)MicroLib對 C99 函式提供有限的支援。 (8)MicroLib不支援作業系統函式。 (9)MicroLib不支援與位置無關的程式碼。 (10)MicroLib不提供互斥鎖來防止非執行緒安全的程式碼。 (11)MicroLib不支援寬字元或多位元組字串。 (12)與stdlib不同,MicroLib不支援可選擇的單或雙區記憶體模型。MicroLib只提供雙區記憶體模型,即單獨的堆疊和堆區。
MicroLib提供了一個有限的stdio子系統,它僅支援未緩衝的stdin、stdout和stderr,那麼也就是說勾選了Use MicroLib選項後,在程式碼工程中就可以使用printf()函式咯? 然而事實並非如此,這樣直接使用printf()函式,其列印的字串最終不知道列印到何處。我們要做的是將除錯資訊列印到USART1中,所以需要對printf()函式所依賴的列印輸出函式fputc()重定向(MicroLib中的printf()函式列印操作依賴fputc())。
1.2 重定向fputc函式
在MicroLib的stdio.h中,fputc()函式的原型為:
int fputc(int ch, FILE* stream)
此函式原本是將字元ch列印到檔案指標stream所指向的檔案流去的,現在我們不需要列印到檔案流,而是列印到串列埠1。基於前面的程式碼:
#include <stdio.h>
int fputc(int ch, FILE* stream)
{
//USART_SendData(USART1, (unsigned char) ch);
//while (!(USART1->SR & USART_FLAG_TXE));
USART_SendChar(USART1, (uint8_t)ch);
return ch;
}
注意,需要包含標頭檔案stdio.h,否則FILE型別未定義。 勾選了Use MicroLib選項,重定向fputc()函式後,我們就可以在工程程式碼中使用printf()函數了:
int main(void)
{
USART_Configuration();
//USART_SendString(USART1, "HelloWorld\n");
//USART_SendChar(USART1, 'h');
printf("\r\nstm32f103rct6\r\n");
printf("\r\nCortex-M3\r\n");
while (1);
return 0;
}
printf()函式的使用方法跟之前一樣,執行結果:
2. 法2:不使用MicroLIB庫
2.1 半主機模式
半主機模式是ARM的一種機制,實現將來ARM應用程式程式碼的輸入/輸出請求傳送至執行著偵錯程式的主機。例如設定使用半主機模式下的ARM應用程式,可以使用printf()和scanf()來使用主機的顯示器和鍵盤,而不需要在ARM系統上搭配顯示器和鍵盤。 半主機通過一組定義好的軟體指令(如SVC)來實現的,這些指令在程式控制下產生異常,ARM應用程式呼叫半主機對應的異常處理函式,然後除錯代理處理該異常。
第二段話感覺理解起來有點模糊,但是第一段還是懂它在講什麼的。一般的ARM應用程式中並不需要半主機操作,在這裡為確保ARM應用程式中沒有連結MicroLib的半主機相關函式,我們要取消ARM的半主機工作模式。
2.2 實現程式碼
在工程中加上如下程式碼:
//取消ARM的半主機工作模式
#pragma import(__use_no_semihosting)
struct __FILE {
int handle;
};
FILE __stdout;
_sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f){
while((USART1->SR&0X40)==0);
USART1->DR = (u8) ch;
return ch;
}
上面的程式碼摘自正點原子的範例程式,具體每一行的意義目前也不大清楚。這樣操作後,在不使用MicroLib的前提下,仍能使用printf()函式將除錯資訊列印到USART1上了。
--------------------- 本文來自 bright261 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/qq_29344757/article/details/75363639?utm_source=copy