首先了解STM32串口發送數據的簡單過程,如下圖所示。
發送:軟件將數據寫到USARTx->DR里面,硬件自動把USARTx->DR里面的數據並行轉移到“發送一位知寄存器”,然后硬件自動將發送一位寄存器中的數據通過TX引腳串行發送出去。接收:RX上有數據過來,則先將數據一位一位的放到“接收移位寄存器”里面,收滿一個字節后,硬件自動將“接收移位寄存器”里面的數據並行轉移到USARTx->DR里面。
while (!(USART1->SR & USART_FLAG_TC));這句是等待數據完完全全從“發送移位寄存器”中發送出去,while (!(USART1->SR & USART_FLAG_TXE));這句是等待數據從USARTx->DR轉移到“發送移位寄存器”中。在后一句的寫道法中,並不需等待數據完全發送,只需要USARTx->DR里面的數據已經被轉移走,就可以馬上進行再次寫入USARTx->DR操作,這樣是不是就可以節省很多時間了?至於出現亂碼,你需要綜合其他的代碼來進行分析。
舉例:STM32 uart發送數據,查詢 USART_FLAG_TC 正常,但使用 USART_FLAG_TXE 會亂碼。
在一個發送單字節的函數中我用下面寫法可以正常工作
USART1->DR = ch & 0xff;
while (!(USART1->SR & USART_FLAG_TC));
但是如果第二句寫成
while (!(USART1->SR & USART_FLAG_TXE));
就會在連續調用這個函數時輸出亂碼(一般第一個字符是正確的)。
分析問題:收發沖突
1、和接收發送沖突,情況可能會是這樣的:“發送移位寄存器”中的內容正在被發送到TX,且USARTx->DR中也有等待被發送的數據,這時候有數據接收過來,新接收的數據也是需要存放在USARTx->DR里面的,這樣也許會導致不可預知的錯誤發生。
2、在你發送的最后一個字節上,假設你發送完最后一個字節后就關閉了串口或者關閉發送功能等等,那就會發生錯誤或亂碼,因為:
在while (!(USART1->SR & USART_FLAG_TXE));之后表示數據已經轉移到“發送移位寄存器”中,此時要發送的是最后一個字節,這時你認為數據已經完全發送,但實際上此時數據並沒有真正意義上的完全發送,還需要等待“發送移位寄存器”中的數據發送出去才算是完全發送,而也就在這時你關閉了串口,那么最后這個字節的發送是失敗的,會產生錯誤或亂碼。