遇到這種情況 你需要添加這幾行代碼
問:在STM32上輕松使用printf函數(shù)
除了點(diǎn)亮LED外,向串行控制臺發(fā)送打印信息可能是調(diào)試嵌入式項(xiàng)目時(shí)最簡單、最直接且最常用的技術(shù)。雖然大多數(shù)平臺都擁有可以在UART總線上傳輸數(shù)據(jù)的API,但它們在功能和普及度上都遜于printf() 函數(shù)。但在嵌入式C應(yīng)用應(yīng)用中僅僅利用此函數(shù)包含stdio 庫是遠(yuǎn)遠(yuǎn)不夠的。在STM32項(xiàng)目中,我們還需要額外添加幾行代碼。
如果你希望在UART總線上 傳輸 和 接收 格式化數(shù)據(jù),請查看附屬文章在STM32上輕松使用scanf !
步驟
此程序涵蓋了配置和啟用適當(dāng)?shù)腢ART外設(shè)的預(yù)備步驟、將該UART實(shí)例映射到printf() 函數(shù)的主要步驟,以及用于打印浮點(diǎn)數(shù)的可選輔助步驟。本文適用于使用STM32CubeIDE 20(版本1.11.2)開發(fā)的項(xiàng)目,但也可以展開以用于其他環(huán)境。
0 建立UART實(shí)例
為了在接下來的步驟中正確地使用stdio 庫中的printf() 函數(shù),我們必須配置一個(gè)UART(或USART)外設(shè)以傳輸格式化字符串。通常情況下,在ST開發(fā)板上操作時(shí),應(yīng)選擇可以連接到ST-LINK編程器/調(diào)試器RX和TX引腳的UART外設(shè)。因?yàn)?,這樣可以通過ST-LINK的USB虛擬COM端口橋接將字符串發(fā)送到串行控制臺。幸運(yùn)的是,在STM32CubeIDE或STM32CubeMX中啟動(dòng)新項(xiàng)目時(shí),該UART實(shí)例已默認(rèn)配置完畢!作為程序員,你只需要留意已經(jīng)配置的具體UART,然后繼續(xù)下一步操作即可。
對于那些已有項(xiàng)目但未配置UART的用戶,只需打開項(xiàng)目的.ioc 文件,并按照圖1所示進(jìn)行修改即可。具體來說,
選擇適當(dāng)?shù)耐庠O(shè)實(shí)例
設(shè)置模式和配置參數(shù)(通常使用的設(shè)置如圖1所示)
確保將適當(dāng)?shù)腉PIO引腳配置為UART RX和TX。
完成后,保存.ioc 文件以生成項(xiàng)目的代碼。
圖 1 : 啟用和配置所需的U(S)ART外設(shè)的示例
1 重新定向printf() 至UART實(shí)例
UART準(zhǔn)備就緒后,只需添加幾行代碼即可添加printf() 。
a. 將#include <stdio.h> 添加到main.c 文件頂部的“包含”部分中(圖2)。
圖2:納入stdio庫
b. 在main.c 文件中,將以下代碼復(fù)制并粘貼到main() 函數(shù)前、UART句柄聲明之后的位置。你可以選擇“私有函數(shù)原型”部分,如下圖3所示。請注意,UART句柄必須從&huart?更改為所需UART外設(shè)的句柄(例如 &huart2)。
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart?, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
圖3:將重新定向代碼添加到main.c文件中
printf() 函數(shù)現(xiàn)在應(yīng)該可以按預(yù)期運(yùn)行了,除了浮點(diǎn)格式說明符。要啟用這些格式說明符,請繼續(xù)下一步。
2 啟用浮點(diǎn)支持(可選)
為了說明浮點(diǎn)格式化的問題,我們可以使用printf() 參考頁面提供的示例代碼。
printf("Characters: %c %cn", 'a', 65);
printf("Decimals: %d %ldn", 1977, 650000L);
p rintf("Preceding with blanks: %10dn", 1977);
printf("Preceding with zeros: %010dn", 1977);
printf("Some different radices: %d %x %o %#x %#on", 100, 100, 100, 100, 100);
printf("floats: %4.2f %+.0e %En", 3.1416, 3.1416, 3.1416);
printf("Width trick: %*dn", 5, 10);
printf("%sn", "A string");
在將此代碼添加到項(xiàng)目后,系統(tǒng)會顯示警告,說明“不支持浮點(diǎn)格式化”。如果我們繼續(xù)構(gòu)建并運(yùn)行項(xiàng)目,串行控制臺上的輸出將確認(rèn)不會打印浮點(diǎn)數(shù)(圖4)。
圖4:未啟用浮點(diǎn)格式化支持的輸出示例
如果你的應(yīng)用中未使用浮點(diǎn)數(shù),那這可能就不是什么問題。但如果你需要使用浮點(diǎn)數(shù),則可在“項(xiàng)目資源管理器”(Project Explorer)中右鍵單擊項(xiàng)目名稱,并選擇屬性(Properties ) 。在“C / C ++ Build”類別下選擇設(shè)置(Settings ) ,并在工具設(shè)置選項(xiàng)卡下選擇MCU( MCU Settings) 設(shè)置 。勾選“從newlib-nano使用printf的浮點(diǎn)數(shù)”旁邊的復(fù)選框,如下圖5所示。點(diǎn)擊應(yīng)用并關(guān)閉( Apply and Close ) 。
請注意,啟用printf() 的浮點(diǎn)格式化支持將消耗相當(dāng)數(shù)量的額外內(nèi)存。具體來說,除了在未啟用浮點(diǎn)支持時(shí)printf() 函數(shù)所消耗的內(nèi)存之外,啟用后還將消耗約0.35 KB的RAM和10.30 KB的閃存,這對低端設(shè)備而言已經(jīng)是個(gè)問題。
圖5:啟用浮點(diǎn)格式化支持
現(xiàn)在,在重新構(gòu)建項(xiàng)目并運(yùn)行代碼后,浮點(diǎn)數(shù)值已經(jīng)正確格式化,并如圖6所示。
圖6:啟用浮點(diǎn)格式化支持的輸出示例
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請聯(lián)系工作人員刪除。