什么是DMA?其全稱是:Direct MemoryAccess;根據(jù)ST公司提供的相關(guān)信息,DMA是STM32中一個獨立與Cortex-M3內(nèi)核的模塊,有點類似與ADC、PWM、TIMER等模塊;主要功能是通信“橋梁”的作用,可以將所有外設映射的寄存器“連接”起來,這樣就可以高速問各寄存器,其傳輸不受CPU的支配,傳輸還是雙向的;例如,從“表面”上看,它可以將flash中的數(shù)據(jù)與儲存器中變量建立通訊,還可以將一外設的積存器或緩沖器與另外設的寄存器或緩沖器建立雙向通訊,有點像把外設硬件之間用“導線”連接在一起了。其間的通訊不占CPU資源,訪問速度高,對于實時性強的應用將是一個很好的選擇;就像我們?nèi)艘粯�,我們平常習慣性的動作是不用經(jīng)過大腦思考的,比如說眨眼睛,呼吸等。DMA就是負責這些工作的,但它沒人這么智能,需要將它設置好了它才會正常工作。當然,對于實時性非常強的,建議還是采用專用的DSP芯片。
怎樣啟用DMA?首先,眾所周知的是初始化,任何設備啟用前都要對其進行初始化,要對模塊初始化,還要先了解該模塊相應的結(jié)構(gòu)及其函數(shù),以便正確的設置;由于DMA較為復雜,我就只談談DMA的基本結(jié)構(gòu)和和常用函數(shù),這些都是ST公司提供在庫函數(shù)中的。在一個重要的條件就是觸發(fā)源是什么,就是說什么時候進行DMA數(shù)據(jù)傳輸呢?這叫觸發(fā)信號。也可以通過軟件編程設置具體時間,具體條件來觸發(fā)DMA數(shù)據(jù)傳輸,DMA的觸發(fā)源是事件,下面代碼是一個標準DMA設置,當然實際應用中可根據(jù)實際情況進行裁減,當然這之前得開啟DMA時鐘:
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//開啟DMA1時鐘
結(jié)構(gòu)體(DMA_InitTypeDef)說明: PeripheralBaseAddr:外設地址 CPAR MemoryBaseAddr: 存儲器地址 CMAR DIR: 傳輸方向(從外設讀/從存儲器讀) BufferSize: 傳輸數(shù)量 PeripheralInc: 外設地址增量模式(傳完一個數(shù)后地址是否+1) MemoryInc: 存儲器地址增量模式 PeripheralDataSize: 外設數(shù)據(jù)寬度(Byte / Half Word /Word) MemoryDataSize: 存儲器數(shù)據(jù)寬度 Mode: 循環(huán)/正常 Priority: 優(yōu)先級 M2M: 存儲器到存儲器模式
DMA_DeInit(DMA_Channel1);
上面這句是給DMA配置通道,根據(jù)ST提供的資料,STM3210Fx中DMA包含7個通道(CH1~CH7),也就是說可以為外設或memory提供7座“橋梁”(請允許我使用橋梁一詞,我覺得更容易理解,哈哈,別“拍磚”呀�。�;
DMA_InitStructure.DMA_PeripheralBaseAddr =ADC1_DR_Address;
上面語句中的DMA_InitStructure是一個DMA結(jié)構(gòu)體,在庫中有聲明了,當然使用時就要先定義了;DMA_PeripheralBaseAddr是該結(jié)構(gòu)體中一個數(shù)據(jù)成員,給DMA一個起始地址,好比是一個buffer起始地址,數(shù)據(jù)流程是:外設寄存器àDMA_PeripheralBaseAddàmemory中變量空間(或flash中數(shù)據(jù)空間等),ADC1_DR_Address是我定義的一個地址變量;
DMA_InitStructure.DMA_MemoryBaseAddr =(u32)ADC_ConvertedValue;
上面這句很顯然是DMA要連接在Memory中變量的地址,ADC_ConvertedValue是我自己在memory中定義的一個變量;
DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralSRC;
上面的這句是設置DMA的傳輸方向,就如前面我所說的,DMA可以雙向傳輸,也可以單向傳輸,這里設置的是單向傳輸,如果需要雙向傳輸:把DMA_DIR_PeripheralSRC改成DMA_DIR_PeripheralDST即可。
DMA_InitStructure.DMA_BufferSize = 2;
上面的這句是設置DMA在傳輸時緩沖區(qū)的長度,前面有定義過了buffer的起始地址:ADC1_DR_Address,為了安全性和可靠性,一般需要給buffer定義一個儲存片區(qū),這個參數(shù)的單位有三種類型:Byte、HalfWord、word,我設置的2個half-word(見下面的設置);32位的MCU中1個half-word占16bits。
DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable;
上面的這句是設置DMA的外設遞增模式,如果DMA選用的通道(CHx)有多個外設連接,需要使用外設遞增模式:DMA_PeripheralInc_Enable;我的例子里DMA只與ADC1建立了聯(lián)系,所以選用DMA_PeripheralInc_Disable
DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable;
上面的這句是設置DMA的內(nèi)存遞增模式,DMA訪問多個內(nèi)存參數(shù)時,需要使用DMA_MemoryInc_Enable,當DMA只訪問一個內(nèi)存參數(shù)時,可設置成:DMA_MemoryInc_Disable。
DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_HalfWord;上面的這句是設置DMA在訪問時每次操作的數(shù)據(jù)長度。有三種數(shù)據(jù)長度類型,前面已經(jīng)講過了,這里不在敘述。DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_HalfWord;
與上面雷同。在此不再說明。
DMA_InitStructure.DMA_Mode =DMA_Mode_Circular;
上面的這句是設置DMA的傳輸模式:連續(xù)不斷的循環(huán)模式,若只想訪問一次后就不要訪問了(或按指令操作來反問,也就是想要它訪問的時候就訪問,不要它訪問的時候就停止),可以設置成通用模式:DMA_Mode_Normal
DMA_InitStructure.DMA_Priority =DMA_Priority_High;
上面的這句是設置DMA的優(yōu)先級別:可以分為4級:VeryHigh,High,Medium,Low.
DMA_InitStructure.DMA_M2M =DMA_M2M_Disable;
上面的這句是設置DMA的2個memory中的變量互相訪問的
DMA_Init(DMA_Channel1,&DMA_InitStructure);
前面那些都是對DMA結(jié)構(gòu)體成員的設置,在次再統(tǒng)一對DMA整個模塊做一次初始化,使得DMA各成員與上面的參數(shù)一致。
DMA_Cmd(DMA_Channel1,ENABLE);
這一句我想我就不羅嗦了,大家一看就明白。


|