<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > stm32中DMA基本使用

stm32中DMA基本使用

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò ) 收藏
DMA有什么用?

直接存儲器存取用來(lái)提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸。無(wú)須CPU的干預,通過(guò)DMA數據可以快速地移動(dòng)。這就節省了CPU的資源來(lái)做其他操作。

本文引用地址:http://dyxdggzs.com/article/201611/318277.htm

有多少個(gè)DMA資源?

有兩個(gè)DMA控制器,DMA1有7個(gè)通道,DMA2有5個(gè)通道。

數據從什么地方送到什么地方?

外設到SRAM(I2C/UART等獲取數據并送入SRAM);

SRAM的兩個(gè)區域之間;

外設到外設(ADC讀取數據后送到TIM1控制其產(chǎn)生不同的PWM占空比);

SRAM到外設(SRAM中預先保存的數據送入DAC產(chǎn)生各種波形);

……還有一些目前還搞不清楚的。

DMA可以傳遞多少數據?

傳統的DMA的概念是用于大批量數據的傳輸,但是我理解,在STM32中,它的概念被擴展了,也許更多的時(shí)候快速是其應用的重點(diǎn)。數據可以從1~65535個(gè)。

直接存儲器存?。―irect Memory Access,DMA)是計算機科學(xué)中的一種內存訪(fǎng)問(wèn)技術(shù)。它允許某些電腦內部的硬體子系統(電腦外設),可以獨立地直接讀寫(xiě)系統存儲器,而不需繞道 CPU。在同等程度的CPU負擔下,DMA是一種快速的數據傳送方式。它允許不同速度的硬件裝置來(lái)溝通,而不需要依于 CPU的大量中斷請求。

現在越來(lái)越多的單片機采用DMA技術(shù),提供外設和存儲器之間或者存儲器之間的高速數據傳輸。當 CPU 初始化這個(gè)傳輸動(dòng)作,傳輸動(dòng)作本身是由DMA 控制器來(lái)實(shí)行和完成。STM32就有一個(gè)DMA控制器,它有7個(gè)通道,每個(gè)通道專(zhuān)門(mén)用來(lái)管理一個(gè)或多個(gè)外設對存儲器訪(fǎng)問(wèn)的請求,還有一個(gè)仲裁器來(lái)協(xié)調各個(gè)DMA請求的優(yōu)先權。

DMA 控制器和Cortex-M3核共享系統數據總線(xiàn)執行直接存儲器數據傳輸。當CPU和DMA同時(shí)訪(fǎng)問(wèn)相同的目標(RAM或外設)時(shí),DMA請求可能會(huì )停止 CPU訪(fǎng)問(wèn)系統總線(xiàn)達若干個(gè)周期,總線(xiàn)仲裁器執行循環(huán)調度,以保證CPU至少可以得到一半的系統總線(xiàn)(存儲器或外設)帶寬。

在發(fā)生一個(gè)事件后,外設發(fā)送一個(gè)請求信號到DMA控制器。DMA控制器根據通道的優(yōu)先權處理請求。當DMA控制器開(kāi)始訪(fǎng)問(wèn)外設的時(shí)候,DMA控制器立即發(fā)送給外設一個(gè)應答信號。當從DMA控制器得到應答信號時(shí),外設立即釋放它的請求。一旦外設釋放了這個(gè)請求,DMA控制器同時(shí)撤銷(xiāo)應答信號。如果發(fā)生更多的請求時(shí),外設可以啟動(dòng)下次處理。

總之,每個(gè)DMA傳送由3個(gè)操作組成:

1. 從外設數據寄存器或者從DMA_CMARx寄存器指定地址的存儲器單元執行加載操作。

2. 存數據到外設數據寄存器或者存數據到DMA_CMARx寄存器指定地址的存儲器單元。

3. 執行一次DMA_CNDTRx寄存器的遞減操作。該寄存器包含未完成的操作數目。

