STM32printf重定向到串口含armcc和gcc兩種方案

STM32串口重定向:MDK與GCC環境下需重寫的函數差異

在嵌入式開發中,尤其是使用 STM32系列微控制器 的項目中,調試信息的輸出是不可或缺的一部分。為了方便調試,開發者通常會選擇將 printf 等標準輸出函數通過 UART 串口發送到 PC 端進行查看和分析。

然而,在不同的編譯器環境中(如 MDK(Keil)GCC),實現標準輸出函數重定向的方式存在差異。本文將詳細介紹如何在這兩種環境下完成串口重定向,并指出它們之間需要重寫的函數區別。


? 一、重定向的基本原理

無論是在 MDK 還是 GCC 編譯環境下,串口重定向的核心思想都是通過重寫底層的字符輸出函數,使得標準庫中的 printf 系列函數能夠通過串口發送數據。

標準 C 庫中的 printf 函數最終會調用底層的字符輸出函數,而不同編譯器對這些底層函數的命名和接口定義略有不同。因此,開發者需要根據所使用的編譯器環境,選擇并實現對應的函數。


🛠? 二、在不同編譯器下的實現方法

1. Keil MDK 環境(ARMCC / AC6)

Keil MDK 中,標準輸入輸出函數依賴于 ARM 自帶的 C 標準庫。要重定向 printf,需要重寫 _sys_write() 或者更常用的 fputc() 函數。

// Keil MDK 下的標準重定向函數
int __io_putchar(int ch)
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);return ch;
}

或者使用傳統的:

int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);return ch;
}

?? 注意:如果使用的是 ARM Compiler 6(即基于 LLVM 的編譯器),建議優先使用 __io_putchar()


2. GCC 編譯器環境(適用于 STM32CubeIDE、Makefile + arm-none-eabi-gcc)

在 GCC 環境下,標準輸出函數依賴于新lib庫(newlib-nano)。此時需要實現 _write() 函數來捕捉 write() 調用,從而完成串口輸出。

// GCC 下的重定向函數
int _write(int fd, char *ptr, int len)
{HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, HAL_MAX_DELAY);return len;
}

該函數接收文件描述符 fd(通常我們忽略它)、指向字符串的指針 ptr,以及長度 len,然后將整個緩沖區通過串口發送出去。


🔁 三、統一方式:使用宏定義簡化適配

為了兼容不同編譯器,可以使用預處理器宏定義統一代碼風格,避免重復編寫兩個版本。

// 通用重定向頭文件或代碼段
#ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endifPUTCHAR_PROTOTYPE
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);return ch;
}// GCC 特定部分
#ifdef __GNUC__
int _write(int fd, char *ptr, int len)
{HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, HAL_MAX_DELAY);return len;
}
#endif

這樣處理后,只需切換編譯器即可自動適配對應函數,提高代碼復用性和可維護性。


💡 四、注意事項

  • 串口句柄:確保 &huart1 已被正確初始化并在全局作用域中可用。
  • 阻塞問題HAL_UART_Transmit() 是阻塞函數,若用于中斷上下文或實時性強的場景,請改用非阻塞方式(如DMA或中斷發送)。
  • 性能優化:頻繁調用 printf() 可能影響性能,建議僅用于調試階段。
  • 重定向范圍:除了輸出,還可以重定向輸入(如 scanf),但需重寫對應的 _read()fgetc()

📌 五、總結

編譯器需重寫的函數函數原型
MDK(Keil)fputc / __io_putcharint fputc(int ch, FILE *f) / int __io_putchar(int ch)
GCC_writeint _write(int fd, char *ptr, int len)

通過以上方式,我們可以靈活地在 STM32 開發中實現串口重定向,為調試提供極大的便利。


📚 參考資料

  • CSDN 博客 - 原文鏈接
  • ST官方 HAL 庫文檔
  • GCC 新版標準庫(newlib-nano)說明文檔

📢 如您發現任何錯誤或有改進建議,歡迎留言交流!


