UART的FIFO功能
UART的FIFO功能
2015年09月08日 18:21:23
閱讀數:5464
經常聽到UART的FIFO功能,但是從來沒有真正使用過和認真思考過它的作用。正好有客戶用到這個功能,在這里做個總結。?
FIFO 是“First-In First-Out”的縮寫,它是一個具有先入先出特點的緩沖區。串口設計FIFO的目的是為了提高串口的通訊性能。如果沒有FIFO或者說緩沖區的長度只有1字節,那么使用接收中斷,就意味著每次收到一個字節的數據就要進一次中斷,這樣頻繁進中斷會占用CPU資源。另外如果沒有及時讀走數據,那么下一個字節數據就會覆蓋之前的數據,導致數據丟失,這在通訊速率高的場合很有可能出現。?
使用FIFO,可以在連續接收若干個數據后才產生一次中斷,然后一起進行處理。這樣可以提高接收效率,避免頻繁進中斷,適用于大數據傳輸。你可能會想到如果FIFO中的數據沒有達到指定長度而無法產生中斷怎么辦,通常MCU會有接收超時中斷,即在一定的時間內沒有接收到數據會進入中斷,可以利用這個中斷把不足FIFO長度的數據最后都讀取完。?
?
但是使用FIFO接收多字節數據進中斷不好的地方是實時性會受到一定的影響,對某些實時性要求高的場合,比如說要求UART收到某個特定字符就立刻停止發送數據這樣一個場合,使用FIFO每多個字節進一次中斷就不合適了。?
所以說使用FIFO好處是1)避免頻繁進中斷,提高吞吐率 2)避免數據因沒有及時處理而丟失。不好的地方是實時性受影響。?
此客戶要求使用FIFO的原因是他們擔心在接收中斷處理過程中數據來的太快沒有及時處理而丟失。?
針對這個問題采取的解決方法是:還是一個字節進一次接收中斷,這樣可以保證實時性,把FIFO打開,這樣可以防止數據被覆蓋而丟失,在接收中斷處理完接收數據之后去判斷緩沖區中是否有數據,如果有的話把數據讀走,這樣就防止了數據丟失,同時保證了實時性。?
對于Kinetis M4 MCU操作也非常簡單。?
以K60為例,UART0和UART1緩沖區長度為8,其他UART緩沖區長度為1.?
?
只要配置UARTx_PFIFO寄存器即可。?
?
軟件上是:
- 1
- 2
- 3
需要注意的是:配置此寄存器 C2[RE] 和C2[TE] 位為0,另外在設置完RXFE位之后,應立刻向UARTx_CFIFO的TXFLUSH和RXFLUSH位寫1.
這樣配置完之后就打開了接收FIFO功能。在中斷處理函數中,最后去判斷UARTx_SFIFO 寄存器的RXEMPT位是否為1即可。?
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
前面提到的接收多個字節進一次中斷該如何實現呢。?
只需要設置一下UARTx_RWFIFO寄存器即可。?
- 1
前面還提到超時中斷,在Kinetis MCU里是叫做IDLE Line 中斷。?
只需要設置UARTx_C2的ILIE為1,使能IDLE LINE中斷。?
?
另外設置UARTx_C1的ILT位?
?
在中斷服務函數中
/* IDLE interrupt */if(UART1_S1&UART_S1_IDLE_MASK)// if IDLE Line interrupt occured{// clear interrupt flag; To clear IDLE, read UART status S1 with IDLE set and then read DUART1_S1 |= UART_S1_IDLE_MASK;Receive_data=(uint8_t)(UART1_BASE_PTR->D); printf("\r\nGo to Idle line\r\n");}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
前面一直說的接收過程,對于發送過程也是類似的。不用FIFO,如果使用中斷方式發送的話,那么就是一個字節發送完進一次中斷,然后發送另外一字節數據。使用FIFO的話,每次中斷處理可以多個字節的數據。?
?
注意在中斷服務里發送的字節數并沒有限制,進發送中斷的核心條件是?
TXWATER默認值為0. 當FIFO為空時,即所有數據都發送出去時進中斷。?
假設我想在每次中斷服務函數中發送4個字節,程序設置如下:?
首先初始化時打開TX的FIFO功能
- 1
- 2
- 3
在中斷處理函數中
/* Tx */if((UART_InstanceTable[HW_UART0]->S1 & UART_S1_TDRE_MASK) && (UART_InstanceTable[HW_UART0]->C2 & UART_C2_TIE_MASK)){/* buffer is used */while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));UART_InstanceTable[HW_UART0]->D = '1';/* buffer is used */while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));UART_InstanceTable[HW_UART0]->D = '2'; /* buffer is used */while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));UART_InstanceTable[HW_UART0]->D = '3'; /* buffer is used */while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));UART_InstanceTable[HW_UART0]->D = '4';/* buffer is used */while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));UART_InstanceTable[HW_UART0]->D = '5';/* buffer is used */while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));UART_InstanceTable[HW_UART0]->D = '6';/* buffer is used */while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));UART_InstanceTable[HW_UART0]->D = '7';/* buffer is used */while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));UART_InstanceTable[HW_UART0]->D = ' ';- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
.?
.?
.?
}
在網上看到一篇很好的文章,下載鏈接為:http://download.csdn.net/detail/wangwenxue1989/9089861
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的UART的FIFO功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SPI 接口配置
- 下一篇: FIFO and DMA