USART(Universal Synchronous/Asynchronous Receiver/Transmitter,即通用同步/異步收發器)串行通信是單片機最常用的一種通信技術,通常用於單片機和電腦之間以及單片機和單片機之間的通信。
5.1 USART串行通信協議
5.1.1 波特率和數據格式
USART通信中的同步通信功能很少用到,大多情況下只採用異步通信,只能實現異步通信功能的接口就稱之為UART。UART通信通常以字節為單位組成數據幀,由通信收發雙方根據預先約定的波特率(傳輸速率)進行通信。
波特率表示每秒發送二進制數據位的速率,單位是bps,即位/秒,波特率越高,傳輸速度越快,常用的UART通信波特率有2400,4800,9600,115200等等。在進行串行通信之前,通信雙方需要設置波特率保持一致,否則不能正常通信。
單片機標準串口進行通信時,沒有數據傳輸時通信線路保持高電平狀態。當要發送數據時,先發送一位0,用以表示開始發送,叫做起始位。然後再按照低位在前,高位在後的順序發送8位數據。當8位數據發送完畢時,再發送一位1表示停止位。對於接收端而言,開始時傳輸線路一直保持高電平,一旦檢測到低電平,便準備開始接收數據。當接收完8位數據時,便檢測停止位,檢測完畢後,表示一幀數據發送完畢,開始準備接受下一幀數據。為了確保數據準確性,通常會在數據位之後設置校驗位。
串行通信的數據幀的格式由起始位、數據位、奇偶校驗位(可選)和停止位等部分組成,如圖5-1所示。
圖5-1 串口數據發送格式示意圖
5.1.2 TTL通信接口和RS232通信接口
電腦和單片機之間進行串口通信,通常使用USB轉UART芯片,將USB通信協議轉成UART協議和單片機通信,如圖5-2所示,CH340的6腳和7腳接到USB口上的D-和D+,3腳和4腳接到STM32的UART接口引腳上。Kingst-32F1開發板上CH340的3腳和4腳通過跳線帽選擇連接在STM32F103ZE單片機USART1的PA10和PA9引腳上。拔掉跳線帽USB轉串口模塊可以單獨使用,注意連接外部串口時設備之間要共地。
圖5-2 USB轉串口電路
單片機的串口接口標準一般是TTL或者CMOS,而除此之外,UART通信還有一種RS232串行通信接口,臺式電腦和早期的工業專用的筆記本電腦通常帶RS232接口。
RS232標準是個反邏輯,也叫做負邏輯。為何叫負邏輯?它的TXD和RXD的電壓,-3V~-15V代表是1,+3~+15V代表是0。低電平代表的是1,而高電平代表的是0,所以稱之為負邏輯。9針RS232串口是不能和單片機直接連接的,需要用一個電平轉換芯片MAX232或者SP3232來完成,這兩個芯片只是設計公司不同,其他是完全兼容的,具體電路如圖5-3所示。Kingst-32F1開發板中RS485和RS232共用USART2,使用時可以通過跳線帽選擇。
圖5-3 RS232轉串口電路圖
5.2 STM32F103ZE單片機USART串口介紹
STM32F103ZE單片機內部集成有3(USART)+2(UART)個串行通信接口,如表5-1所示。
在使用異步通信時也就是相當於有5個UART模塊,並且這5個模塊能同時進行數據發送和接收,互不干擾。除此之外STM32的USART模塊支持8位或9位長度的數據字;可配置1位或2位的停止位。
USART外設發送和接收的數據是通過數據寄存器(USART_DR)傳輸的。該寄存器兼具讀和寫的功能,實際上它是由發送數據寄存器(TDR)和接收數據寄存器(RDR)兩個寄存器組成,就好比一個房間有兩個門,一個只進不出,一個只出不進,如圖5-4所示。
圖5-4 USART數據發送和接收簡易結構圖
USART發送數據的大體流程:數據通過內部總線,先發送到TDR中,然後再由TDR移送到"發送移位寄存器",最後數據通過移位從TXD引腳輸出。當TDR中的數據傳送到移位寄存器後,TDR為空,同時硬件會設置一個"發送數據寄存器空(TXE)"的標誌位,此時可以把下一幀數據寫入TDR中,而不必等到移位寄存器發送完所有位,向TDR中寫入數據會清除TXE標誌位。當一幀數據發送完成(停止位發送後)且TXE=1(TDR為空),即沒有數據再寫入到TDR時,硬件會設置一個"發送完成(TC)"標誌位,表示最後一幀數據發送完畢,USART發送過程標誌位狀態如圖5-5所示。如果設置了TXEIE(TXE中斷使能位)或TCIE(TC中斷使能位),當TXE或TC標誌位被置位時,程序會執行串口中斷服務函數。需要注意的是當USART發送功能(TE位)激活後(初始化或復位時),將發送一個空閒幀(0xFF),如果此時沒有數據發送,則TXE標誌位和TC標誌位會一直處於"置位"狀態,如果使能了TXEIE或TCIE,程序會重複執行串口中斷服務函數,這將會大量佔用CPU資源。
在使用串口中斷髮送數據時,只要TDR寄存器為空,就可以寫入數據,而不需要等待數據發送完成,因此通常選擇檢測TXE標誌位,而不是TC標誌位。由於TDR寄存器一旦為空,TXE標誌位會硬件置位,進而觸發中斷,所以當不發送數據時要及時關閉發送中斷。
圖 5-5 USART發送數據過程狀態圖
USART接收數據的流程要比發送數據簡單很多。數據的最低有效位首先從RXD引腳移入到"接收移位寄存器",當一幀數據接收完成,接收移位寄存器將數據發送到接收數據寄存器(RDR)中。此時硬件會設置一個接收數據寄存器非空標誌位(RXNE),表示數據已經被接收並且可以讀出,如果設置了接收中斷,當檢測到RXNE標誌位時會執行中斷服務函數。讀取接收數據寄存器(RDR)中的數據可以自動清除RXNE標誌位。RXNE標誌位在下一字符接收前也可以手動清除,避免溢出錯誤。
5.3 USART配置流程
5.3.1 配置流程
USART中配置流程並不複雜,只需要按照要求設置相應參數即可。在配置時要分清USART標誌位和USART中斷標誌位,具體流程如下:
(1) 使能USART時鐘及配置相關引腳:在使能USART時鐘時,注意STM32F103ZE單片機的USART1模塊位於APB2總線上,USART2、USART3、UART4、UART5位於APB1總線上。USART雙向通信時至少需要TXD和RXD兩個引腳,其中TXD引腳配置為複用推輓輸出模式,RXD引腳配置為浮空輸入模式。
(2) USART外設初始化參數設置:初始化時要設置USART的波特率、數據長度、停止位、是否使用校驗位、使能USART的發送功能和接收功能,一旦激活發送功能,USART會發送一個空閒幀,最後使用USART_Init初始化函數進行初始化。
(3) USART中斷優先級設置:通過NVIC_Init函數配置串口中斷優先級。
(4) 使能USART中斷: 通過USART_ITConfig函數使能串口發送中斷和串口接收中斷。注意在此只使能串口接收中斷,發送中斷必須在發送前使能,發送完畢後關閉,否則程序會重複執行中斷服務函數。
(5) 使能USART外設:通過USART_Cmd函數使能USART外設,一旦使能,USART便開始工作。
(6) 編寫USART中斷服務函數:串口中斷服務函數需要使用中斷向量表中定義的函數名稱,具體如表5-2所示,中斷服務函數依舊是保存在stm32f10x_it.c文件中。
5.3.2 初始化參數
USART初始化結構體的成員,包括波特率、數據長度、停止位數、校驗位、模式設置、硬件控制流設置。在對USART初始化結構體成員設置參數時參考表5-3 USART初始化結構體參數設置列表。
5.3.3 USART中斷設置
USART_ITConfig函數是使能或者失能USART模塊的中斷,函數原型如下:void USART_ITConfig(USART_TypeDef* USARTx, u16 USART_IT, Functional StateNewState),待使能或者失能的 USART 中斷源如表5-4所示。USART發送數據時分為查詢方式和中斷方式,因查詢方式會較長時間的佔用CPU,可能耽誤對其它事件的響應處理,因此實際項目開發中一般採用中斷方式發送和接收數據,本章就以中斷方式為例來配置USART。初始化時先使能"接收中斷(USART_IT_RXNE)",而"發送中斷(USART_IT_TXE)"即用即開,用完關閉。
採用中斷方式發送數據和接收數據時,當程序進入中斷服務後需要判斷到來的是哪個中斷源,然後執行相應的函數。因此需要使用中斷標誌位檢測函數USART_GetITStatus(USART_TypeDef* USARTx, u16 USART_IT)檢測USART相應中斷標誌的狀態,比如:USART_GetITStatus (USART1, USART_IT_TXE)表示獲取發送中斷標誌位狀態,其他中斷標誌位可以參考表5-5。
當檢測到相應中斷標誌為後,有些硬件會自動清除相應標誌位,而硬件不能自動清除時往往需要手動清除,此時可以使用USART_ClearITPendingBit(USART_TypeDef* USARTx, u16 USART_IT)中斷標誌位清除函數,清除相應標誌位。中斷標誌位清除函數和中斷標誌位檢測函數使用相同的USART中斷標誌位參數,如表5-5所示。比如清除"發送數據寄存器空(TXE)"標誌位代碼如下:USART_ClearITPendingBit(USART_IT_TXE);
5.3.4 USART通信實例
單片機串口主要用於單片機與電腦以及單片機之間進行信息交互。通過前面幾節,基本瞭解了STM32串口的基本狀況和配置流程,接下來就是用USART1做一個簡單的串口收發實驗,實現串口助手發送單個字符到Kingst32-F1開發板,Kingst32-F1開發板收到字符後,對字符進行加1,然後重新發回到串口助手,並通過數碼管顯示該字符的十六進制數。首先還是先建立usart.c和usart.h驅動文件,根據前幾節所講的配置流程,編寫USART驅動函數,具體代碼如下:
5.3 實用串口通信例程
在實際應用中,單片機串口和計算機的上位機軟件之間往往需要信息交互,從而實現上
位機發送指令,單片機通過串口接收指令並做出應答,然後執行相應的操作,這就要求通信雙方具有一個合理的通信機制和邏輯關係。
在實際通信中,傳輸一幀(多個字節)數據時往往都是連續不斷的發送的,即發送完一個字節後會緊接著發送下一個字節,期間沒有間隔或間隔很短,而當這一幀數據都發送完畢後,就會間隔很長一段時間(相對於連續發送時的間隔來講)不再發送數據,也就是通信總線上會空閒一段較長的時間。根據這種現象可以建立一種程序機制:設置一個定時器用來計算總線的空閒時間。定時器在有數據傳輸時(即單片機接收到數據時)清零,而在總線空閒時(沒有接收到數據時)時累加,當它累加到一定時間(例程裡是30ms)後,就可以認定一幀完整的數據已經傳輸完畢了,於是告訴其它程序可以來處理數據了,本次的數據處理完後就恢復到初始狀態,再準備下一次的接收。那麼用於判定一幀結束的空閒時間取多少合適呢?它取決於多個條件,並沒有一個固定值,這裡介紹幾個需要考慮的原則:第一,這個時間必須大於傳輸一個字節的時間,很明顯單片機接收中斷產生是在一個字節接收完畢後,也就是一個時刻點,而其接收過程程序是無從知曉的,因此在至少一個字節傳輸時間內絕不能認為空閒已經時間達到了。第二,要考慮發送方的系統延時,因為不是所有的發送方都能讓數據嚴格無間隔的發送,因為軟件響應、關中斷、系統臨界區等等操作都會引起延時,所以還得再附加幾個到十幾個ms的時間。選取的30ms是一個折中的經驗值,它能適應大部分的波特率(大於1200)和大部分的系統延時(PC機或其它單片機系統)情況。
利用這種程序機制,上位機可以通過串口向單片機發送指令,進而控制相應的模塊,這個在實際項目中是非常有意義的。結合第四章的舞臺燈光例程,設計一個基於計算機串口調試助手發送相應指令到單片機模擬舞臺燈光程序中的按鍵選擇功能,實現舞臺燈光變換,其餘與舞臺燈光實驗完全相同。RGB控制指令如表5-6所示,單片機接收到控制指令後,如果指令正確,返回"done.",錯誤時返回"error."。其中type後面跟隨數字1~13,用來表示模式,比如發送type 1選擇模式1,如果type後面跟隨其他字符,雖然也會返回"done."但是並不會執行動作函數,僅表示發送指令格式正確。speed faster和speed slower指令用於控制閃縮和漸變速度,發送一次指令,速度變化一個等級。
具體代碼如下:
長按識別關注 “金沙灘工作室”
知識共享|助力夢想
閱讀更多 金沙灘工作室 的文章