STM32 DMA模塊的配置與使用
DMA有什么用?
直接存儲(chǔ)器存取用來(lái)提供在外設(shè)和存儲(chǔ)器之間或者存儲(chǔ)器和存儲(chǔ)器之間的高速數(shù)據(jù)傳輸。無(wú)須CPU的干預(yù),通過(guò)DMA數(shù)據(jù)可以快速地移動(dòng)。這就節(jié)省了CPU的資源來(lái)做其他操作。
有多少個(gè)DMA資源?
有兩個(gè)DMA控制器,DMA1有7個(gè)通道,DMA2有5個(gè)通道。
數(shù)據(jù)從什么地方送到什么地方?
外設(shè)到SRAM(I2C/UART等獲取數(shù)據(jù)并送入SRAM);
SRAM的兩個(gè)區(qū)域之間;
外設(shè)到外設(shè)(ADC讀取數(shù)據(jù)后送到TIM1控制其產(chǎn)生不同的PWM占空比);
SRAM到外設(shè)(SRAM中預(yù)先保存的數(shù)據(jù)送入DAC產(chǎn)生各種波形);
……還有一些目前還搞不清楚的。
DMA可以傳遞多少數(shù)據(jù)?
傳統(tǒng)的DMA的概念是用于大批量數(shù)據(jù)的傳輸,但是我理解,在STM32中,它的概念被擴(kuò)展了,也許更多的時(shí)候快速是其應(yīng)用的重點(diǎn)。數(shù)據(jù)可以從1~65535個(gè)。
直接存儲(chǔ)器存取(Direct Memory Access,DMA)是計(jì)算機(jī)科學(xué)中的一種內(nèi)存訪問(wèn)技術(shù)。它允許某些電腦內(nèi)部的硬體子系統(tǒng)(電腦外設(shè)),可以獨(dú)立地直接讀寫系統(tǒng)存儲(chǔ)器,而不需繞道 CPU。在同等程度的CPU負(fù)擔(dān)下,DMA是一種快速的數(shù)據(jù)傳送方式。它允許不同速度的硬件裝置來(lái)溝通,而不需要依于 CPU的大量中斷請(qǐng)求?!菊訵ikipedia】
現(xiàn)在越來(lái)越多的單片機(jī)采用DMA技術(shù),提供外設(shè)和存儲(chǔ)器之間或者存儲(chǔ)器之間的高速數(shù)據(jù)傳輸。當(dāng) CPU 初始化這個(gè)傳輸動(dòng)作,傳輸動(dòng)作本身是由DMA 控制器來(lái)實(shí)行和完成。STM32就有一個(gè)DMA控制器,它有7個(gè)通道,每個(gè)通道專門用來(lái)管理一個(gè)或多個(gè)外設(shè)對(duì)存儲(chǔ)器訪問(wèn)的請(qǐng)求,還有一個(gè)仲裁器來(lái)協(xié)調(diào)各個(gè)DMA請(qǐng)求的優(yōu)先權(quán)。
DMA 控制器和Cortex-M3核共享系統(tǒng)數(shù)據(jù)總線執(zhí)行直接存儲(chǔ)器數(shù)據(jù)傳輸。當(dāng)CPU和DMA同時(shí)訪問(wèn)相同的目標(biāo)(RAM或外設(shè))時(shí),DMA請(qǐng)求可能會(huì)停止 CPU訪問(wèn)系統(tǒng)總線達(dá)若干個(gè)周期,總線仲裁器執(zhí)行循環(huán)調(diào)度,以保證CPU至少可以得到一半的系統(tǒng)總線(存儲(chǔ)器或外設(shè))帶寬。
在發(fā)生一個(gè)事件后,外設(shè)發(fā)送一個(gè)請(qǐng)求信號(hào)到DMA控制器。DMA控制器根據(jù)通道的優(yōu)先權(quán)處理請(qǐng)求。當(dāng)DMA控制器開(kāi)始訪問(wèn)外設(shè)的時(shí)候,DMA控制器立即發(fā)送給外設(shè)一個(gè)應(yīng)答信號(hào)。當(dāng)從DMA控制器得到應(yīng)答信號(hào)時(shí),外設(shè)立即釋放它的請(qǐng)求。一旦外設(shè)釋放了這個(gè)請(qǐng)求,DMA控制器同時(shí)撤銷應(yīng)答信號(hào)。如果發(fā)生更多的請(qǐng)求時(shí),外設(shè)可以啟動(dòng)下次處理。
簡(jiǎn)單來(lái)說(shuō):
DMA,全稱為:Direct Memory Access,即直接存儲(chǔ)器訪問(wèn)。DMA傳輸方式無(wú)需CPU 直接控制傳輸,也沒(méi)有中斷處理方式那樣保留現(xiàn)場(chǎng)和恢復(fù)現(xiàn)場(chǎng)的過(guò)程,通過(guò)硬件為RAM 與I/O設(shè)備開(kāi)辟一條直接傳送數(shù)據(jù)的通路,能使CPU 的效率大為提高。
STM32中 DMA1有7個(gè)通道,DMA2有5個(gè)通道(DMA2 僅存在大容量產(chǎn)品中)。DMA掛載的時(shí)鐘為AHB總線,其時(shí)鐘為72Mhz,所以可以實(shí)現(xiàn)高速數(shù)據(jù)搬運(yùn)。
STM32F103RBT6 只有1 個(gè)DMA控制器,DMA1 ,下面我們就針對(duì)DMA1 進(jìn)行介紹。
從外設(shè)(TIMx、ADC、SPIx 、I2Cx 和USARTx )產(chǎn)生的DMA請(qǐng)求,通過(guò)邏輯或輸入到DMA控制器,這就意味著同時(shí)只能有一個(gè)請(qǐng)求有效。外設(shè)的DMA請(qǐng)求,可以通過(guò)設(shè)置相應(yīng)的外設(shè)寄存器中的控制位,被獨(dú)立地開(kāi)啟或關(guān)閉。
DMA1各通道一覽:
這里我們要使用的是串口 1 的 DMA 傳送,也就是要用到通道 4。
1、DMA的配置
要配置的有DMA傳輸通道選擇,傳輸?shù)某蓡T和方向、普通模式還是循環(huán)模式等等。
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
//DMA設(shè)置:
//設(shè)置DMA源:內(nèi)存地址&串口數(shù)據(jù)寄存器地址
//方向:內(nèi)存-->外設(shè)
//每次傳輸位:8bit
//傳輸大小DMA_BufferSize=SENDBUFF_SIZE
//地址自增模式:外設(shè)地址不增,內(nèi)存地址自增1
//DMA模式:一次傳輸,非循環(huán)
//優(yōu)先級(jí):中
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;//外設(shè)作為DMA的目的端
DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;//傳輸大小
DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable;//外設(shè)地址不增加
DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable;//內(nèi)存地址自增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)先級(jí)為中等)
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
}
注:
1、傳輸通道:通過(guò)查表,串口1的發(fā)送對(duì)應(yīng)的是DMA的通道4,所以此處選擇通道4.
2、DMA傳輸方式:
(1) DMA_Mode_Normal,正常模式,當(dāng)一次DMA數(shù)據(jù)傳輸完后,停止DMA傳送,對(duì)于上例而言,就是DMA_PeripheralDataSize_Byte個(gè)字節(jié)的傳送完成后,就停止傳送。
(2)DMA_Mode_Circular
循環(huán)模式,當(dāng)傳輸完一次后,重新接著傳送,永不停息。
2、外設(shè)的DMA方式設(shè)置
將串口1設(shè)置成DMA模式:
每一個(gè)外設(shè)都有一個(gè)類似以下的一個(gè)DMA調(diào)用函數(shù):xxx_DMACmd();
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);//發(fā)送就為USART_DMAReq_Tx;讀取就為USART_DMAReq_Rx
3、待傳輸數(shù)據(jù)的定義和初始化
#define SENDBUFF_SIZE 10240
vu8 SendBuff[SENDBUFF_SIZE];
for(i=0;i
SendBuff[i] = i%10+'0';
}
4、開(kāi)始DMA傳輸(使能對(duì)應(yīng)的DMA通道)
DMA_Cmd(DMA1_Channel4, ENABLE);
5、DMA傳輸?shù)耐瓿?/p>
while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET)
{
LED_1_REV; //LED翻轉(zhuǎn)
Delay(); //浪費(fèi)時(shí)間
}
當(dāng)傳輸完成后,就會(huì)跳出上面的死循環(huán)。
當(dāng)然,使用串口作為外設(shè)的時(shí)候,還需要對(duì)串口進(jìn)行初始化。