版權聲明:本文為原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請注明出處并保留原文鏈接。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/82376.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/82376.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/82376.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++ 文本讀寫與二進制讀寫的底層機制

1.文件的打開方式 1.文本打開 在windows中,寫入時會將\n換成\r\n,讀出時\r\n會讀出\n linux對\n讀寫不做處理 2.二進制打開 對\n讀寫不做處理 2.文本讀寫 1.數據要先變成字符串再寫進緩沖區 2.字符串直接寫進緩沖區就是 3.c對文本讀寫的支持 istream/ostream中重載了對…

02 mysql 管理(Windows版)

一、啟動及關閉 MySQL 服務器 1.1 通過 “服務” 管理工具 winr打開運行,輸入services.msc 找到MySQL80,這個是我們在安裝mysql的時候給的服務的名稱,具體見文章mysql 安裝 右鍵選擇啟動或者停止。 1.2 通過命令提示符 1.2.1 關閉命令…

Elasticsearch知識匯總之 ElasticSearch高可用方案

六 ElasticSearch高可用方案 6.1 高可用架構 請求協調節點根據負載均衡,轉發給主分片節點,主分片同步復制給從節點,主從節點都寫入完成返回客戶端請求成功。對于讀請求,協調負載到任意節點數據節點,數據節點把各自符合…

H5 移動端適配最佳實踐落地指南。

文章目錄 前言一、為什么需要移動端適配?二、核心適配方案1. 視口(Viewport)設置2. 三種適配方案 (僅供參考)(1)rem 適配方案(2)vw/vh 適配方案(3&#xff09…

MySQL初階:數據庫約束和表的設計

數據庫約束 數據庫約束是針對數據庫中的表中的數據進行施加規則和條件,用于確保數據的準確性和可靠性。 數據庫約束類型 1)not null 非空類型 :指定非空類型的列不能存儲null,如果插入的數據是null便會報錯。 2)de…

LVGL- 按鈕矩陣控件

1 按鈕矩陣控件 lv_btnmatrix 是 LVGL(Light and Versatile Graphics Library) v8 中提供的一個非常實用的控件,用于創建帶有多個按鈕的矩陣布局。它常用于實現虛擬鍵盤、數字鍵盤、操作面板、選擇菜單等場景,特別適用于嵌入式設…

excel 批量導出圖片并指定命名

一、開發環境 打開excel文件中的宏編輯器和JS代碼調試 工具-》開發工具-》WPS宏編輯器 左邊是工程區,當打開多個excel時會有多個,要注意不要把代碼寫到其他工作簿去了 右邊是代碼區 二、編寫代碼 宏是js語言,因此變量或者方法可以網上搜…

yolov5基礎--yolov5源碼閱讀(common.py)

🍨 本文為🔗365天深度學習訓練營 中的學習記錄博客🍖 原作者:K同學啊 博主簡介:努力學習的22級本科生一枚 🌟?;探索AI算法,C,go語言的世界;在迷茫中尋找光芒…

5.0.5 變換(旋轉、縮放、扭曲)

WPF變換可以產生特殊效果,如平移、旋轉、扭曲。 變換類 描述TranslateTransform沿著X軸和Y軸平移ScaleTransform 沿著定義的中心點縮放RotateTransform沿著定義的中心點旋轉SkewTransform 扭曲元素MatrixTransfrom提供3x3矩陣,用于定義一個自定義變換 1…

如何設置內網映射端口到外網訪問?哪些軟件可以進行端口映射?

大多數時候我們所使用的服務器都是在內網搭建的,而且內網是可以訪問外網的,但外網是沒法直接訪問內網IP和端口服務的。也就是說外網無法直接訪問到內網的網絡地址,需要大家去搭建一個內外網互通的橋梁,把內網服務器指定端口映射到…

養生:塑造健康生活的良方

養生是一場貫穿生活的自我關愛行動,從飲食、運動、睡眠到心態調節,每一個環節都對健康有著深遠影響。以下為你帶來全面且實用的養生策略。 飲食養生:科學搭配,呵護腸胃 合理規劃三餐,遵循 “早營養、午均衡、晚清淡”…

