stm32異步串口(uart)通訊一些冷知識

| 異步串口通訊接收方RX接收數據的詳細過程

1.檢測數據線上起始位

2.將緊跟著起始位的8/9位(字長設置決定)有效數據從引腳<strong>串行讀入接收移位寄存器(<strong>LSB在前)


stm32異步串口(uart)通訊一些冷知識

圖1 字長為8


stm32異步串口(uart)通訊一些冷知識

圖2 字長為9

3.停止位如果沒有在預期的時間內接收識別出來,則會觸發<strong>幀錯誤,噪音、發送方與接收方未能同步都是造成這種情況的可能原因

4.此時若狀態寄存器(SR)的讀數據寄存器非空位(RXNE)已復位(置零),移位寄存器的數據並行讀入數據寄存器(DR),準確的說是輸入數據寄存器(RDR),並置位狀態寄存器(SR)的讀數據寄存器非空位(RXNE),若使能了接收中斷,則觸發對應中斷處理程序


stm32異步串口(uart)通訊一些冷知識

圖3 TDR 與 RDR

如果讀數據寄存器非空位(RXNE)未被複位,意即數據寄存器(DR)中的數據未被讀取,又接收到一個字符,則會觸發<strong>溢出錯誤

5.由中斷處理程序/循環查詢標誌程序/DMA將數據從數據寄存器(DR)讀走,同時清零RXNE位

至此,一幀數據的接收完畢,接下來我們一步步分析數據接收過程中的冷知識

| 起始位的檢測與數據的抓取

數據接收的過程中,接收模塊第一步就是檢測數據線上的起始位,進而抓取之後的數據。那麼在可能的噪聲環境裡,在沒有時鐘線傳送時鐘保證同步的情況下,如何正確判斷起始位的下降沿與低電平,數據位如何正確讀取而不被毛刺等噪聲電平干擾呢?這裡接收模塊藉助一套串口標準和過採樣技術保證了數據的準確性

起始位檢測

標準UART的RXD前端有一個"<strong>1到0跳變檢測器"(空閒狀態下,有效電平為1),當該檢測器檢測到下降沿的跳變時,在一位數據週期裡(若波特率為57600,則該週期為1/57600s),每隔相同的時間間隔會進行多次採樣,如下圖所示,若採樣16次,即為<strong>16倍過採樣

,採樣次數可根據需要選擇,據硬件平臺而定,常見的有8倍過採樣、16倍過採樣、64倍過採樣

stm32異步串口(uart)通訊一些冷知識

圖4 起始位檢測

這裡以16倍過採樣為例,如上圖所示採集的16次樣本里,從首次採樣點起,若滿足0X0X0X0000(X可以是0也可以是1)這個採樣序列則確認檢測到了起始位,開始下一位數據的接收。

值得注意的是,若第3、5、7採樣點中僅有2個是0或第8、9、10採樣點中僅有2個0,那麼仍然認為檢測到了起始位,開始數據接收,但會置位噪音錯誤標誌位(NE),認為出現了<strong>噪音錯誤

其他情況,中止起始位的偵測過程,接收模塊回到空閒狀態

數據位抓取

當接收模塊確認檢測到起始位後,立即進行數據的抓取,同檢測起始位一樣,這裡也會在一位數據的時間裡對接收引腳電平進行16次採樣,如下圖所示

stm32異步串口(uart)通訊一些冷知識

圖5 數據位抓取

通過中間8、9、10次採樣點,判斷該位數據0/1碼,判斷標準如下表所示


stm32異步串口(uart)通訊一些冷知識

圖6 數據位判斷標準

如表中所示,只要三次採樣數據不一致,數據即應為無效,<strong>噪聲錯誤則被觸發,但狀態寄存器中的噪音錯誤標誌位(NE)並不會被立即置位,而是要等到全部8/9位(由設定字長決定)接收完畢並讀入到數據寄存器(DR)中,在讀數據寄存器非空位(RXNE)的上升沿被置位。如果並沒有針對噪音錯誤作相應處理,且奇偶校驗也沒有相應動作,則該數據將被作為有效數據接收

