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