實現(xiàn)STM32中USART的DMA
傳輸數(shù)據(jù)到某個位置,如果不用DMA,那要CPU參與操作,一個字節(jié)一個字節(jié)地搬,效率高
點的,就一個字一個字地搬.但當你用了DMA 后,那就是只需要設(shè)置:A.從哪里開始搬; B,
搬到哪里去;C以字節(jié)方式搬還是半字還是字;D:一共搬多少個.之后,啟動DMA.CPU內(nèi)部
就會開始搬數(shù)據(jù)了,整個搬數(shù)據(jù)的過程都不需要指令的參與,唯一要做的,就是檢測什么時
候搬完.你可以掃描寄存器,也可以用中斷.這里,我使用了中斷.
具體設(shè)置功能看注釋就可以明白了.注意一點就是,有一個設(shè)置:
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
這個是外設(shè)的地址不遞增.也就是說,每次搬動,都是從源頭,也就是USART1的DR寄存器
搬,但內(nèi)存地址卻是遞增的:
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
這個歷程實現(xiàn)了 接受 串口的數(shù)據(jù) 寫到FLASH 之中工作,而DMA的作用在于將 串口收寄存器 USART1->DR 的 數(shù)據(jù)寫到內(nèi)存之中 比如某個數(shù)組之中 u8 USART1_DMA_Buf1[512]; 寫滿512個字節(jié)之后將進入DMA中斷(通道5)在這里修改DMA 的內(nèi)存寫入入口
u8 USART1_DMA_Buf2[512]; ,同時標記 下次的入口Free_Buf_No=BUF_NO1; 與 Buf_Ok=TRUE; 證明已有數(shù)據(jù)準備完成。這時CUP將USART1_DMA_Buf1中的數(shù)據(jù)寫入FLASH .
又抄了一點
這次使用的是雙緩沖,也有人
叫乒乓緩沖.因為一般情況下,串口的數(shù)據(jù)DMA 傳輸進BUF1 的過程中,是不建議對
BUF1 進行操作的.但由于串口數(shù)據(jù)是不會等待的直傳,所以你總不能等BUF1 滿了,
才往FLASH 上寫,因為這時候串口數(shù)據(jù)依舊是源源不斷.于是,使用雙緩沖就變的理
所當然了.當BUF1 滿了的時候,就馬上設(shè)置DMA的目標為BUF2,并且BUF1的數(shù)據(jù)
往25F080上灌.當串口DMA寫滿了BUF2的時候,再設(shè)置DMA的目標為BUF1,此時
再操作BUF2寫進25F080.如此一直循環(huán),就好像打乒乓球那樣吧,所以就叫乒乓緩沖.
用這個方法的速度極限就是,你必須確保兩點a.DMA 灌滿了BUF1 的時候,會發(fā)生中
斷,此時切換DMA 的目標緩沖為BUF2,而且切換的過程必須在新的串口數(shù)據(jù)溢出之
前完成.b.在DMA的BUF1滿之前,另外一個有數(shù)據(jù)的BUF2必須能全部寫進25F080,
其中包括了遇到新的扇區(qū)邊界而要刷除扇區(qū)的操作時間!!
可以看出,BUF的增大,并不能夠很大程度的提升速度極限.
假設(shè) USART 與 FLASH 的底層驅(qū)動已經(jīng)寫好了。
#define SRC_USART1_DR
//DMA目標緩沖,這里使用雙緩沖
u8 USART1_DMA_Buf1[512];
u8 USART1_DMA_Buf2[512];
bool Buf_Ok;
BUF_NO Free_Buf_No;
DMA_InitTypeDef DMA_InitStructure;
void USART_DMAToBuf1(void)
{