STM32 串口調試中常遇到「配置正確、NVIC/GPIO 無誤,卻進不了 RXNE 接收中斷」的詭異現象。經大量實戰驗證,罪魁禍首往往是 **同時啟用 TXE(發送資料暫存器空)中斷** 導致的中斷風暴。本文深度剖析根因並給出標準化修復流程。
USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE); // 接收中斷
USART_ITConfig(USARTx, USART_IT_TXE, ENABLE); // 發送中斷 ← 關鍵問題行
USART_Cmd(USARTx, ENABLE);
現象:
🔴 程式跑飛、主迴圈卡死
🔴 RXNE 中斷服務程式 (ISR) 從未被調用
🔴 註釋掉 TXE 啟用行後一切恢復正常
USART_SendData() 才能清除旗位,否則無限重入// 初始化時僅啟用 RXNE
USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
// 實際需要發送資料時,再動態啟用 TXE
void USART_SendString(USART_TypeDef* USARTx, char *str) {
while (*str) {
USART_SendData(USARTx, *str++);
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); // 輪詢等待
}
}
// 或配合 DMA 發送,完全避免 TXE 中斷
void USARTx_IRQHandler(void) {
if (USART_GetITStatus(USARTx, USART_IT_TXE) != RESET) {
if (tx_buffer_has_data()) {
USART_SendData(USARTx, tx_buffer_pop()); // 寫入資料 → 自動清 TXE
} else {
USART_ITConfig(USARTx, USART_IT_TXE, DISABLE); // 無資料時關閉中斷
}
}
if (USART_GetITStatus(USARTx, USART_IT_RXNE) != RESET) {
rx_buffer_push(USART_ReceiveData(USARTx));
}
}
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2)(2 位搶佔 + 2 位響應)| 旗位 | 含義 | 適用場景 |
|---|---|---|
| TXE | 發送暫存器空,可寫入下一幀 | 連續發送、中斷/DMA 驅動 |
| TC | 傳輸完全結束(移位寄存器也空) | 最後一幀發送後切換模式/進入低功耗 |
掌握 TXE 中斷特性,杜絕「中斷風暴」導致的系統假死,是 STM32 串口穩定運行的關鍵一環。