使用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