首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

STM32Cube 實現 printf 串口輸出與單字節中斷接收

     編輯:關於C++

背景

STM32Cube HAL 庫提供的 HAL_UART_Transmit/Receive 系列函數需預知數據長度,無法直接支援 printf 這類流式輸出,也無單字節收發介面。本文給出最小改動方案:重寫 fputc 實現 printf,並手寫中斷服務函數實現單字節接收回顯。

1. 實現 printf(重定向 fputc)

在 main.c 或獨立文件添加:

#include <stdio.h>
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE {
    // 等待發送完成標誌(阻塞式,不開啟 TX 中斷)
    huart1.Instance->DR = (uint8_t)ch;
    while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);
    return ch;
}

注意:必須關閉 UART 發送中斷(TXEIE),否則進入死等待。CubeMX 生成代碼默認未開啟 TX 中斷,滿足條件。

2. 單字節中斷接收回顯

修改中斷服務函數 USART1_IRQHandler

void USART1_IRQHandler(void) {
    if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) == SET) {
        static uint8_t buf[100], cnt = 0;
        buf[cnt] = (uint8_t)(huart1.Instance->DR & 0xFF);  // 讀取數據寄存器自動清標誌
        huart1.Instance->DR = buf[cnt];                    // 回顯發送
        if (++cnt >= 100) cnt = 0;
    }
}

啟用接收中斷(在 HAL_UART_MspInit 中)

void HAL_UART_MspInit(UART_HandleTypeDef* huart) {
    if (huart->Instance == USART1) {
        // ... GPIO、時鐘、NVIC 初始化 ...
        HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
        // 關鍵:手動置位 RXNEIE 位
        huart->Instance->CR1 |= USART_CR1_RXNEIE;
    }
}

3. 測試任務(FreeRTOS 示例)

void LED_Task2(void const * argument) {
    while (1) {
        HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_14);
        printf("LED_Task2\r\n");
        osDelay(2000);
    }
}

4. 原理總結

5. 代價與替代方案

  • 犧牲:Cube HAL 的 HAL_UART_Transmit_IT/DMA、HAL_UART_Receive_IT/DMA 將不可用。
  • 替代:若需保留 HAL 異步收發,可改用 HAL_UART_Transmit_IT 發送單字節,並在 HAL_UART_TxCpltCallback 中處理緩衝隊列;接收端用 HAL_UART_Receive_IT 循環單字節接收。代碼量較大但功能完整。

6. 適用場景

適合調試階段、數據量小、實時性要求不高的項目。正式產品建議使用環形緩衝區 + DMA/中斷的完整驅動框架。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
功能關鍵點
printf 輸出重寫 fputc/__io_putchar,阻塞輪詢 TC 標誌,不使用 HAL 發送函數
單字節接收在 IRQHandler 讀 DR 寄存器,手動啟用 RXNEIE,不使用 HAL_UART_Receive_IT
衝突避免禁用 HAL 發送中斷,禁用 HAL 接收中斷回調,完全接管 UART 硬件