YOLOv12云端GPU谷歌免費版訓練模型

1.效果 2.打開 https://colab.research.google.com/?utm_sourcescs-index 3.上傳代碼 4.解壓 !unzip /content/yolov12-main.zip -d /content/yolov12-main 5.進入yolov12-main目錄 %cd /content/yolov12-main/yolov12-main 6.安裝依賴庫 !pip install -r requirements.…

機器人手臂的坐標變換:一步步計算齊次矩陣過程 [特殊字符]

大家好!今天我們來學習如何計算機器人手臂的坐標變換。別擔心,我會用最簡單的方式解釋這個過程,就像搭積木一樣簡單! 一、理解問題 我們有一個機器人手臂,由多個關節組成。每個關節都有自己的坐標系,我們需要計算從世界坐標系(W)到末端執行器(P?)的完整變換。 二、已…

CSS中的@import指令

一、什么是import指令&#xff1f; import 是CSS提供的一種引入外部樣式表的方式&#xff0c;允許開發者在CSS文件中引入其他CSS文件&#xff0c;或者在HTML的<style>標簽中引入外部樣式。與常見的<link>標簽相比&#xff0c;import 提供了一種更“CSS原生”的樣式…

[學成在線]23-面試題總結

1. 詳細說說你的項目吧 從以下幾個方面進行項目介紹: 項目的背景&#xff0c;包括: 是自研還是外包、什么業務、服務的客戶群是誰、誰去運營等問題。項目的業務流程項目的功能模塊項目的技術架構個人工作職責個人負責模塊的詳細說明&#xff0c;包括模塊的設計&#xff0c;所…

C++編程語言:標準庫:標準庫概觀(Bjarne Stroustrup)

第30章 標準庫概觀(Standard-Library Overview) 目錄 30.1 引言 30.1.1 標準庫設施 30.1.2 設計約束 30.1.3 描述風格 30.2 頭文件 30.3 語言支持 30.3.1 對initializer_list的支持 30.3.2 對范圍for的支持 30.4 異常處理 30.4.1 異常 30.4.1…

spring5.x講解介紹

Spring 5.x 是 Spring Framework 的重要版本升級&#xff0c;全面擁抱現代 Java 技術棧&#xff0c;其核心改進涵蓋響應式編程、Java 8支持、性能優化及開發模式創新。以下從特性、架構和應用場景三個維度詳細解析&#xff1a; 一、核心特性與架構改進 Java 8 全面支持 Spring …

【C++進階】第2課—多態

文章目錄 1. 認識多態2. 多態的定義和實現2.1 構成多態的必要條件2.2 虛函數2.3 虛函數的重寫或覆蓋2.4 協變(了解)2.5 析構函數的重寫2.6 override和final關鍵字2.7 重載、重寫、隱藏對比 3. 純虛函數和抽象類4. 多態原理4.1 虛函數表指針4.2 多態的實現4.3 靜態綁定和動態綁定…

Dive into LVGL (1) —— How LVGL works from top to down

0.briefly speaking 由于工作原因&#xff0c;最近開始接觸到一些圖形圖像處理相關的知識&#xff0c;在這個過程中逐漸接觸到了LVGL。作為一個開源的圖形庫&#xff0c;LVGL可以高效地為MCU、MPU等嵌入式設備構建美觀的UI界面。我的手頭也正好有一塊集成了Vivante 2.5D GPU的…

【HarmonyOS 5】鴻蒙中進度條的使用詳解

【HarmonyOS 5】鴻蒙中進度條的使用詳解 一、HarmonyOS中Progress進度條的類型 HarmonyOS的ArkUI框架為開發者提供了多種類型的進度條&#xff0c;每種類型都有其獨特的樣式&#xff0c;以滿足不同的設計需求。以下是幾種常見的進度條類型&#xff1a; 線性進度條&#xff08;…