仲裁器根據通道請求的優(yōu)先級來(lái)啟動(dòng)外設/存儲器的訪(fǎng)問(wèn)。優(yōu)先級分為兩個(gè)等級:軟件(4個(gè)等級:最高、高、中等、低)、硬件(有較低編號的通道比擁有較高編號的通道有較高的優(yōu)先權)。

可以在DMA傳輸過(guò)半、傳輸完成和傳輸錯誤時(shí)產(chǎn)生中斷。

STM32中DMA的不同中斷(傳輸完成、半傳輸、傳輸完成)通過(guò)“線(xiàn)或”方式連接至NVIC,需要在中斷例程中進(jìn)行判斷。

進(jìn)行DMA配置前,不要忘了在RCC設置中使能DMA時(shí)鐘。STM32的DMA控制器掛在A(yíng)HB總線(xiàn)上。

DMA總共有7個(gè)通道,各個(gè)通道的DMA映射關(guān)系如下:

外設的事件連接至相應DMA通道,每個(gè)通道均可以通過(guò)軟件觸發(fā)實(shí)現存儲器內部的DMA數據傳輸(M2M模式)

Tips:庫2.0中函數RCC_AHBPeriphClockCmd的參數由“RCC_AHBPeriph_DMA”改成“RCC_AHBPeriph_DMA1”(如果是DMA1控制器的話(huà))。

DMA的傳輸標志位(CHTIFx、CTCIFx、CGIFx)由硬件設置為“1”,但需要軟件清零,在中斷服務(wù)程序中清除。當CGIFx(全局中斷標志位)清零后,CHTIFx 和 CTCIFx均清零。

過(guò)程:怎樣啟用DMA?首先,眾所周知的是初始化,任何設備啟用前都要對其進(jìn)行初始化,要對模塊初始化,還要先了解該模塊相應的結構及其函數,以便正確的設置;由于DMA較為復雜,我就只談?wù)凞MA的基本結構和和常用函數,這些都是ST公司提供在庫函數中的。

1、 下面代碼是一個(gè)標準DMA設置,當然實(shí)際應用中可根據實(shí)際情況進(jìn)行裁減:

DMA_DeInit(DMA_Channel1);

