作者:junziyang
(注:如非特別聲明,以下筆記內(nèi)容均針對(duì)STM32F103ZET6而言。不同型號(hào),細(xì)節(jié)可能存在差別。)
6.1 USART簡(jiǎn)介
USART全稱為Universal synchronous asynchronous receiver transmitter,意為通用同步異步收發(fā)器。顧名思義,該模塊可以同步或異步方式,實(shí)現(xiàn)數(shù)據(jù)的接收或發(fā)送。USART是一種常用的串行(數(shù)據(jù)按一定的格式按位排隊(duì)發(fā)送)通信接口,堪稱萬(wàn)能接口。主要功能和特點(diǎn)如下:
- 采用NRZ(none return zero)行業(yè)標(biāo)準(zhǔn)
- 支持全雙工異步通信
- 支持單線半雙工通信
- 支持IrDA串行紅外(SIR)編解碼器,常規(guī)模式支持3/16位長(zhǎng)度
- 支持LIN(local interconnection network),具備主同步斷開(kāi)發(fā)送能力和從斷開(kāi)檢測(cè)能力。當(dāng)USART硬件配置位LIN時(shí),可生成13位斷開(kāi)符和10/11為斷開(kāi)檢測(cè)符
- 具備智能卡模擬功能。支持ISO 7816-3標(biāo)準(zhǔn)定義的異步協(xié)議智能卡,支持0.5和1.5停止位。
- 通過(guò)DMA可配置多緩沖器通信。采用集中式DMA,可在SRAM中預(yù)留接收/發(fā)送緩沖字節(jié)
- 采用分?jǐn)?shù)波特率發(fā)生系統(tǒng),可編程傳輸和接收波特率高達(dá)460800(4.5M bits/s)
- 數(shù)據(jù)字長(zhǎng)可編程(8位或9位)
- 停止位可配置,支持1個(gè)或2個(gè)停止位
- 發(fā)射器為同步傳輸提供時(shí)鐘
- 接收器和發(fā)射器使能位獨(dú)立
- 支持以下傳輸檢查標(biāo)志:
- 接收緩沖器慢
- 發(fā)射緩沖器孔
- 傳輸結(jié)束標(biāo)志
- 校驗(yàn)控制:發(fā)送校驗(yàn)位;對(duì)接收到的數(shù)據(jù)字節(jié)進(jìn)行校驗(yàn)
- 支持4個(gè)錯(cuò)誤檢查標(biāo)志:溢出錯(cuò)誤;噪聲錯(cuò)誤;幀錯(cuò)誤;校驗(yàn)錯(cuò)誤
- 支持10個(gè)帶標(biāo)志中斷源:CTS改變;LIN斷開(kāi);傳輸數(shù)據(jù)寄存器空;傳輸完成;接收數(shù)據(jù)寄存器滿;傳輸線空閑檢測(cè);溢出錯(cuò)誤;噪聲錯(cuò)誤;幀錯(cuò)誤;校驗(yàn)錯(cuò)誤
- 支持多處理器通信 – 如果地址不匹配,進(jìn)入靜默模式
- 從靜默模式喚醒(通過(guò)空閑總線檢測(cè)或地址標(biāo)準(zhǔn)檢測(cè))
- 具備2種接收器喚醒模式:地址位(MSB第9位),總線空閑
STM32F103ZET6共有3個(gè)USART和2個(gè)UART,UART功能與USART類似,只是僅支持異步通信。同步通信和異步通信的本質(zhì)區(qū)別在于,通信時(shí)是否需要時(shí)鐘同步。平時(shí)常用的串口通訊基本都是UART。
6.2 USART工作原理
6.2.1 USART原理框圖
圖1. USART 框圖
圖1所示為USART的框圖。左下角是波特率發(fā)生器,通過(guò)配置BRR寄存器,設(shè)置波特率分頻系數(shù),對(duì)PCLKx進(jìn)行分頻,產(chǎn)生接收器時(shí)鐘,再經(jīng)16分頻,產(chǎn)生發(fā)送控制器時(shí)鐘。兩路時(shí)鐘分別送往接收控制器(Receiver control)和發(fā)送控制器(Transmit control)。兩個(gè)控制器匯總中部5個(gè)寄存器中的設(shè)置,將控制信號(hào)分別發(fā)往兩個(gè)移位寄存器和中斷控制器。
6.2.2 功能引腳
USART共有6個(gè)功能引腳,雙向通信時(shí)至少需要2個(gè)引腳(RX和TX)。各引腳功能簡(jiǎn)述如下:
- RX為接收數(shù)據(jù)輸入端。接收器通過(guò)過(guò)采樣技術(shù)來(lái)辨別數(shù)據(jù)和噪聲,從而恢復(fù)數(shù)據(jù)。
- TX為發(fā)送數(shù)據(jù)輸出端。當(dāng)發(fā)射器被禁用時(shí),此引腳恢復(fù)為IO端口。當(dāng)發(fā)射器被開(kāi)啟且無(wú)數(shù)據(jù)待發(fā)送時(shí),此引腳處于高電平。在單線和智能卡模式下,此IO同時(shí)擔(dān)負(fù)發(fā)送和接收任務(wù)。
- SW_RX為單線輸入引腳,這是一個(gè)內(nèi)部引腳,在單線半雙工模式下,RX和TX同時(shí)切換到SW_RX內(nèi)部引腳。
- nCTS為停止發(fā)送(Cease To Send)引腳。該引腳為高電平時(shí),當(dāng)前傳輸結(jié)束后會(huì)阻斷下一次數(shù)據(jù)傳輸。
- nRTS為請(qǐng)求發(fā)送(Request To Send)引腳。該引腳為低電平時(shí),指示USART已經(jīng)準(zhǔn)備接收數(shù)據(jù)。
- CK為發(fā)送器時(shí)鐘輸出(Transmitter ClocK output)引腳。該引腳將發(fā)射器時(shí)鐘輸出,用于實(shí)現(xiàn)同步傳輸。時(shí)鐘的相位和極性可以通過(guò)軟件控制。在智能卡模式下,CK可為智能卡提供時(shí)鐘。
6.2.3 USART數(shù)據(jù)格式
USART通信是一種串行通信,數(shù)據(jù)以幀(Frame)為單元,按位依次發(fā)送,低位優(yōu)先。USART通信過(guò)程中共涉及3種幀結(jié)構(gòu):
- 數(shù)據(jù)幀(Data frame) 包含數(shù)據(jù)的幀。每個(gè)數(shù)據(jù)幀發(fā)送1個(gè)字節(jié)的數(shù)據(jù)(8個(gè)比特),除了數(shù)據(jù)位,每個(gè)數(shù)據(jù)幀包括1個(gè)起始位(Start bit)、1個(gè)可選校驗(yàn)位(Parity bit)和0.5-2個(gè)停止位(Stop bit)。數(shù)據(jù)位和校驗(yàn)位的總長(zhǎng)度稱為字長(zhǎng)(Word length),所以根據(jù)有無(wú)校驗(yàn)位USART的可能字長(zhǎng)為9或8。 很顯然,起始位和停止位是為了區(qū)分相繼傳遞的兩個(gè)數(shù)據(jù)的。數(shù)據(jù)幀也稱為數(shù)據(jù)包。
- 空閑幀(Idle frame) 一個(gè)全為“1”的幀??臻e幀長(zhǎng)度包含停止位。在發(fā)送數(shù)據(jù)幀之前,USART的發(fā)送器會(huì)先發(fā)出一個(gè)空閑幀??臻e幀主要是用來(lái)同步的,如果接收端處于睡眠模式,收到空閑幀后會(huì)被喚醒,從空閑幀以后開(kāi)始解析數(shù)據(jù),這是USART通信協(xié)議的一部分??臻e幀發(fā)送出去的字符稱為空閑字符。
- 斷開(kāi)幀(Break frame) 一個(gè)全為“0”的幀。斷開(kāi)幀包含1或2個(gè)停止位,即斷開(kāi)幀是長(zhǎng)度為10或11位的低電平。斷開(kāi)幀之后發(fā)送器會(huì)插入1或2個(gè)停止位(“1”)來(lái)確認(rèn)下一幀的起始位。斷開(kāi)幀也是用于同步的,是USART通信協(xié)議的一部分。斷開(kāi)幀發(fā)送出去的字符稱為斷開(kāi)字符。
圖2所示為9位字長(zhǎng)和1位停止位的幀結(jié)構(gòu)和時(shí)序,8位字長(zhǎng)時(shí)不包括Bit8。時(shí)鐘信號(hào)來(lái)自波特率發(fā)生器,一個(gè)時(shí)鐘周期發(fā)送1個(gè)bit的數(shù)據(jù)。顯然,為了正確解析信息,收發(fā)雙方必須采用相同的波特率,波特率越高數(shù)據(jù)發(fā)送速度越快。
圖2. USART的幀結(jié)構(gòu)與時(shí)序
從圖中可以看出,起始位期間TX引腳為低電平,而停止位期間PX引腳為高電平。停止位后是下一幀的起始位,依此次序按幀將數(shù)據(jù)發(fā)送到TX引腳。
發(fā)送和接收受同一個(gè)波特率發(fā)生器驅(qū)動(dòng),通過(guò)將接收器或發(fā)送器的使能位置1,來(lái)產(chǎn)生各自的時(shí)鐘。異步通信并不是不需要同步,只是通過(guò)發(fā)送同步信號(hào)和約定波特率,收發(fā)雙方可以使用各自的本地時(shí)鐘,不需要一個(gè)共同的時(shí)鐘來(lái)進(jìn)行同步。
6.2.4 發(fā)送器 (Transmitter)
根據(jù)CR1寄存器中M位的設(shè)置,發(fā)送器可以發(fā)送8位或9位字長(zhǎng)的數(shù)據(jù)。發(fā)送使能位(CR1的TE位)被設(shè)置后,發(fā)送移位寄存器中的數(shù)據(jù)被依次輸出到TX引腳,相應(yīng)的時(shí)鐘脈沖被輸出到CK引腳。每個(gè)數(shù)據(jù)包包含一個(gè)字節(jié),低位優(yōu)先,每個(gè)字節(jié)前有一個(gè)起始位(長(zhǎng)度為1個(gè)位周期的低電平)來(lái)作為前導(dǎo),其后用一個(gè)停止位來(lái)結(jié)尾。
1. 發(fā)送端停止位的設(shè)置
停止位的長(zhǎng)度可以在CR2寄存器中(STOP[1:0])進(jìn)行配置,USART支持長(zhǎng)度為0.5,1,1.5和2個(gè)周期的停止位。整數(shù)對(duì)應(yīng)正常模式,小數(shù)對(duì)應(yīng)智能卡模式。詳情如下:
- 0.5 – 用于智能卡模式接收數(shù)據(jù)
- 1 – 默認(rèn)停止位位數(shù)
- 1.5 – 用于智能卡模式收發(fā)數(shù)據(jù)
- 2 – 常規(guī)USART、單線模式、調(diào)制解調(diào)器模式
2. 發(fā)送器的配置步驟
下面來(lái)看一下常規(guī)USART模式下,發(fā)送數(shù)據(jù)的基本過(guò)程:
- 向CR1寄存器的UE(USART enable)位寫(xiě)入1來(lái)使能USART;
- 設(shè)置CR1的M位來(lái)定義字長(zhǎng);
- 設(shè)置CR2的STOP[1:0]來(lái)配置停止位的個(gè)數(shù);
- 如果采用多緩沖器通信,設(shè)置CR3的DMAT使能DMA。按多緩沖器通信要求配置DMA寄存器;
- 設(shè)置BRR(Baud rate register)寄存器來(lái)選擇所需的波特率;
- 向CR1的TE位寫(xiě)入1,使能發(fā)送器并發(fā)送一個(gè)空閑幀作為第一幀;
- 將待發(fā)送數(shù)據(jù)依次寫(xiě)入DR寄存器(此操作會(huì)清除SR寄存器中的TXE位);
- 在向DR寄存器寫(xiě)入最后一個(gè)數(shù)據(jù)后,等待SR寄存器中的TC位(Transfer complete)被置1。在關(guān)閉USART或進(jìn)入宕機(jī)模式時(shí)都要進(jìn)行這種檢查,以避免破壞最后一次傳輸。
數(shù)據(jù)從總線傳入,依次經(jīng)TDR和移位寄存器被發(fā)送出去。當(dāng)向DR寄存器寫(xiě)入數(shù)據(jù)時(shí),如果有數(shù)據(jù)正在傳輸,數(shù)據(jù)會(huì)被寫(xiě)入TDR緩存,在當(dāng)前數(shù)據(jù)傳輸完畢,數(shù)據(jù)會(huì)被復(fù)制到移位寄存器。TDR與移位寄存器間數(shù)據(jù)是并行傳輸?shù)?。若?xiě)入數(shù)據(jù)時(shí)沒(méi)有數(shù)據(jù)正在傳輸,則數(shù)據(jù)將會(huì)被直接寫(xiě)入移位寄存器。數(shù)據(jù)的傳輸狀態(tài)可以通過(guò)查詢相關(guān)的寄存器來(lái)獲知。
3. 數(shù)據(jù)的發(fā)送
與發(fā)送過(guò)程密切相關(guān)的寄存器位有4個(gè):TXE(Transmit data register empty)、TC(Transmision complete)、TXEIE(TXT interrupt enable)、TCIE(TC interrupt enable)。
- SR寄存器中的TXE位為1時(shí),表明前一個(gè)數(shù)據(jù)已從TDR被移入移位寄存器并開(kāi)始發(fā)送了,TDR寄存器已空。因此,此時(shí)向TDR寫(xiě)入下一個(gè)數(shù)據(jù)已不會(huì)覆蓋前一個(gè)數(shù)據(jù)。
- 如果CR1寄存器中的TXEIE位開(kāi)啟,TXE被置1時(shí)會(huì)產(chǎn)生中斷。此中斷可以用來(lái)通知軟件,將下一個(gè)數(shù)據(jù)寫(xiě)入TDR。
- 在數(shù)據(jù)傳輸過(guò)程中,SR寄存器的TC位處于低電平。如果一幀數(shù)據(jù)傳輸完畢(stop bit之后)且TXE位為1,TC位變?yōu)楦唠娖?,如果CR1寄存器中的TCIE位開(kāi)啟,則會(huì)產(chǎn)生中斷。因?yàn)閿?shù)據(jù)從移位寄存器發(fā)送出去需要一定的時(shí)間,因此在將最后一個(gè)數(shù)據(jù)寫(xiě)入DR寄存器后,必須等待TC=1。在此之前不可以關(guān)閉USART或讓MCU進(jìn)入低功耗模式,否則會(huì)破壞最后一個(gè)數(shù)據(jù)。顯然,開(kāi)啟TCIE,在中斷回調(diào)函數(shù)中執(zhí)行后續(xù)這些操作,可以避免破壞數(shù)據(jù)。
圖3. 數(shù)據(jù)發(fā)送過(guò)程中相關(guān)寄存器的時(shí)序變化
圖3所示為數(shù)據(jù)發(fā)送過(guò)程中相關(guān)寄存器的時(shí)序變化:軟件使能USART時(shí),TXE為高電平,第一個(gè)數(shù)據(jù)被軟件寫(xiě)入DR寄存器,TEX被拉低;空閑幀發(fā)送完畢,stop bit下降沿觸發(fā)第一幀數(shù)據(jù)F1被移入移位寄存器;因DR為空,TXE被拉高,軟件檢測(cè)到TXE=1將第二幀F(xiàn)2迅速寫(xiě)入DR,TEX又被拉低;重復(fù)此過(guò)程直到最后一個(gè)數(shù)據(jù)包被寫(xiě)入DR;軟件開(kāi)始等待TC=1;最后一個(gè)數(shù)據(jù)包被移入移位寄存器后,TXE開(kāi)始持續(xù)為高電平;最后一幀發(fā)送完畢,在其stop bit下降沿因TXE=1,硬件將TC置1,傳輸過(guò)程結(jié)束。
從上述工作過(guò)程可以看出:
- 整個(gè)工作過(guò)程中,TXE和TC寄存器都是通過(guò)硬件置1,軟件置0的。軟件向DR寫(xiě)入數(shù)據(jù),TXE和TC即被置0。在stop bit下降沿,TDR中的數(shù)據(jù)被移走后,TXE被硬件置1。
- 硬件在stop bit的下降沿通過(guò)檢測(cè)TXE是否為1來(lái)判斷數(shù)據(jù)傳輸是否結(jié)束。由于從TDR移走數(shù)據(jù)需要一定的時(shí)間,如果不是最后一個(gè)數(shù)據(jù),TXE的置1有所滯后。stop bit下降沿TXE仍為0,所以TC保持低電平。而最后一個(gè)數(shù)據(jù)被移入移位寄存器后,TXE即持續(xù)為高電平,它被發(fā)送完畢后,在其stop bit下降沿會(huì)檢測(cè)到TXE=1,因此硬件會(huì)將TC置1。數(shù)據(jù)發(fā)送完畢。
- 數(shù)據(jù)發(fā)送結(jié)束后,TX、TXE、TC均為高電平。
- 軟件等待TC=1的時(shí)長(zhǎng)至少為2個(gè)數(shù)據(jù)包的發(fā)送周期,即從最后一個(gè)數(shù)據(jù)包寫(xiě)入TDR開(kāi)始,至TC=1結(jié)束。
空閑字符和斷開(kāi)字符的發(fā)送通過(guò)軟件設(shè)置寄存器來(lái)實(shí)現(xiàn)。向CR1寄存器的SBK位寫(xiě)入1,會(huì)在完成當(dāng)前傳輸后在TX發(fā)送一個(gè)斷開(kāi)字符。在斷開(kāi)字符的stop bit,硬件會(huì)將SBK位重置為0。USART會(huì)在最后一個(gè)斷開(kāi)字符的尾部添加一個(gè)邏輯1位,來(lái)確保對(duì)下一幀start bit的正確識(shí)別。空閑字符的發(fā)送通過(guò)設(shè)置CR1寄存器的TE位實(shí)現(xiàn),發(fā)送第一個(gè)數(shù)據(jù)幀之前需要發(fā)送給一個(gè)空閑幀,來(lái)實(shí)現(xiàn)接收器的喚醒或同步。
6.2.5 接收器(Receiver)
接收器接收的數(shù)據(jù)字長(zhǎng)可以為8位或9位,也是由CR1寄存器中M位進(jìn)行設(shè)置。異步通信模式下,收發(fā)雙方的波特率、字長(zhǎng)、停止位必須一致。
1. 接收器的配置步驟
接收器配置過(guò)程的前5步與發(fā)送器配置過(guò)程完全一致。
- 向CR1寄存器的UE(USART enable)位寫(xiě)入1來(lái)使能USART;
- 設(shè)置CR1的M位來(lái)定義字長(zhǎng);
- 設(shè)置CR2的STOP[1:0]來(lái)配置停止位的個(gè)數(shù);
- 如果采用多緩沖器通信,設(shè)置CR3的DMAT使能DMA。按多緩沖器通信要求配置DMA寄存器;
- 設(shè)置BRR(Baud rate register)寄存器來(lái)選擇所需的波特率;
- 向CR1寄存器的RE(Receiver enable)位寫(xiě)入1,使能接收器,使其開(kāi)始尋找起始位。
2. 起始位的檢測(cè)原理
如前所述,每個(gè)數(shù)據(jù)包是以起始位(低電平)開(kāi)始和停止位(高電平)結(jié)束的,識(shí)別起始位是正確接收和解析數(shù)據(jù)的前提。
圖4. 起始位檢測(cè)原理
起始位的檢測(cè)原理如圖4所示。USART接收器的采樣頻率是發(fā)送器波特率的16倍(參見(jiàn)圖1)。自前一個(gè)包(數(shù)據(jù)幀或空閑幀)下降沿,到下一個(gè)包起始位結(jié)束,共有16次采用。為了避免噪聲干擾,從接收到下降沿開(kāi)始,分別判斷此后第3、5、7和8、9、10次采用的值。如果兩組采樣全為0,則確認(rèn)找到起始位,并將SR寄存器中的RXNE(Receiver data register not empty)置1,如果開(kāi)啟了RXNEIE,則會(huì)產(chǎn)生相應(yīng)的中斷;如果兩組采樣中,有非0值,但每組的3個(gè)采樣值都至少有2個(gè)為0,仍判為有效起始位(RXNE置1,如果開(kāi)啟了中斷則觸發(fā)),但同時(shí)會(huì)將SR寄存器中的NE(Noise error)位置1,標(biāo)明檢測(cè)到噪聲;如果非前兩種情況,則停止檢測(cè),接收器恢復(fù)空閑狀態(tài),繼續(xù)等待下一個(gè)下降沿。
3. 數(shù)據(jù)的接收
如圖1所示,接收數(shù)據(jù)時(shí)數(shù)據(jù)先是存入接收移位寄存器(Receive Shift Register),然后再轉(zhuǎn)入接收數(shù)據(jù)寄存器(RDR,receive data register)的,低位優(yōu)先。移位寄存器與RDR間數(shù)據(jù)是并行傳輸?shù)?。與接收過(guò)程相關(guān)的關(guān)鍵寄存器位有2個(gè):RXNE和RXNEIE。
- SR寄存器中的RXNE位為1時(shí),表明移位寄存器的內(nèi)容已被轉(zhuǎn)移到RDR,可以被讀取了。
- 如果CR1寄存器中的RXNEIE位開(kāi)啟,RXNE被置1時(shí)會(huì)產(chǎn)生中斷。此中斷可以用來(lái)通知軟件,及時(shí)將RDR中的數(shù)據(jù)讀取。
- 在單緩存模式(非DMA)中,軟件讀取DR寄存器時(shí)會(huì)將RXNE位清0。在下一個(gè)字符接收完成之前(移位寄存器被填滿),RXNE必須被清0,否則會(huì)導(dǎo)致溢出錯(cuò)誤。多緩存模式下,DMA讀取DR寄存器也會(huì)將RXNE位清0。
- 數(shù)據(jù)位的值是根據(jù)第8,9,10三個(gè)采樣點(diǎn)的值來(lái)確定的。詳細(xì)情況見(jiàn)下面的噪聲錯(cuò)誤部分。
空閑字符會(huì)被當(dāng)作正常字符來(lái)接收,如果設(shè)置了IDLEIE中斷,接收到空閑字符時(shí)會(huì)觸發(fā)該中斷。斷開(kāi)字符則會(huì)被當(dāng)作幀錯(cuò)誤來(lái)處理。USART可以識(shí)別3種接收錯(cuò)誤并根據(jù)設(shè)置觸發(fā)相應(yīng)的中斷。
4. 噪聲錯(cuò)誤
為了區(qū)分有效的輸入數(shù)據(jù)和噪聲,異步USART接收器中采用了過(guò)采樣技術(shù)。RX線上的輸入電平會(huì)被以波特率的16倍進(jìn)行采樣。這樣1個(gè)數(shù)據(jù)位中會(huì)有16個(gè)采樣點(diǎn)。USART會(huì)用每個(gè)位中間的3次(第8,9,10次)采樣值確定數(shù)據(jù)位的電平并判斷數(shù)據(jù)是否有效。
圖5. 取樣數(shù)據(jù)的噪聲檢測(cè)
如前所述,在找到有效起始位時(shí)會(huì)設(shè)置RXNE為1,在RNXE的上升沿會(huì)同時(shí)會(huì)設(shè)置NE位。如圖5所示,如果NE為0,即起始位無(wú)噪聲時(shí),后續(xù)各位的取樣中只有中間3次取樣值全部相同才會(huì)被判定為有效數(shù)據(jù)。如果NE=1,接收到的位的值會(huì)根據(jù)中間3次取樣的值按照少數(shù)服從多少的原則確定,并判定為無(wú)效數(shù)據(jù)。無(wú)效數(shù)據(jù)也會(huì)被從移位寄存器轉(zhuǎn)入DR寄存器。在單緩沖器通訊情況下,噪聲錯(cuò)誤不會(huì)參數(shù)中斷,但由于NE和RXNE是被同時(shí)設(shè)置的,RXNE可以觸發(fā)中斷。如果需要檢查噪聲錯(cuò)誤,可以在該中斷中實(shí)現(xiàn)。在多緩沖器通信情況下,如果已經(jīng)設(shè)置了CR3寄存器中的EIE(Error interrupt enable)位,將產(chǎn)生一個(gè)錯(cuò)誤中斷。
通過(guò)讀取SR寄存器,接著讀取DR寄存器,可以復(fù)位NE標(biāo)志位。
5. 溢出錯(cuò)誤(Overrun error)
RDR每次收到數(shù)據(jù)硬件會(huì)將RXNE置1,數(shù)據(jù)被讀取后RXNE被復(fù)位為0。如果數(shù)據(jù)沒(méi)有被及時(shí)讀取(RXNE=1),移位寄存器被充滿后無(wú)法將數(shù)據(jù)轉(zhuǎn)移到RDR,就會(huì)觸發(fā)溢出錯(cuò)誤。錯(cuò)誤出現(xiàn)后:
- SR寄存器的ORE位會(huì)被置1;
- 如果開(kāi)啟了RXNEIE或同時(shí)開(kāi)啟了EIE和DMAR,會(huì)觸發(fā)中斷;
- 溢出錯(cuò)誤期間,RDR中的數(shù)據(jù)不會(huì)被破壞,但移位寄存器中收到的數(shù)據(jù)會(huì)因被重寫(xiě)而丟失;
通過(guò)讀取SR寄存器,接著讀取DR寄存器,可以復(fù)位ORE標(biāo)志位。
6. 幀錯(cuò)誤
由于同步出錯(cuò)或因噪聲太多,導(dǎo)致在預(yù)期的時(shí)間沒(méi)有識(shí)別到停止位,就會(huì)產(chǎn)生幀錯(cuò)誤。如前所述,當(dāng)接收到斷開(kāi)幀時(shí)也會(huì)當(dāng)作幀錯(cuò)誤來(lái)處理。當(dāng)檢測(cè)到幀錯(cuò)誤時(shí):硬件會(huì)將SR寄存器的FE(Frame error)位置1。后續(xù)處理與噪聲錯(cuò)誤類似,但字節(jié)通信時(shí)也可以在RXNE相關(guān)的中斷中進(jìn)行檢查。
通過(guò)讀取SR寄存器,接著讀取DR寄存器,可以復(fù)位FE標(biāo)志位。
7. 接收端對(duì)停止位的處理
接收端停止位設(shè)置與發(fā)送端相同,也是通過(guò)CR2寄存器中STOP[1:0]位來(lái)設(shè)置。但由于接收端是過(guò)采樣,要分情況處理:
- 0.5個(gè)停止位(智能卡接收) 因?yàn)樵?.5個(gè)停止位的位置(第8和第9次采樣中間)沒(méi)有采樣,導(dǎo)致這種情況下無(wú)法檢測(cè)幀錯(cuò)誤和斷開(kāi)幀。
- 1個(gè)停止位 用第8,9,10個(gè)采樣點(diǎn)的值來(lái)確定停止位。
- 1.5個(gè)停止位(智能卡收發(fā)) 前0.5個(gè)周期不采樣,對(duì)后一個(gè)時(shí)鐘周期的中間3個(gè)取樣點(diǎn)取樣。如果從停止位上升沿開(kāi)始計(jì)數(shù),對(duì)應(yīng)第16,17,18個(gè)采樣點(diǎn)。詳情查閱智能卡相關(guān)章節(jié)。
- 2個(gè)停止位 對(duì)第一個(gè)停止位的第8,9,10個(gè)采樣點(diǎn)采用。
6.2.6 分?jǐn)?shù)波特率的產(chǎn)生
1. 計(jì)算公式
USART的接收器和發(fā)送器的波特率是通過(guò)對(duì)外設(shè)總線的時(shí)鐘頻率分頻得到的,計(jì)算公式如下:
其中fCK為USART所在外設(shè)總線的時(shí)鐘頻率,USARTDIV為分頻系數(shù),由USART_BRR寄存器進(jìn)行設(shè)置。從上述公式可以看出,USART的最高波特率為外設(shè)總線APBx頻率的1/16,原因在于接收端要16倍過(guò)采樣來(lái)接收數(shù)據(jù),采樣頻率不可能高于APBx頻率。如圖1右下角所示,USART的接收器和發(fā)射器的波特率是通過(guò)同一個(gè)寄存器進(jìn)行配置的。為了支持分?jǐn)?shù)波特率,BRR寄存器的低16位被分成了兩部分:0-3位設(shè)置分?jǐn)?shù)部分,4-15位設(shè)置整數(shù)部分。二者共同定義分配因子USARTDIV。
根據(jù)BRR寄存器的設(shè)置,USARTDIV的計(jì)算規(guī)則如下:
- 4-15位轉(zhuǎn)為10進(jìn)制,作為整數(shù)部分。整數(shù)部分的取值范圍為0-4095;
- 0-3位轉(zhuǎn)為10進(jìn)制再除以16即為小數(shù)部分。之所以是16,是因?yàn)樾?shù)部分在寄存器中只占4位,所以能精確表示的小數(shù)只能是N/16,其中N的取值范圍為0-15。
反之,根據(jù)系統(tǒng)時(shí)鐘頻率和要求的波特率,BRR寄存器的整數(shù)和分?jǐn)?shù)部分分別按下列公式計(jì)算:
- UrtDIV = fCK/(16 baudrate)
- 整數(shù)部分:IntDIV = (u16)UrtDIV
- 分?jǐn)?shù)部分:FrcDIV = (u16)[(UrtDIV-IntDIV)*16+0.5]
例如:APB2總線頻率72MHz,要求波特率115200。計(jì)算結(jié)果:UrtDIV=39.0625,IntDIV=0d39(0x27),F(xiàn)rcDIV=0d01(0x01)。
受USARTDIV取值的限制,不是所有的波特率都可以精確的配置出來(lái)。波特率設(shè)置值與實(shí)際值之間有時(shí)會(huì)存在誤差。圖6所示即為常用波特率設(shè)置值與實(shí)際值之間的相對(duì)誤差情況。
圖6. 波特率誤差分析
對(duì)STM32F1系列芯片而言,APB1總線的最高頻率為36MHz,APB2總線的最高頻率為72MHz。除了USART1掛載在APB2總線上外,其余USART/UART均掛載與APB1總線。從圖1可以看出,常用的波特率設(shè)置115200,在36MHz情況下就會(huì)有0.15%的相對(duì)誤差。通常時(shí)鐘頻率越低,具體波特率的精度也會(huì)越低。USART1的最高波特率可達(dá)4.5M bps。
2. 接收器時(shí)鐘公差
異步通訊中,只有整個(gè)時(shí)鐘系統(tǒng)的誤差小于USART接收器容許的公差時(shí)數(shù)據(jù)才能被正確接收。誤差的主要來(lái)源包括:
- DTRA:發(fā)送端引入的誤差,例如發(fā)送端時(shí)鐘的漂移
- DQUANT:接收端波特率量化誤差
- DREC:接收端本地時(shí)鐘的漂移
- DTCL:傳輸線引入的漂移,通常來(lái)源于收發(fā)器高-低、低-高時(shí)序切換間的不同步
為保證數(shù)據(jù)能被正確接收,上述4種誤差總和必須小于USART接收器的公差。而公差又與三個(gè)因素有關(guān):字長(zhǎng),即CR1寄存器的M=0或1;分?jǐn)?shù)波特率,即BRR寄存器的低4位是否全為0;噪聲幀的處理,忽略還是當(dāng)作錯(cuò)誤。根據(jù)這三個(gè)因素的不同,公差表分別如圖7所示:
圖7. 接收器時(shí)鐘公差
6.2.7 靜默與喚醒
通過(guò)USART可以實(shí)現(xiàn)多處理器通信。為了減少USART的服務(wù)開(kāi)銷,可以讓空閑的USART進(jìn)入靜默模式(mute mode),在需要與某個(gè)USART進(jìn)行通信時(shí),可以將其定向喚醒,而其余空閑USART不受影響。即使是兩個(gè)USART之間的通信,在無(wú)數(shù)據(jù)傳輸時(shí)雙方也可以進(jìn)入靜默模式,有數(shù)據(jù)傳輸需求時(shí),提出需求的一方(軟件喚醒)通過(guò)發(fā)送喚醒信號(hào),激活對(duì)方。
USART的靜默與喚醒共涉及3個(gè)寄存器功能位:CR1寄存器的WAKE和RWU、CR2的ADD[3:0]。WAKE位設(shè)置喚醒方式,根據(jù)WAKE位的不同,使USART進(jìn)入或退出靜默模式有兩種方法:空閑總線檢測(cè)(WAKE=0)和地址標(biāo)記檢測(cè)(WAKE=1)。
1. 空閑總線檢測(cè)
圖8. 空閑總線檢測(cè)靜默-喚醒示意圖
空閑總線檢測(cè)靜默-喚醒示意圖如圖8所示。當(dāng)WAKE=0時(shí),通過(guò)向RWU(Receiver wakeup)位寫(xiě)入1可使USART進(jìn)入靜默模式。進(jìn)入靜默模式后,接收器停止接收數(shù)據(jù),但仍會(huì)檢測(cè)RX引腳上的輸入信號(hào),如果檢測(cè)到空閑幀,硬件會(huì)清除RWU,USART被喚醒開(kāi)始正常接收數(shù)據(jù)(RXNE位開(kāi)始變化)。
- 在靜默模式下收到的空閑幀不會(huì)觸發(fā)IDLEIE中斷,因?yàn)橛布粫?huì)設(shè)置SR寄存器中的IDLE位。
- 這種方式適合于同時(shí)需要喚醒多個(gè)USART的情形。只需發(fā)送一個(gè)空閑幀,所有WAKE=0且RWU=0的USART收到后都會(huì)被喚醒。
2. 地址標(biāo)記檢測(cè)
圖9. 地址標(biāo)記總線檢測(cè)靜默-喚醒示意圖
地址標(biāo)記檢測(cè)靜默-喚醒示意圖如圖9所示。這種模式下通常將字長(zhǎng)設(shè)置為9,最高位(MSB)用來(lái)作為數(shù)據(jù)和地址的標(biāo)識(shí)符。當(dāng)MSB=1時(shí),數(shù)據(jù)包被解析為地址;而當(dāng)MSB=0時(shí),則解析為數(shù)據(jù)。地址包的低4位存儲(chǔ)一個(gè)地址標(biāo)記,USART收到地址包后會(huì)與CR2寄存器的ADD[3:0]中的地址進(jìn)行比較。如果地址不匹配,硬件將RWU置1,進(jìn)入/保持靜默模式,RXNE不會(huì)被設(shè)置,也不會(huì)有中斷產(chǎn)生;如果地址匹配,硬件將RWU置0,喚醒USART,在地址包中Stop bit的下降硬件會(huì)設(shè)置RXNE,后續(xù)字符會(huì)被正常接收。
- 地址包也會(huì)被接收,喚醒后收到的第一個(gè)字符是地址。
- 這種模式需要提前配置每個(gè)USART的ADD[3:0],為其分配一個(gè)地址(不一定唯一)。
- 這種方式是一種以地址包為前導(dǎo)的定向通信,通信對(duì)象更明確。每次只喚醒地址匹配的USART,如果有多個(gè)同地址的會(huì)被同時(shí)喚醒。
6.2.8 數(shù)據(jù)校驗(yàn)
奇偶校驗(yàn)是一種校驗(yàn)代碼傳輸正確性的方法。根據(jù)被傳輸?shù)囊唤M二進(jìn)制代碼中“1”的個(gè)數(shù)是奇數(shù)還是偶數(shù)來(lái)進(jìn)行校驗(yàn)。采用奇數(shù)的稱為奇校驗(yàn),反之,稱為偶校驗(yàn)。校驗(yàn)方式是通信雙方提前約定好的。通過(guò)在數(shù)據(jù)包中的校驗(yàn)位來(lái)進(jìn)行校驗(yàn)。發(fā)送方根據(jù)數(shù)據(jù)設(shè)置校驗(yàn)位,接收方接收數(shù)據(jù)后對(duì)校驗(yàn)位進(jìn)行檢查,從而確定傳輸代碼的正確性。
通過(guò)將CR1寄存器的PCE(Parity control enable)位置1來(lái)使能奇偶校驗(yàn),校驗(yàn)方式通過(guò)PS(Parity selection)位來(lái)設(shè)置:PS=0,偶校驗(yàn);PS=1,奇校驗(yàn)。
需要說(shuō)明的是,如果開(kāi)啟了奇偶校驗(yàn),USART的字長(zhǎng)包含1個(gè)校驗(yàn)位;如果同時(shí)開(kāi)啟了地址標(biāo)記喚醒,數(shù)據(jù)位的最高位會(huì)被用作地址標(biāo)記,這種情況下實(shí)際數(shù)據(jù)的位數(shù)比所設(shè)字長(zhǎng)會(huì)少2位。注意合理設(shè)置,防止數(shù)據(jù)被修改或誤用(比如數(shù)據(jù)包被解析為地址包)。
舉例來(lái)說(shuō):如果設(shè)置字長(zhǎng)9位,停止位1位,同時(shí)開(kāi)啟奇偶校驗(yàn)和地址標(biāo)記喚醒,則最高位被校驗(yàn)位占據(jù),剩余數(shù)據(jù)為的最高位會(huì)被當(dāng)作地址標(biāo)記位。實(shí)際數(shù)據(jù)占7位,設(shè)為1011011,如果選擇偶校驗(yàn),則校驗(yàn)位為0。整個(gè)數(shù)據(jù)包的內(nèi)容為:10010110110,從左到右依次為停止位1、奇偶校驗(yàn)位0、地址標(biāo)記0(這是數(shù)據(jù)幀)、數(shù)據(jù)位1011011、起始位0(數(shù)據(jù)傳輸?shù)臀粌?yōu)先)。
接收器收到數(shù)據(jù)后,會(huì)檢查數(shù)據(jù)位中“1”的個(gè)數(shù)是奇數(shù)還是偶數(shù),并按校驗(yàn)規(guī)則與校驗(yàn)位核對(duì)。如果不符表明傳輸出錯(cuò)(比如噪聲干擾等),SR寄存器中的PE(Parity error)位會(huì)被置1,如果CR1中的PEIE(Parity error interrupt enable)開(kāi)啟,則會(huì)產(chǎn)生中斷。
6.2.9 USART同步模式
USART可以以同步模式工作。向CR2寄存器的CLKEN(Clock enable)寫(xiě)入1即可開(kāi)啟同步模式。同步模式下,數(shù)據(jù)在TX引腳輸出的同時(shí),發(fā)送器時(shí)鐘從CK引腳輸出,但在數(shù)據(jù)包的起始位和停止位CK引腳上無(wú)時(shí)鐘脈沖。
- 通過(guò)配置CR2寄存器的LBCL位,可以設(shè)置最后一個(gè)有效數(shù)據(jù)位(地址標(biāo)記)是否輸出時(shí)鐘脈沖;
- 通過(guò)CR2寄存器的CPOL(Clock polarity)可以設(shè)置時(shí)鐘的極性,即在傳輸窗口外CK引腳的電平是高(CPOL=1)還是低(CPOL=0);
- 通過(guò)CR2的CPHA位可以設(shè)置時(shí)鐘的相位,即在時(shí)鐘的第一個(gè)邊緣進(jìn)行數(shù)據(jù)捕獲(CPHA=0),還是在時(shí)鐘的第二個(gè)邊沿進(jìn)行數(shù)據(jù)捕獲(CPHA=1)。CPOL和CPHA一起配合來(lái)產(chǎn)生需要的時(shí)鐘/數(shù)據(jù)采樣關(guān)系。
發(fā)射器的運(yùn)作在同步模式下和異步模式下完全相同。只是TX引腳上的數(shù)據(jù)是與CK引腳上的時(shí)鐘同步發(fā)出的。
接收器的運(yùn)作在同步模式下與異步模式下不同。由于有同步時(shí)鐘,因此不需要不需要進(jìn)行過(guò)采樣。而是在RE=1使能接收器后,數(shù)據(jù)在CK的上升沿或下降沿被直接采樣。但必須重視建立時(shí)間(setup time)和保持時(shí)間(hold time)。
- 建立時(shí)間是指,采樣時(shí)鐘邊沿到來(lái)之前,數(shù)據(jù)提前保持不變的時(shí)間;保持時(shí)間是指,采樣時(shí)鐘邊沿到來(lái)之后,數(shù)據(jù)必須繼續(xù)保持不變的時(shí)間。這兩個(gè)時(shí)間與波特率有關(guān),通常要求這兩個(gè)時(shí)間不低于1/16個(gè)bit的時(shí)長(zhǎng)。
- USART只支持主模式,即只能由它來(lái)輸出時(shí)鐘同步其他設(shè)備,而不能反過(guò)來(lái)。CK引腳永遠(yuǎn)都是輸出端。
- 同步模式下CR2寄存器的LINEN位、CR3寄存器的SCEN,HDSEL和IREN位必須清零。相關(guān)寄存器位(包括LBCL、CPOL、CPHA)的設(shè)置都必須在TE和RE使能前完成,發(fā)送器和接收器使能后不能再修改這些位,否則可能會(huì)導(dǎo)致時(shí)鐘工作不正常。
- CK和TX引腳一起運(yùn)作,因此只有TE=1且數(shù)據(jù)已開(kāi)始傳輸時(shí)才能提供時(shí)鐘。在發(fā)送數(shù)據(jù)前是無(wú)法向異步模式中那樣,提前發(fā)送一個(gè)數(shù)據(jù)進(jìn)行同步的。
圖10所示是USART同步通信的時(shí)序示意圖。圖示是M=1,即9位字長(zhǎng)的情況,8位字長(zhǎng)與此類似。
圖10. USART同步通信時(shí)序圖
從圖10可以看出,CPOL=0時(shí),閑時(shí)電平為低電平,而CPOL=1時(shí),閑時(shí)電平為高電平;CPHA=0時(shí),第一個(gè)時(shí)鐘沿采樣,而CPHA=1時(shí),第二個(gè)時(shí)鐘沿采樣。LBCL(Last bit clock)控制的是最后一個(gè)數(shù)據(jù)是否產(chǎn)生輸出時(shí)鐘脈沖。
6.2.10 單線半雙工通信
單線通信的最大好處是只占一根線,通過(guò)分時(shí)收發(fā)(半雙工)來(lái)實(shí)現(xiàn)通信。通過(guò)將CR3寄存器的HDSEL(half-duplex selection)位置1來(lái)選擇半雙工模式。在此模式下,CR2寄存器的LINKEN位、CLKEN位,CR3寄存器的SCEN和IREN位必須清零。
單線半雙工模式下,TX和RX引腳在芯片內(nèi)部被連通。HDSEL被寫(xiě)入1后,RX引腳被停用;在無(wú)數(shù)據(jù)發(fā)送時(shí),TX引腳被釋放。TX引腳在空閑或接收數(shù)據(jù)時(shí)跟一個(gè)標(biāo)準(zhǔn)的I/O口一樣。所以在不被USART驅(qū)動(dòng)時(shí),TX引腳必須配置位浮空輸入(或輸出高開(kāi)漏)。除此以外,通信與正常USART模式相似。由于只有一條線路,要由軟件來(lái)負(fù)責(zé)避免出現(xiàn)線上沖突。特別需要說(shuō)明的是,發(fā)送永遠(yuǎn)不會(huì)被硬件阻斷,當(dāng)TE=1時(shí),只要有數(shù)據(jù)被寫(xiě)到DR寄存器,就會(huì)被發(fā)送出去。
6.2.11 硬件流控制
圖11. 硬件流控制工作原理
所謂硬件流控制,是指通過(guò)硬件發(fā)送控制信號(hào)來(lái)控制數(shù)據(jù)流的一種方式,相當(dāng)于一種握手協(xié)議。主要是為了避免因雙方處理速度不匹配或USART網(wǎng)絡(luò)中多個(gè)發(fā)送器同時(shí)向一個(gè)接收器發(fā)送數(shù)據(jù)導(dǎo)致接收端溢出錯(cuò)誤和數(shù)據(jù)丟失。硬件流控制的基本原理圖如圖11所示,在兩個(gè)USART間增加了兩條控制信號(hào)線,一個(gè)USART的nRTS連到另一個(gè)的nCTS(n表示低電平有效)。當(dāng)接收端數(shù)據(jù)處理即將完畢時(shí),通過(guò)nRTS端口向發(fā)送端發(fā)送RTS(Request to send)請(qǐng)求發(fā)送信號(hào)。而發(fā)送端的nCTS端口收到信號(hào)后,將其解讀為CTS(Clear to send)允許發(fā)送信號(hào),進(jìn)而允許發(fā)送器繼續(xù)發(fā)送數(shù)據(jù)。
RTS和CTS可以通過(guò)向CR3寄存器的RTSE(RTS enable)和CTSE(CTS enable)位寫(xiě)入1來(lái)獨(dú)立開(kāi)啟。
圖12. RTS流控過(guò)程
圖12所示為RTS流控過(guò)程示意圖。如前所述,接收器接收數(shù)據(jù)時(shí),數(shù)據(jù)先通過(guò)移位寄存器接收,當(dāng)接收到Stop bit后,數(shù)據(jù)會(huì)被存入緩存RDR,RXNE=1。如果使能了RTS,在RXNE=1期間,接收器停止接收數(shù)據(jù),nRTS輸出高電平1,向發(fā)送器發(fā)出停止發(fā)送請(qǐng)求,發(fā)送器應(yīng)當(dāng)在當(dāng)前幀發(fā)送結(jié)束后會(huì)暫停發(fā)送,直至收到新的發(fā)送請(qǐng)求。
數(shù)據(jù)被從RDR讀取后,RXNE=0。如果使能了RTS,nRTS輸出低電平0,向發(fā)送器發(fā)出新的發(fā)送請(qǐng)求。如果數(shù)據(jù)傳輸通暢,RXNE=1的時(shí)間很短,數(shù)據(jù)幾乎是連續(xù)發(fā)送。如果發(fā)生特殊情況耽誤了RDR中數(shù)據(jù)的讀?。ū热绨l(fā)生中斷),nRTS=1,停止發(fā)送,防止丟失數(shù)據(jù)。
圖13. CTS流控過(guò)程 圖13. CTS流控過(guò)程
圖13所示為CTS流控過(guò)程示意圖。使能CTS后,發(fā)送器在發(fā)送下一幀前會(huì)檢查nCTS輸入端口的電平。如果nCTS有效(低電平)且TXE=0(TDR非空),則下一幀被發(fā)送;反之,則不會(huì)進(jìn)行發(fā)送。如果nCTS在數(shù)據(jù)發(fā)送期間失效(變?yōu)榱烁唠娖剑?,?dāng)前幀傳輸完成后會(huì)停止發(fā)送。如圖13中所示,Data2發(fā)送期間CTS失效,Data3雖已被移入TDR,但Data2發(fā)送后會(huì)停止發(fā)送,等待CTS=0再開(kāi)始發(fā)送Data3。從圖13還可以看到,在Stop bit后,Data2被移入移位寄存器,TDR中有個(gè)短暫的empty期,即TXE=0的間隙。
使能CTS后,只要nCTS電平發(fā)生躍變,硬件就會(huì)自動(dòng)將SR寄存器中的CTS狀態(tài)位置1。如果設(shè)置了CR3寄存器的CTSIE位,則會(huì)產(chǎn)生中斷。
6.3 USART模式配置與中斷
6.3.1 模式配置
STM32F103ZET6共有3個(gè)USART和2個(gè)UART。3個(gè)USART支持所有的模式,但2個(gè)UART只支持部分模式,而且兩個(gè)UART支持的模式也存在差別。具體配置如圖14所示。
圖14. USART模式配置
6.3.2 事件與中斷
圖15. USART相關(guān)中斷
圖15所示為USART相關(guān)中斷事件和標(biāo)志位。共有11個(gè)中斷標(biāo)志和8個(gè)相關(guān)中斷,其中前3個(gè)為發(fā)送器相關(guān)中斷,其余為接收器相關(guān)中斷。通過(guò)設(shè)置相關(guān)的控制位使能中斷。USART的所有中斷都連接到同一個(gè)中斷向量。
6.4 USART寄存器
STM32F103ZET6中與USART相關(guān)的寄存器共有7個(gè),地址映射與復(fù)位值表如圖16所示。可以看出,這些寄存器雖然都是32bit寄存器,但功能位沒(méi)有超過(guò)16bit的。所以這些寄存器允許按半字或全字訪問(wèn)。
圖16. 寄存器地址映射與復(fù)位值
6.4.1 USART_SR 狀態(tài)寄存器
USART_SR為狀態(tài)寄存器(Status Register),用以管理USART相關(guān)的狀態(tài)標(biāo)志。
位置 | 名稱 | 功能說(shuō)明 |
9 | CTS | CTS flag nCTS引腳輸入電平跳變(上升/下降)時(shí),硬件將此位置1。軟件寫(xiě)入0清除。若CR3寄存器中的CTSIE=1,會(huì)觸發(fā)中斷。USART4&5無(wú)此功能。 |
8 | LBD | LIN break detection flag LIN模式下檢測(cè)到斷開(kāi)幀時(shí),硬件將此位置1。軟件寫(xiě)入0清除。若CR2寄存器中的LBDIE=1,會(huì)觸發(fā)中斷。 |
7 | TXE | TDR empty TDR寄存器中的數(shù)據(jù)被移入移位寄存器后,硬件將此位置1。向TDR寫(xiě)入數(shù)據(jù)會(huì)清0。若CR1寄存器中的TXEIE=1,會(huì)觸發(fā)中斷。 TXE=1,說(shuō)明TDR已空,數(shù)據(jù)已轉(zhuǎn)讓發(fā)送移位寄存器,可緩存下一個(gè)待發(fā)送數(shù)據(jù)了。 注意:此位在單緩存發(fā)生時(shí)可用。不適用于DMA。 |
6 | TC | Transmission complete 數(shù)據(jù)幀傳輸完畢且TXE=1時(shí),硬件將此位置1。軟件序列清零。也可以直接向TC寫(xiě)入0來(lái)清除(僅DMA模式推薦)。若CR1寄存器中的TCIE=1,會(huì)觸發(fā)中斷。 |
5 | RXNE | RDR not empty 當(dāng)發(fā)送移位寄存器中的數(shù)據(jù)被轉(zhuǎn)入RDR時(shí),硬件將此位置1。讀取RDR或向此位寫(xiě)入0可清除(只寫(xiě)法僅DMA模式推薦)。若CR1寄存器中的RXNEIE=1,會(huì)觸發(fā)中斷。 RXNE=1,說(shuō)明RDR非空,接收移位寄存器中的數(shù)據(jù)被移出,可接收下一個(gè)數(shù)據(jù)了。 |
4 | IDLE | IDLE line detected 當(dāng)檢測(cè)到空閑幀時(shí),硬件將此位置1。軟件序列清零。若CR1寄存器中的IDLEIE=1,會(huì)觸發(fā)中斷。 |
3 | ORE | Overrun error 接收移位寄存器已滿但RXNE=1(RDR非空)時(shí),硬件將此位置1。軟件序列清零:先讀USART_SR,接著寫(xiě)入U(xiǎn)SART_DR。若CR1寄存器中的RXNEIE=1,會(huì)觸發(fā)中斷。 注意:RDR中的內(nèi)容無(wú)恙,但移位寄存器中的數(shù)據(jù)被覆蓋。多緩存通信時(shí)若EIE=1,會(huì)觸發(fā)中斷。 |
2 | NE | Noise error 接收到的幀中檢測(cè)到噪聲時(shí),硬件將此位置1。軟件序列清除。 注意:NE不會(huì)產(chǎn)生中斷,因?yàn)樗cRXNE同時(shí)出現(xiàn),RXNE自己會(huì)產(chǎn)生中斷。多緩存通信時(shí)若EIE=1,NE發(fā)生會(huì)觸發(fā)中斷。 |
1 | FE | Framing error 當(dāng)檢測(cè)到同步錯(cuò)誤、噪聲過(guò)多或端口字符時(shí),硬件將此位置1。軟件序列清除。 注意:FE不會(huì)產(chǎn)生中斷,因?yàn)樗cRXNE同時(shí)出現(xiàn),RXNE自己會(huì)產(chǎn)生中斷。若FE和ORE同時(shí)發(fā)生,引發(fā)錯(cuò)誤的幀仍會(huì)被傳輸,只有ORE位被設(shè)置。多緩存通信時(shí)若EIE=1,F(xiàn)E發(fā)生會(huì)觸發(fā)中斷。 |
0 | PE | Parity error 當(dāng)接收端出現(xiàn)奇偶校驗(yàn)錯(cuò)誤時(shí),硬件將此位置1。軟件序列清除。清零前必須等待RXNE被置1(有新數(shù)據(jù)緩存如RDR)。若CR1寄存器中的PEIE=1,會(huì)觸發(fā)中斷。 |
注:軟件序列清零是指,軟件先讀USART_SR,接著寫(xiě)入U(xiǎn)SART_DR。
6.4.2 USART_DR 數(shù)據(jù)寄存器
USART_DR為數(shù)據(jù)寄存器(Data Register),用以容納接收或發(fā)送的數(shù)據(jù)。該寄存器由兩個(gè)寄存器構(gòu)成:TDR和RDR。二者均為9位,共用地址(軟件讀取時(shí)用RDR、寫(xiě)入時(shí)用TDR),與配套的寄存器間并行通信。若開(kāi)啟了奇偶校驗(yàn),MSB位會(huì)被校驗(yàn)位取代。
6.4.3 USART_BRR 波特率寄存器
USART_BRR為波特率寄存器(Baud Rate Register),用以配置分?jǐn)?shù)波特率發(fā)生器的分頻系數(shù)USARTDIV。該寄存器共占用16位,分為兩個(gè)功能區(qū):
DIV_Mantissa[15:4]:配置USARTDIV整數(shù)部分;
DIV_Fraction[3:0]:配置USARTDIV分?jǐn)?shù)部分。
6.4.4 USART_CR1 控制寄存器1
USART_CR1為控制寄存器(Control Register)。USART共有3個(gè)控制寄存器,CR1主要用來(lái)設(shè)置收/發(fā)過(guò)程相關(guān)的參數(shù),包括字長(zhǎng)、校驗(yàn)位設(shè)置、喚醒方式、收/發(fā)器使能、靜默模式、及收/發(fā)過(guò)程相關(guān)的5個(gè)中斷。
位置 | 名稱 | 功能說(shuō)明 |
13 | UE | USART enable 0: USART分頻器和輸出關(guān)閉; 1: USART開(kāi)啟 。 |
12 | M | Word length 0: 停止位1,數(shù)據(jù)位 8,,停止位n (n=0.5,1,1.5,2) 1: 停止位1,數(shù)據(jù)位 9,停止位n 注意:傳輸過(guò)程中不要修改 |
11 | WAKE | Wakeup method 0: 空閑幀喚醒; 1: 地址標(biāo)記喚醒 |
10 | PCE | Parity control enable 0: 關(guān)閉奇偶校驗(yàn); 1: 開(kāi)啟奇偶校驗(yàn) |
9 | PS | Parity selection 0: 偶校驗(yàn); 1: 奇校驗(yàn) |
8 | PEIE | PE interrupt enable 0: 禁用PE(奇偶校驗(yàn)錯(cuò)誤)中斷; 1: 開(kāi)啟PE中斷 |
7 | TXEIR | TXE interrupt enable 0: 禁用TXE(TDR空)中斷; 1: 開(kāi)啟TXE中斷 |
6 | TCIE | TC interrupt enable 0: 禁用TC(傳輸完成)斷; 1: 開(kāi)啟TC中斷 |
5 | RXNEIE | RXNE interrupt enable 0: 禁用RXNE(RDR非空)中斷 1: 開(kāi)啟RXNE中斷 |
4 | IDLEIE | IDLE interrupt enable 0: 禁用IDLE(空閑幀)中斷 1: 開(kāi)啟IDLEL中斷 |
3 | TE | Transmitter enable 0: 關(guān)閉發(fā)送器;1: 使能發(fā)送器 注意:除了智能卡模式,若在傳輸過(guò)程中TE位上有0脈沖,會(huì)在當(dāng)前幀傳輸結(jié)束發(fā)送一個(gè)前導(dǎo)符(空閑幀);TE設(shè)1后要延遲1個(gè)bit才開(kāi)始傳輸。 |
2 | RE | Receiver enable 0: 關(guān)閉接收器;1: 使能接收器,并開(kāi)始查找起始位 |
1 | RWU | Receiver wakeup 0: 退出靜默模式;1: 進(jìn)入靜默模式 |
0 | SBK | Send break 該位寫(xiě)入1會(huì)發(fā)生一個(gè)斷開(kāi)符。 |
6.4.5 USART_CR2 控制寄存器2
CR2主要用來(lái)設(shè)置CK引腳的同步時(shí)鐘、LIN模式、停止位以及USART地址。
位置 | 名稱 | 功能說(shuō)明 |
14 | LINEN | LIN mode enable 0: 關(guān)閉LIN模式; 1: 開(kāi)啟LIN模式 |
13:12 | STOP | STOP bits 00: 1; 01: 0.5; 10: 2; 11: 1.5; UART4 & 5 不支持0.5和1.5個(gè)停止位 |
11 | CLKEN | Clock enable 0: 停止CK時(shí)鐘輸出; 1: 使能CK時(shí)鐘輸出 |
10 | CPOL | Clock pority 0: 閑時(shí)低電平; 1: 閑時(shí)高電平 UART4 & 5 不支持 |
9 | CPHA | Clock phase 0: 第1個(gè)始終沿捕獲數(shù)據(jù); 1:第2個(gè)時(shí)鐘沿捕獲數(shù)據(jù) UART4 & 5 不支持 |
8 | LBCL | Last bit clock pulse 0: Last bit不輸出時(shí)鐘脈沖; 1:輸出 UART4 & 5 不支持 |
6 | LBDIE | LIN break detection interrupt enable 0: 禁止LIN斷開(kāi)幀中的; 1: 開(kāi)啟 |
5 | LBDL | LIN break detection length 0: 10bit斷開(kāi)符檢測(cè); 1:11位斷開(kāi)符檢測(cè) |
3:0 | ADD | USART address 為USART分配地址。此位在多處理器通信時(shí)用于通過(guò)地址標(biāo)記定向喚醒。 |
注意:CPOL,CPHA,LBCL在傳輸過(guò)程中禁止修改。
6.4.6 USART_CR3 控制寄存器3
CR3主要用來(lái)設(shè)置硬件流控制、DMA收發(fā)、智能卡和IrDA模式,以及FE/ORE/NE錯(cuò)誤中斷。
位置 | 名稱 | 功能說(shuō)明 |
10 | CTSIE | CTS interrupt enable 1: 使能CTS中斷; UART4 & 5 不支持 |
9 | CTSE | CTS enable 1: 使能CTS硬件流控制; UART4 & 5 不支持 |
8 | RTSE | RTS enable 1: 使能RTS硬件流控制; UART4 & 5 不支持 |
7 | DMAT | DMA enable transmitter 1: 使能DMA模式發(fā)送; UART4 & 5 不支持 |
6 | DMAR | DMA enable receiver 1: 使能DMA模式接收; UART4 & 5 不支持 |
5 | SCEN | Smartcard mode enable 1: 使能智能卡模式; UART4 & 5 不支持 |
4 | NACK | Smartcard NACK enable 1: 出現(xiàn)奇偶校驗(yàn)錯(cuò)誤時(shí)使能NACK; UART4 & 5 不支持 |
3 | HDSEL | Half-duplex selection 1: 選擇半雙工模式 |
2 | IRLP | IrDA low-power 0: 正常模式;1: 低功耗模式 |
1 | IREN | IrDA mode enable 1: 使能IrDA紅外模式 |
0 | EIE | Error interrupt enable 1: 多緩沖區(qū)模式下,使能FE、ORE、NE中斷 |
6.4.7 USART_GTPR保護(hù)時(shí)間和預(yù)分頻寄存器
USART_GTPR為保護(hù)時(shí)間和預(yù)分頻寄存器(Guard Time and Prescaler Register)。該寄存器共占16位,分為兩個(gè)功能區(qū):
GT[15:8]:用于設(shè)置智能卡模式下的保護(hù)時(shí)間,單位為波特率時(shí)鐘個(gè)數(shù),保護(hù)時(shí)間過(guò)后才會(huì)設(shè)置TC標(biāo)志位。
PSC[7:0]:用于設(shè)置智能卡和IrDA低功耗模式下的波特率預(yù)分頻系數(shù)。IrDA低功耗模式下,
6.5 USART功能設(shè)置
初始化USART的基本步驟如下:
6.5.1 寄存器操作
為了便于寄存器操作,頭文件stm32f10x.h中定義了與USART寄存器相關(guān)的宏,對(duì)地址進(jìn)行了映射。以USART1為例,相關(guān)宏定義和地址映射如下:
#define PERIPH_BASE ((uint32_t)0x40000000)#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)#define ADC3_BASE (APB2PERIPH_BASE + 0x3C00)#define USART1 (USART_TypeDef *) USART1_BASE)typedef struct{ __IO uint16_t SR; uint16_t RESERVED0; __IO uint16_t DR; uint16_t RESERVED1; __IO uint16_t BRR; uint16_t RESERVED2; __IO uint16_t CR1; uint16_t RESERVED3; __IO uint16_t CR2; uint16_t RESERVED4; __IO uint16_t CR3; uint16_t RESERVED5; __IO uint16_t GTPR; uint16_t RESERVED6;} USART_TypeDef;
通過(guò)上述宏名稱,可以對(duì)USART相關(guān)寄存器中的功能位進(jìn)行設(shè)置。
//波特率115200,數(shù)據(jù)位8,停止位1,RX+TX,無(wú)奇偶校驗(yàn),無(wú)硬件流控usart1_int(void){uint32_t temp/* 1 使能時(shí)鐘 */RCC->APB2EN |= 0x00004004;//使能GPIOA和USART1的時(shí)鐘/* 2 配置引腳 */temp = GPIOA->CRH;temp &= 0xFFFFF00F; //resettemp |= 0x000004B0; //PA9:50MHz,復(fù)用推挽;PA10:浮空輸入GPIOA->CRH = temp;/* 3 配置USART參數(shù) */USART1->BRR = 0x2701; //72MHz,115200 =>39.0625temp = USART1->CR1;temp &= 0xFFFFE9F3;//Clear M/PCE/PS/TE/REtemp |= 0x000C;//數(shù)據(jù)位8、無(wú)奇偶校驗(yàn)、收發(fā)均開(kāi)啟USART1->CR1 = temp;USART1->CR2 &= 0xFFFFCFFF;//停止位1USART1->CR2 &= 0xFFFFCFFF;//硬件流控制nCTS,nRTS均不開(kāi)啟/* 4 配置USART中斷 */ 待補(bǔ)充2021.9.7/* 5 使能USART */USART1->CR1 |= 0x01<<13; }
6.5.2 標(biāo)準(zhǔn)庫(kù)相關(guān)函數(shù)
標(biāo)準(zhǔn)庫(kù)中USART相關(guān)的庫(kù)函數(shù)共29個(gè),在stm32f10x_usart.h中聲明,stm32f10x_usart.c中定義。按函數(shù)功能大體分類,簡(jiǎn)述如下:
1. 初始化函數(shù)
- USART_DeInit(); 復(fù)位USART外設(shè)總線時(shí)鐘。該函數(shù)實(shí)際訪問(wèn)的是RCC_APBxRSTR寄存器,先ENABLE接著DISABLE(為何要多此一舉?)。
- USART_StructInit(); USART_Init( ); 這個(gè)兩個(gè)函數(shù)用來(lái)初始化USART參數(shù)??梢韵扔肬SART_StructInit()用默認(rèn)參數(shù)初始化一個(gè)USART_InitTypeDef結(jié)構(gòu)體。默認(rèn)參數(shù)為:波特率9600,字長(zhǎng)8bit,停止位1,奇偶校驗(yàn)none,模式RX+TX,硬件流控None。執(zhí)行此函數(shù)后,修改必要參數(shù),再調(diào)用USART_Init()完成初始化。不用USART_StructInit(),需要逐字段輸入。
typedef struct{ uint32_t USART_BaudRate; uint16_t USART_WordLength; uint16_t USART_StopBits; uint16_t USART_Parity; uint16_t USART_Mode; uint16_t USART_HardwareFlowControl;} USART_InitTypeDef;USART_StructInit(){ /* USART_InitStruct members default value */ USART_InitStruct->USART_BaudRate = 9600; USART_InitStruct->USART_WordLength = USART_WordLength_8b; USART_InitStruct->USART_StopBits = USART_StopBits_1; USART_InitStruct->USART_Parity = USART_Parity_No ; USART_InitStruct->USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStruct->USART_HardwareFlowControl = USART_HardwareFlowControl_None; }
USART_Init()中設(shè)置的是CR1-3和BRR寄存器。波特率設(shè)置時(shí),總線時(shí)鐘是根據(jù)時(shí)鐘系統(tǒng)設(shè)置進(jìn)行計(jì)算,進(jìn)而計(jì)算和設(shè)置BRR的整數(shù)和分?jǐn)?shù)功能區(qū)的值。
- USART_ClockStructInit(); USART_ClockInit(); 與前述兩個(gè)函數(shù)類似。這兩個(gè)函數(shù)用來(lái)初始化CK引腳的時(shí)鐘??上日{(diào)用USART_ClockStructInit(),生成一個(gè)用默認(rèn)參數(shù)初始化的USART_ClockInitTypeDef結(jié)構(gòu)體,進(jìn)行必要修改后傳個(gè)USART_ClockInit()完成初始化。默認(rèn)參數(shù)為:CK時(shí)鐘關(guān)閉,極性low,相位第1邊沿,最后bit無(wú)時(shí)鐘脈沖。
typedef struct{ uint16_t USART_Clock; uint16_t USART_CPOL; uint16_t USART_CPHA; uint16_t USART_LastBit;} USART_ClockInitTypeDef;USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct){ /* USART_ClockInitStruct members default value */ USART_ClockInitStruct->USART_Clock = USART_Clock_Disable; USART_ClockInitStruct->USART_CPOL = USART_CPOL_Low; USART_ClockInitStruct->USART_CPHA = USART_CPHA_1Edge; USART_ClockInitStruct->USART_LastBit = USART_LastBit_Disable;}
2. 功能管理
- USART_Cmd(); 使能/禁用USART。設(shè)置CR1寄存器的UE位。
- USART_SetAddress(); 為USART分配地址。設(shè)置CR2寄存器的ADD[3:0]位。
- USART_WakeUpConfig(); 設(shè)置USART喚醒模式。設(shè)置CR1寄存器的WAKE位。
- USART_ReceiverWakeUpCmd(); 使能/禁用靜默模式。設(shè)置CR1寄存器的RWU位。
- USART_DMACmd(); 使能/禁用DMA接收/發(fā)送。設(shè)置CR3寄存器的DMAR或DMAT位。
- USART_HalfDuplexCmd(); 使能/禁用半雙工模式。設(shè)置CR3的HDSEL位。
- USART_OverSampling8Cmd(); 接收器一般都是16倍過(guò)采樣。只有STM32F100xx系列支持8倍過(guò)采樣,因?yàn)樵撓盗凶罡哳l率只有24MHz,降低過(guò)采樣可以提高波特率。
- USART_OneBitMethodCmd(); 只有低端芯片才支持的功能。
3. 接收和發(fā)送函數(shù)
- USART_SendData(); 發(fā)送數(shù)據(jù),即將數(shù)據(jù)寫(xiě)入DR寄存器。雖然輸入的Data為16位,但只有低9位有效。這個(gè)函數(shù)核心代碼只有一行,這也是寄存器操作發(fā)送數(shù)據(jù)的典型代碼:
USARTx->DR = (Data & (uint16_t)0x01FF); //取低9位
- USART_ReceiveData(); 接收數(shù)據(jù),即將數(shù)據(jù)從DR寄存器返回。與SendData函數(shù)類似,該函數(shù)只取DR的低9位。
return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);
4. 中斷管理函數(shù)
- USART_ITConfig(); 配置USART中斷。設(shè)置寄存器中與中斷相關(guān)的8個(gè)位(前8個(gè))。
// 所有11個(gè)中斷別名#define USART_IT_PE ((uint16_t)0x0028)#define USART_IT_TXE ((uint16_t)0x0727)#define USART_IT_TC ((uint16_t)0x0626)#define USART_IT_RXNE ((uint16_t)0x0525)#define USART_IT_IDLE ((uint16_t)0x0424)#define USART_IT_LBD ((uint16_t)0x0846)#define USART_IT_CTS ((uint16_t)0x096A)#define USART_IT_ERR ((uint16_t)0x0060)#define USART_IT_ORE ((uint16_t)0x0360)#define USART_IT_NE ((uint16_t)0x0260)#define USART_IT_FE ((uint16_t)0x0160)
- USART_GetITStatus(); 可分別查詢10個(gè)中斷(除了ERR)相關(guān)位的值,借以判別中斷狀態(tài)。
- USART_ClearITPendingBit(); 該函數(shù)用于清除CTS/LBD/TC/RXNE中斷的中斷狀態(tài)位。其他中斷狀態(tài)位的清除方法:
- TXEIE – 讀DR寄存器可清除。
- PEIE/FE/NE/ORE/IDLEIE中斷狀態(tài)位需要軟件序列清除:先用USART_GetITStatus()讀SR寄存器,接著用USART_ReceiveData()讀DR寄存器。
- TC中斷狀態(tài)位需要軟件序列清除:先用USART_GetITStatus()讀SR寄存器,接著用USART_SendData()寫(xiě)DR寄存器。
- USART_GetFlagStatus(); 功能同USART_GetITStatus。
- USART_ClearFlag(); 功能同USART_ClearITPendingBit。
5. LIN模式相關(guān)函數(shù)
- USART_LINCmd(); 使能/禁用LIN模式。設(shè)置CR2寄存器的LINEN位。
- USART_LINBreakDetectLengthConfig(); 配置LIN模式下斷開(kāi)符檢測(cè)時(shí)的幀長(zhǎng)度,10或11bit。設(shè)置CR2寄存器的LBDL位。
- USART_SendBreak(); 向USARTx發(fā)送一個(gè)斷開(kāi)符。設(shè)置CR1寄存器的SBK位。
6. SmartCard模式相關(guān)函數(shù)
- USART_SmartCardCmd(); 使能或禁用智能卡模式。設(shè)置CR3寄存器的SCEN位。
- USART_SetGuardTime(); 設(shè)置智能卡保護(hù)時(shí)間,GTPR寄存器的高8位GT[15:8]。
- USART_SetPrescaler(); 設(shè)置智能卡分頻系數(shù),GTPR寄存器的低8位PSC[7:0]。
- USART_SmartCardNACKCmd(); 使能/禁用NACK傳輸。設(shè)置CR3寄存器的NACK位。
7. IrDA紅外模式相關(guān)函數(shù)
- USART_IrDAConfig(); 配置紅外模式。設(shè)置CR3寄存器的IRLP位。
- USART_IrDACmd(); 使能/退出紅外模式。設(shè)置CR3寄存器的IREN位。
6.5.3 HAL庫(kù)相關(guān)函數(shù)
HAL庫(kù)中USART相關(guān)的常規(guī)庫(kù)函數(shù)有40多個(gè),還有多個(gè)宏函數(shù),在stm32f1xx_hal_usart.h中聲明,stm32f1xx_hal_usart.c中定義。只是比STD庫(kù)多了些函數(shù),換了個(gè)名稱,功能分的更細(xì)一些而已。歸根結(jié)底,也是設(shè)置的各個(gè)寄存器。僅將函數(shù)名稱羅列如下,大多可以從名稱看出功能。
/* 宏函數(shù) _HANDLE_是外設(shè)參數(shù)對(duì)應(yīng)的結(jié)構(gòu)體,HAL庫(kù)中稱為外設(shè)句柄 */__HAL_UART_RESET_HANDLE_STATE()__HAL_UART_FLUSH_DRREGISTER()__HAL_UART_GET_FLAG()__HAL_UART_CLEAR_FLAG()__HAL_UART_CLEAR_PEFLAG()__HAL_UART_CLEAR_FEFLAG()__HAL_UART_CLEAR_NEFLAG()__HAL_UART_CLEAR_OREFLAG()__HAL_UART_CLEAR_IDLEFLAG()__HAL_UART_ENABLE_IT()__HAL_UART_DISABLE_IT()__HAL_UART_GET_IT_SOURCE()__HAL_UART_HWCONTROL_CTS_ENABLE()__HAL_UART_HWCONTROL_CTS_DISABLE()__HAL_UART_HWCONTROL_RTS_ENABLE()__HAL_UART_HWCONTROL_RTS_DISABLE()__HAL_UART_ENABLE()__HAL_UART_DISABLE()/* Initialization/de-initialization functions **/HAL_UART_Init();HAL_HalfDuplex_Init();HAL_LIN_Init();HAL_MultiProcessor_Init();HAL_UART_DeInit();HAL_UART_MspInit();HAL_UART_MspDeInit();/* IO operation functions **/HAL_UART_Transmit();HAL_UART_Receive();HAL_UART_Transmit_IT();HAL_UART_Receive_IT();HAL_UART_Transmit_DMA();HAL_UART_Receive_DMA();HAL_UART_DMAPause();HAL_UART_DMAResume();HAL_UART_DMAStop();HAL_UARTEx_ReceiveToIdle();HAL_UARTEx_ReceiveToIdle_IT();HAL_UARTEx_ReceiveToIdle_DMA();/* Transfer Abort functions */HAL_UART_Abort();HAL_UART_AbortTransmit();HAL_UART_AbortReceive();HAL_UART_Abort_IT();HAL_UART_AbortTransmit_IT();HAL_UART_AbortReceive_IT();/* 中斷與回調(diào)函數(shù) */HAL_UART_IRQHandler();HAL_UART_TxCpltCallback();HAL_UART_TxHalfCpltCallback();HAL_UART_RxCpltCallback();HAL_UART_RxHalfCpltCallback();HAL_UART_ErrorCallback();HAL_UART_AbortCpltCallback();HAL_UART_AbortTransmitCpltCallback();HAL_UART_AbortReceiveCpltCallback();HAL_UARTEx_RxEventCallback();/* Peripheral Control functions **/HAL_LIN_SendBreak();HAL_MultiProcessor_EnterMuteMode();HAL_MultiProcessor_ExitMuteMode();HAL_HalfDuplex_EnableTransmitter();HAL_HalfDuplex_EnableReceiver();/* Peripheral State functions **/HAL_UART_GetState();HAL_UART_GetError();
typedef enum{ HAL_OK = 0x00U, HAL_ERROR = 0x01U, HAL_BUSY = 0x02U, HAL_TIMEOUT = 0x03U} HAL_StatusTypeDef;
HAL庫(kù)中將外設(shè)所有的參數(shù)和回調(diào)函數(shù)整合到一個(gè)結(jié)構(gòu)體之中,稱為外設(shè)的句柄,命名規(guī)則PPPP_HandleTypeDef。具體到USART,UART_HandleTypeDef的定義如下:
/* UART handle Structure definition */typedef struct __UART_HandleTypeDef{ USART_TypeDef *Instance; /*!< UART registers base address */ UART_InitTypeDef Init; /*!< UART communication parameters */ uint8_t *pTxBuffPtr; /*!< Pointer to UART Tx transfer Buffer */ uint16_t TxXferSize; /*!< UART Tx Transfer size */ __IO uint16_t TxXferCount; /*!< UART Tx Transfer Counter */ uint8_t *pRxBuffPtr; /*!< Pointer to UART Rx transfer Buffer */ uint16_t RxXferSize; /*!< UART Rx Transfer size */ __IO uint16_t RxXferCount; /*!< UART Rx Transfer Counter */ __IO HAL_UART_RxTypeTypeDef ReceptionType; /*!< Type of ongoing reception */ DMA_HandleTypeDef *hdmatx; /*!< UART Tx DMA Handle parameters */ DMA_HandleTypeDef *hdmarx; /*!< UART Rx DMA Handle parameters */ HAL_LockTypeDef Lock; /*!< Locking object */ __IO HAL_UART_StateTypeDef gState; /*!< UART state information related to global Handle management and also related to Tx operations. This parameter can be a value of @ref HAL_UART_StateTypeDef */ __IO HAL_UART_StateTypeDef RxState; /*!< UART state information related to Rx operations. This parameter can be a value of @ref HAL_UART_StateTypeDef */ __IO uint32_t ErrorCode; /*!< UART Error code */#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) (* TxHalfCpltCallback)(struct __); /*!< UART Tx Half Complete Callback */ (* TxCpltCallback)(struct __); /*!< UART Tx Complete Callback */ (* RxHalfCpltCallback)(struct __); /*!< UART Rx Half Complete Callback */ (* RxCpltCallback)(struct __); /*!< UART Rx Complete Callback */ (* ErrorCallback)(struct __); /*!< UART Error Callback */ (* AbortCpltCallback)(struct __); /*!< UART Abort Complete Callback */ (* AbortTransmitCpltCallback)(struct __); /*!< UART Abort Transmit Complete Callback */ (* AbortReceiveCpltCallback)(struct __); /*!< UART Abort Receive Complete Callback */ (* WakeupCallback)(struct __); /*!< UART Wakeup Callback */ (* RxEventCallback)(struct __, uint16_t Pos); /*!< UART Reception Event Callback */ (* MspInitCallback)(struct __); /*!< UART Msp Init callback */ (* MspDeInitCallback)(struct __); /*!< UART Msp DeInit callback */#endif /* USE_HAL_UART_REGISTER_CALLBACKS */} UART_HandleTypeDef;
有些屬性本身有是一個(gè)結(jié)構(gòu)體。句柄的概念與MATLAB中的handle非常像。通過(guò)一個(gè)句柄可以管理外設(shè)對(duì)象的所有屬性。
USART在STM32CubeIDE中的配置過(guò)程如下面幾幅圖所示
TODO:LIN模式、智能卡模式、IrDA模式暫時(shí)不深究,用到時(shí)再學(xué)習(xí);USART利用DMA連續(xù)通信,留待學(xué)習(xí)DMA時(shí)一并學(xué)習(xí)。