本帖最后由 kkhkbb 于 2018-4-3 21:21 編輯
一、概述:
1、DMA簡(jiǎn)介
DMA的英文拼寫(xiě)是"Direct Memory Access",漢語(yǔ)的意思就是直接內(nèi)存訪問(wèn),是一種不經(jīng)過(guò)CPU而直接從內(nèi)存存取數(shù)據(jù)的數(shù)據(jù)交換模式。在DMA模式下,CPU只須向DMA控制器下達(dá)指令,讓DMA控制器來(lái)處理數(shù)據(jù)的傳送,數(shù)據(jù)傳送完畢再把信息反饋給CPU,這樣就很大程度上減輕了CPU資源占有率,可以大大節(jié)省系統(tǒng)資源。DMA模式又可以分為Single-Word DMA(單字節(jié)DMA)和Multi-Word DMA(多字節(jié)DMA)兩種。
2、DMA工作原理
DMA 允許不同速度的硬件裝置來(lái)溝通,而不需要依于 CPU 的大量中斷負(fù)載。否則,CPU 需要從來(lái)源把每一片段的資料復(fù)制到暫存器,然后把他們?cè)俅螌?xiě)回到新的地方。在這個(gè)時(shí)間中,CPU 對(duì)于其他的工作來(lái)說(shuō)就無(wú)法使用。
DMA 傳輸主要地將一個(gè)內(nèi)存區(qū)從一個(gè)裝置復(fù)制到另外一個(gè)。當(dāng) CPU 初始化這個(gè)傳輸動(dòng)作,傳輸動(dòng)作本身是由 DMA 控制器來(lái)實(shí)行和完成。典型的例子就是移動(dòng)一個(gè)外部?jī)?nèi)存的區(qū)塊到芯片內(nèi)部更快的內(nèi)存去。像是這樣的操作并沒(méi)有讓處理器工作拖延,反而可以被重新排程去處理其他的工作。所以,DMA傳輸對(duì)于高效能嵌入式系統(tǒng)算法和網(wǎng)絡(luò)是很重要的。
3、DMA類(lèi)別
按鍵主要有兩種類(lèi)型:?jiǎn)巫止?jié)DMA、多字節(jié)DMA。
單字節(jié)DMA:一次傳送一個(gè)字節(jié),效率較低,但它會(huì)保證在兩次DMA傳送之間,CPU有機(jī)會(huì)獲得總線控制權(quán),執(zhí)行一次CPU總線周期。
多字節(jié)DMA:一次請(qǐng)求傳送一個(gè)數(shù)據(jù)塊,效率高,但在整個(gè)DMA傳送期間,CPU長(zhǎng)時(shí)間無(wú)法控制總線(無(wú)法響應(yīng)其他DMA請(qǐng)求,無(wú)法處理其他中斷等)。 二、實(shí)驗(yàn)原理: DMA(直接存儲(chǔ)器訪問(wèn))傳輸不需要占用CPU,可以在存儲(chǔ)器至實(shí)現(xiàn)高速的數(shù)據(jù)傳輸。本實(shí)驗(yàn)采用DMA2控制器的數(shù)據(jù)流0,選用通道0進(jìn)行數(shù)據(jù)傳輸。通過(guò)LED的顏色來(lái)判斷傳輸是否成功。 三、源代碼: 1.主函數(shù)及DMA設(shè)置 - /*
- * Name : main
- * Description : ---
- * Author : ysloveivy.
- *
- * History
- * --------------------
- * Rev : 0.00
- * Date : 11/21/2015
- *
- * create.
- * --------------------
- */
- int main(void)
- {
- int i,k;
- DMA_InitTypeDef DMA_InitStructure;
- led.initialize();
- dma.initialize();
- //測(cè)試DMA,測(cè)試成功藍(lán)燈閃爍,測(cè)試失敗,紅燈閃爍
- DMA_InitStructure.DMA_Channel = DMA_Channel_0; //選擇通道0
- DMA_InitStructure.DMA_PeripheralBaseAddr = (unsigned long int)src_buffer; //DMA外設(shè)基地址
- DMA_InitStructure.DMA_Memory0BaseAddr = (unsigned long int)dst_buffer; //DMA存儲(chǔ)器地址
- DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory; //方向?yàn)榇鎯?chǔ)器到存儲(chǔ)器
- DMA_InitStructure.DMA_BufferSize = (unsigned long int)BUFFER_SIZE; //數(shù)據(jù)傳輸量
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; //外設(shè)增量模式
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存儲(chǔ)器增量模式
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //設(shè)置外設(shè)數(shù)據(jù)寬度
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //設(shè)置存儲(chǔ)器數(shù)據(jù)寬度
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //運(yùn)行模式為普通模式
- DMA_InitStructure.DMA_Priority = DMA_Priority_High; //優(yōu)先級(jí)級(jí)別為高
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //FIFO模式禁止
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; //FIFO閾值
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存儲(chǔ)器突發(fā)單次傳輸
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外設(shè)突發(fā)單次傳輸
- DMA_Init(DMA2_Stream0, &DMA_InitStructure);
- DMA_Cmd(DMA2_Stream0, ENABLE); //使能DMA2_Stream0
- while(DMA_GetCmdStatus(DMA2_Stream0) != DISABLE);
- for(i = 0;i < BUFFER_SIZE;i++){
- if(dst_buffer[i] != src_buffer[i]){
- //測(cè)試失敗
- while(1){
- for(k = 0;k < 10000000;k++);
- LED_RED_ON;
- for(k = 0;k < 10000000;k++);
- LED_RED_OFF;
- }
- }
- }
- //測(cè)試成功
- while(1){
- for(k = 0;k < 10000000;k++);
- LED_BLUE_ON;
- for(k = 0;k < 10000000;k++);
- LED_BLUE_OFF;
- }
- }
復(fù)制代碼2.DMA初始化函數(shù) - /*
- * Name : initialize
- * Description : ---
- * Author : ysloveivy.
- *
- * History
- * --------------------
- * Rev : 0.00
- * Date : 11/29/2015
- *
- * create.
- * --------------------
- */
- static int initialize(void)
- {
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); //使能DMA2時(shí)鐘
- DMA_DeInit(DMA2_Stream0); //配置DMA2
- while (DMA_GetCmdStatus(DMA2_Stream0) != DISABLE) //等待DMA可配置
- {
- }
- return 0;
- }
復(fù)制代碼3、小知識(shí) 在DMA的設(shè)置中我們遇到了關(guān)于DMA設(shè)置的結(jié)構(gòu)體,我們通過(guò)配置其相關(guān)參數(shù),以實(shí)現(xiàn)我們想要的功能,其解釋如下: - typedef struct
- {
- uint32_t DMA_Channel; //選擇通道
- uint32_t DMA_PeripheralBaseAddr; //DMA外設(shè)基地址
- uint32_t DMA_Memory0BaseAddr; //DMA存儲(chǔ)器地址
- uint32_t DMA_DIR; //DMA傳輸方向
- uint32_t DMA_BufferSize; //數(shù)據(jù)傳輸量
- uint32_t DMA_PeripheralInc; //外設(shè)增量模式選擇
- uint32_t DMA_MemoryInc; //存儲(chǔ)器增量模式
- uint32_t DMA_PeripheralDataSize; //設(shè)置外設(shè)數(shù)據(jù)寬度
- uint32_t DMA_MemoryDataSize; //設(shè)置存儲(chǔ)器數(shù)據(jù)寬度
- uint32_t DMA_Mode; //運(yùn)行模式選擇
- uint32_t DMA_Priority; //優(yōu)先級(jí)選擇
- uint32_t DMA_FIFOMode; //FIFO模式選擇
- uint32_t DMA_FIFOThreshold; //FIFO閥值
- uint32_t DMA_MemoryBurst; //存儲(chǔ)器突發(fā)單次傳輸
- uint32_t DMA_PeripheralBurst; //外設(shè)突發(fā)單次傳輸
- }DMA_InitTypeDef;
復(fù)制代碼四、實(shí)驗(yàn)現(xiàn)象: 試驗(yàn)成功藍(lán)色LED燈閃爍,試驗(yàn)反敗紅色LED燈閃爍。 五、代碼包下載連接: 網(wǎng)盤(pán):http://pan.baidu.com/s/1bcY5JK
|