上面這句是給DMA配置通道,根據ST提供的資料,STM3210Fx中DMA包含7個(gè)通道(CH1~CH7),也就是說(shuō)可以為外設或memory提供7座“橋梁”(請允許我使用橋梁一詞,我覺(jué)得更容易理解,,別“拍磚”呀?。?;

DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;

上面語(yǔ)句中的DMA_InitStructure是一個(gè)DMA結構體,在庫中有聲明了,當然使用時(shí)就要先定義了;DMA_PeripheralBaseAddr是該結構體中一個(gè)數據成員,給DMA一個(gè)起始地址,好比是一個(gè)buffer起始地址,數據流程是:外設寄存器à DMA_PeripheralBaseAddàmemory中變量空間(或flash中數據空間等),ADC1_DR_Address是我定義的一個(gè)地址變量;

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue;

上面這句很顯然是DMA要連接在Memory中變量的地址,ADC_ConvertedValue是我自己在memory中定義的一個(gè)變量;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

上面的這句是設置DMA的傳輸方向,就如前面我所說(shuō)的,DMA可以雙向傳輸,也可以單向傳輸,這里設置的是單向傳輸,如果需要雙向傳輸:把DMA_DIR_PeripheralSRC改成DMA_DIR_PeripheralDST即可。

DMA_InitStructure.DMA_BufferSize = 2;

上面的這句是設置DMA在傳輸時(shí)緩沖區的長(cháng)度,前面有定義過(guò)了buffer的起始地址:ADC1_DR_Address ,為了安全性和可靠性,一般需要給buffer定義一個(gè)儲存片區,這個(gè)參數的單位有三種類(lèi)型:Byte、HalfWord、word,我設置的2個(gè)half-word(見(jiàn)下面的設置);32位的MCU中1個(gè)half-word占16 bits。

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

上面的這句是設置DMA的外設遞增模式,如果DMA選用的通道(CHx)有多個(gè)外設連接,需要使用外設遞增模式:DMA_PeripheralInc_Enable;我的例子里DMA只與ADC1建立了聯(lián)系,所以選用DMA_PeripheralInc_Disable

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

上面的這句是設置DMA的內存遞增模式,DMA訪(fǎng)問(wèn)多個(gè)內存參數時(shí),需要使用DMA_MemoryInc_Enable,當DMA只訪(fǎng)問(wèn)一個(gè)內存參數時(shí),可設置成:DMA_MemoryInc_Disable。

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

上面的這句是設置DMA在訪(fǎng)問(wèn)時(shí)每次操作的數據長(cháng)度。有三種數據長(cháng)度類(lèi)型,前面已經(jīng)講過(guò)了,這里不在敘述。

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

與上面雷同。在此不再說(shuō)明。

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

上面的這句是設置DMA的傳輸模式:連續不斷的循環(huán)模式,若只想訪(fǎng)問(wèn)一次后就不要訪(fǎng)問(wèn)了(或按指令操作來(lái)反問(wèn),也就是想要它訪(fǎng)問(wèn)的時(shí)候就訪(fǎng)問(wèn),不要它訪(fǎng)問(wèn)的時(shí)候就停止),可以設置成通用模式: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個(gè)memory中的變量互相訪(fǎng)問(wèn)的

DMA_Init(DMA_Channel1,&DMA_InitStructure);

前面那些都是對DMA結構體成員的設置,在次再統一對DMA整個(gè)模塊做一次初始化,使得DMA各成員與上面的參數一致。

/*DMA Enable*/

DMA_Cmd(DMA_Channel1,ENABLE);

stm32使用DMA的相關(guān)操作:
1、DMA的配置
要配置的有DMA傳輸通道選擇,傳輸的成員和方向、普通模式還是循環(huán)模式等等。
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
//DMA設置:
//設置DMA源:內存地址&串口數據寄存器地址
//方向:內存-->外設
//每次傳輸位:8bit
//傳輸大小DMA_BufferSize=SENDBUFF_SIZE
//地址自增模式:外設地址不增,內存地址自增1
//DMA模式:一次傳輸,非循環(huán)
//優(yōu)先級:中
DMA_DeInit(DMA1_Channel4);//串口1的DMA傳輸通道是通道4
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralDST;//外設作為DMA的目的端
DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;//傳輸大小
DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable;//外設地址不增加
DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable;//內存地址自增1
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode =DMA_Mode_Circular;
//DMA_Mode_Normal(只傳送一次),DMA_Mode_Circular (不停地傳送)
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//(DMA傳送優(yōu)先級為中等)
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
}
注:
1、傳輸通道:通過(guò)查表,串口1的發(fā)送對應的是DMA的通道4,所以此處選擇通道4.
2、DMA傳輸方式:
(1) DMA_Mode_Normal,正常模式,當一次DMA數據傳輸完后,停止DMA傳送,對于上例而言,就是DMA_PeripheralDataSize_Byte個(gè)字節的傳送完成后,就停止傳送。
(2)DMA_Mode_Circular
循環(huán)模式,當傳輸完一次后,重新接著(zhù)傳送,永不停息。
2、外設的DMA方式設置
將串口1設置成DMA模式:
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
3、待傳輸數據的定義和初始化
#define SENDBUFF_SIZE 10240
vu8 SendBuff[SENDBUFF_SIZE];
for(i=0;i {
SendBuff[i] = i%10+0;
}
4、開(kāi)始DMA傳輸(使能對應的DMA通道)
DMA_Cmd(DMA1_Channel4, ENABLE);
5、DMA傳輸的完成
while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET)
{
LED_1_REV; //LED翻轉
Delay(); //浪費時(shí)間
}
當傳輸完成后,就會(huì )跳出上面的死循環(huán)。


關(guān)鍵詞: stm32DMA基本使

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>