奇偶校驗位的特殊地位

對於許多新手而言,串口應用的常規配置為一位起始位,8位字長,無奇偶校驗,一位停止位,但當啟用了奇偶校驗功能後,就需要小心處理了,<strong>奇偶校驗位會佔據一位有效數據,<strong>即寫進數據寄存器數據的MSB位被校驗位替換後發送出去,如下表所示:

stm32異步串口(uart)通訊一些冷知識

圖7 奇偶校驗位的位置

TDR與RDR

通常我們使用某串口接收數據時會調用如下庫函數:

<code>uint16_t USART_ReceiveData(USART_TypeDef* USARTx){  /* Check the parameters */  assert_param(IS_USART_ALL_PERIPH(USARTx));    /* Receive Data */  return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);}/<code>

而通過某串口發送數據時,調用如下庫函數:

<code>void USART_SendData(USART_TypeDef* USARTx, uint16_t Data){  /* Check the parameters */  assert_param(IS_USART_ALL_PERIPH(USARTx));  assert_param(IS_USART_DATA(Data));       /* Transmit Data */  USARTx->DR = (Data & (uint16_t)0x01FF);}/<code>

對比上述兩個函數,可以發現發送和接收數據其實操作的是同一個寄存器,那麼如果在向數據寄存器DR寫入發送數據時,模塊恰巧接收了一幀數據,會不會出現衝突,導致寫入的數據或接收的數據被抹掉?答案當然是否定的


stm32異步串口(uart)通訊一些冷知識

圖8 TDR 與 RDR

如上圖所示,原因就在於其實<strong>數據寄存器(DR)由兩個寄存器組成的,一個是發送數據寄存器(TDR),它提供了內部總線和輸出移位寄存器之間的並行接口,承接發送時寫入數據寄存器的數據,一個是接收數據寄存器(RDR),它提供了內部總線和輸入移位寄存器之間的並行接口,承接接收時讀入數據寄存器的數據。<strong>二者共享數據寄存器的地址,由硬件區分

波特率

波特率,意即每秒鐘傳送的二進制位數,以波特率57600為例,也就是數據每秒傳送量為57600個二進制位。

但需要清楚的是,這並非意味著我們可以每秒接收57600個有效數據,需要在此基礎上減去起始位、停止位以及可能的奇偶校驗位的數量,如圖1、圖2

其次,當串口模塊外接無線模塊作為傳輸介質時,同樣要考慮無線模塊的波特率配置及其帶寬限制,這往往是引發數據傳輸錯誤的盲點

stm32異步串口(uart)通訊一些冷知識

圖9 無線數傳

發送數據時,等待TXE還是TC

在發送數據時,必須等待上一幀數據發送完畢才能發送下一幀數據,否則就會使當前正在發送的數據受到破壞。那麼我們是等待狀態寄存器的發送數據寄存器空位(TXE)位置位還是等待發送完成位(TC)位置位呢?

stm32異步串口(uart)通訊一些冷知識

圖10 發送時TC/TXE的變化情況

當寫操作把數據存進TDR寄存器後,硬件會自動判斷當前移位寄存器內的數據是否傳輸完畢,只有在數據傳輸結束時,才把TDR寄存器中的數據複製進移位寄存器。

由上圖可知,當TDR數據寄存器中的數據被複制進移位寄存器中後,發送數據寄存器空(TXE)標誌位被硬件自動置位,當讀取狀態寄存器SR,並向數據寄存器TDR寫入數據時,該標誌位清零。而在TXE被清零時,即TDR寄存器有數據時,發送完畢標誌(TC)位在移位寄存器中的現有數據發送完畢時得不到置位操作。

綜上,這裡建議發送數據時,等待TXE被置位後將下一幀數據寫入TDR寄存器


分享到:


相關文章: