使用DMA傳輸可以連續擷取或發送一段資訊而不佔用中斷或延時,在通訊頻繁或有大段資訊要傳輸時非常有用。
由上表可知,要使用USART1TX/RX我們選擇通道4和5
1、 DMA傳輸方式:
(1) DMA_Mode_Normal,當通道配置為非迴圈模式時,傳輸結束後(即傳輸計數變為0)將不再產生DMA操作。要開始新的DMA傳輸,需要3個步驟:在關閉DMA通道的情況下,在DMA_CNDTRx寄存器中重新寫入傳輸數目,然後重新開啟DMA。
void DMA1_Channel5_IRQHandler(void){//由於不同的中斷源擁有同一個中斷向量入口,所以需要判斷中斷標誌 if(DMA_GetFlagStatus(DMA1_FLAG_TC5)==SET) { DMA_Cmd (DMA1_Channel5,DISABLE);//關閉DMA通道 DMA_ClearFlag(DMA1_FLAG_TC5);//清中斷標誌,否則會一直中斷 DMA_SetCurrDataCounter(DMA1_Channel5,UART_DMA_BUFFSIZE);//重設傳輸數目,當再次達到這個數目就會進中斷 DMA_Cmd (DMA1_Channel5,ENABLE);//開啟DMA通道 }}
(2) DMA_Mode_Circular,在迴圈模式下,最後一次傳輸結束時, DMA_CNDTRx寄存器的內容會自動地被重新載入為其初始數值,內部的當前外設/儲存空間地址寄存器也被重新載入為DMA_CPARx/DMA_CMARx寄存器設定的初始基地址。
2、將外設與DMA串連起來
將串口1的發送設定成DMA模式:
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
3、資料的發送
使用非迴圈模式,跟上文的1.(1)中重新開啟DMA的3個步驟一樣,將UART_TX_Buff中的資料準備好,然後開啟DMA,即可自動發送UART_TX_Buff中的資料,資料轉送完成,進入中斷DMA1_Channel4_IRQHandler
4、資料的接收
使用DMA中斷來接收資料,只能接收固定幀長的資料,USART接收夠一定長度的資料,就會進入DMA中斷。
若要接收可變長度的資料,方法有以下3種:
1.將RX腳與一路時鐘外部引腳相連,當串口一幀發完,即可利用此定時器產生逾時中斷.這個即時性較高,可以做到1個位元組即時監測.
2.不改變硬體,開啟一個定時器監控DMA接收,如果逾時則產生中斷.這個即時性不高,因為逾時時間必須要大於需要接收幀的時間,精度不好控制.
3.STM32單片機有的串口可以監測匯流排是否處於空閑,如果空閑則產生中斷.可以用它來監測DMA接收是否完畢.這種方式即時性很高。當USART在停止位後的一個byte的時間內,匯流排是閒置,就置位匯流排空閑標誌,這時我們認為一幀的資料轉送完成,就會進入USART中斷處理。
但這裡需要注意一個問題就是,如果兩幀的資料緊挨著一起被接收,那麼這種情況應該使用DMA中斷。因為使用USART空閑中斷的話,要兩幀全部發完才能進入中斷,這樣只能處理一幀的資料;使用DMA中斷的話,在第一幀結束就可以進入中斷,即使第二幀緊跟著後面。
代碼中是採用第三種方法。
【Reference】
http://blog.csdn.net/jdh99/article/details/8444474
http://blog.chinaunix.net/uid-21658993-id-3030728.html