前言
本篇文章對串口Usart進行講解,為后面的esp8266和語音模塊控制打好基礎。
1.串口USART
USART(Universal Synchronous/Asynchronous Receiver/Transmitter,通用同步 / 異步收發器) 是一種常見的串行通信接口,廣泛應用于嵌入式系統、單片機、傳感器、通信設備等領域,主要用于設備之間的數據傳輸。
它的核心功能和作用可以從以下幾個方面理解:
1.1.實現設備間的串行通信
串行通信:數據通過一根或幾根信號線逐位傳輸(與并行通信的多線同時傳輸相比),節省硬件引腳資源,適合遠距離或低成本的數據交換。
連接場景:例如單片機(如 STM32)與傳感器、藍牙模塊(如 HC-05)、Wi-Fi 模塊(如 ESP8266)、上位機(如電腦)等設備之間的通信,通常通過 USART 接口連接。
1.2. 支持同步和異步兩種通信模式
USART 的 “同步 / 異步” 特性使其靈活性很高:
異步模式(最常用):不需要專用的時鐘線,雙方通過預先約定的波特率(數據傳輸速率,如 9600bps、115200bps)同步數據,僅通過TX(發送線) 和RX(接收線) 傳輸數據。例如:電腦通過 USB 轉 TTL 模塊與 ESP8266 的通信,就是用異步模式,通過串口助手發送 AT 指令。
同步模式:需要額外的時鐘線(SCK)來同步數據傳輸,適合對時序要求嚴格的場景(如與某些傳感器或外設的高速通信)。
1.3. 數據傳輸的基本原理
數據以 “幀” 為單位傳輸,每一幀包含:起始位(標志數據開始)、數據位(實際傳輸的 8 位或 9 位數據)、校驗位(可選,用于驗證數據正確性)、停止位(標志數據結束)。
雙方需約定相同的波特率(如 9600、115200)、數據位、校驗位、停止位(稱為 “串口參數”),否則會出現數據傳輸錯誤。
1.4. 在嵌入式開發中的典型應用
指令控制:通過 USART 發送 AT 指令配置模塊(如 ESP8266 的 Wi-Fi 連接、藍牙模塊的配對)。
數據采集:傳感器(如溫濕度傳感器、GPS 模塊)通過 USART 向上位機或單片機發送采集到的數據。
調試輸出:單片機通過 USART 向上位機(如電腦)發送調試信息(如打印變量值、程序運行狀態),方便開發調試。
設備聯動:多個單片機或模塊通過 USART 組成通信網絡,實現數據共享或協同控制(如智能家居中多個設備的聯動)。
1.5. 與 UART 的區別
UART(Universal Asynchronous Receiver/Transmitter) 僅支持異步通信,沒有同步模式。
USART 是 UART 的增強版,既支持異步通信,也支持同步通信,功能更全面。在實際應用中,若無需同步模式,USART 通常也以異步模式使用,此時可視為 UART。
總之,USART 是嵌入式系統中設備間 “對話” 的重要橋梁,通過簡單的硬件連接(通常只需 TX、RX、GND 三根線)和軟件配置,即可實現穩定的數據傳輸,是物聯網、智能家居、工業控制等領域的基礎通信接口。
1.6.硬件介紹

2.代碼實現
2.1.STM32Cubemx配置
我們這里以輸出調試信息所用到的USART串口1為例。PA9為串口1的TXD、PA10為串口1的RXD。

我們將串口UART1配置為異步功能,Mode選擇為Asynchronous,與PC端的通訊波特率為115200 Bit/s。

因為我們只是向PC端發送一些調試信息,無需接收PC端的數據,所以我們無需打開中斷功能。
?
2.2.fputc重定向支持printf
在 STM32 開發中,標準庫函數(如printf())默認輸出到控制臺(如電腦終端),但在嵌入式系統中,通常需要將輸出重定向到串口。通過重寫fputc()函數,可以實現以下功能:
- 使用printf()調試:將調試信息通過串口發送到電腦,方便開發時查看。
- 與外部設備通信:通過串口向其他設備發送數據。
該函數的作用是將字符ch,通過 USART1 串口發送出去,并等待發送完成。
int fputc(int ch, FILE *f)
{//USART1->SR:USART1 的狀態寄存器,其中第 6 位(TXE)表示發送緩沖區是否為空。//0x40:二進制為0100 0000,用于檢查TXE位。//循環等待:直到TXE位被置 1(發送緩沖區為空),才繼續執行下一步。while( (USART1->SR & 0x40) == 0 );//USART1->DR:USART1 的數據寄存器,寫入此寄存器將觸發串口發送。//(uint8_t) ch:將字符轉換為無符號 8 位整數后發送。USART1->DR = (uint8_t) ch;//返回發送的字符(作為整數),表示操作成功。return ch;
}
2.3.printf使用
int main()
{printf("Demo run!!!\n"); delay_ms(1000);
}