stm32學習筆記 F1系列DMA

DMA 全稱Direct Memory Access,即直接存儲器訪問。
DMA傳輸將數據從一個地址空間複製到另一個地址空間。當CPU初始化這個傳輸動作,傳輸動作本身是由DMA控制器來實現和完成的。
DMA傳輸方式無需CPU直接控制傳輸,也沒有中斷處理方式那樣保留現場和恢復現場過程,通過硬件爲RAM和IO設備開闢一條直接傳輸數據的通道,使得CPU的效率大大提高。
DMA作用:爲CPU減負。
STM32最多有2個DMA控制器(DMA2僅存在大容量產品中),DMA1有7個通道。DMA2有5個通道。每個通道專門用來管理來自於一個或多個外設對存儲器訪問的請求。還有一個仲裁起來協調各個DMA請求的優先權。

STM32的DMA有以下一些特性: 
①每個通道都直接連接專用的硬件DMA請求,都支持軟件觸發,這些通過軟件來配置。
②在七個請求間的優先權可以通過軟件編程設置(共有四級:很高、高、中等和低),假如在相等優先權時由硬件決定(請求0優先於請求1,依此類推) 。 
③ 獨立的源和目標數據區的傳輸寬度(字節、半字、全字),模擬打包和拆包的過程。源    和目標地址必須按數據傳輸寬度對齊。 
④ 支持循環的緩衝器管理 
⑤ 每個通道都有3個事件標誌(DMA 半傳輸,DMA傳輸完成和DMA傳輸出錯),這3個事件標誌邏輯或成爲一個單獨的中斷請求。 
⑥ 外設和存儲器,存儲器和外設的傳輸 ,存儲器和存儲器間的傳輸
⑦ 閃存、SRAM、外設的SRAM、APB1 APB2和AHB外設均可作爲訪問的源和目標。 
⑧ 可編程的數據傳輸數目:最大爲65536
從外設(TIMx、ADC、SPIx、I2Cx 和 USARTx)產生的 DMA 請求,通過邏輯或輸入到DMA 控制器,這就意味着同時只能有一個請求有效。外設的 DMA 請求,可以通過設置相應的外設寄存器中的控制位,被獨立地開啓或關閉。

下面是配置DMA通道x的過程(x代表通道號):
1. 在DMA_CPARx寄存器中設置外設寄存器的地址。發生外設數據傳輸請求時,這個地址將是數據傳輸的源或目標。
2. 在DMA_CMARx寄存器中設置數據存儲器的地址。發生外設數據傳輸請求時,傳輸的數據將從這個地址讀出或寫入這個地址。
3. 在DMA_CNDTRx寄存器中設置要傳輸的數據量。在每個數據傳輸後,這個數值遞減。
4. 在DMA_CCRx寄存器的PL[1:0]位中設置通道的優先級。
5. 在DMA_CCRx寄存器中設置數據傳輸的方向、循環模式、外設和存儲器的增量模式、外設和存儲器的數據寬度、傳輸一半產生中斷或傳輸完成產生中斷。
6. 設置DMA_CCRx寄存器的ENABLE位,啓動該通道。
一旦啓動了DMA通道,它既可響應連到該通道上的外設的DMA請求。當傳輸一半的數據後,半傳輸標誌(HTIF)被置1,當設置了允許半傳輸中斷位(HTIE)時,將產生一箇中斷請求。在數據傳輸結束後,傳輸完成標誌(TCIF)被置1,當設置了允許傳輸完成中斷位(TCIE)時,將產生一箇中斷請求。


常用的外設DMA使能庫函數
void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq,FunctionalState NewState);
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState);
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void SDIO_DMACmd(FunctionalState NewState);
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq,FunctionalState NewState);
void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase,uint16_t TIM_DMABurstLength)

void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource,FunctionalState NewState);


常用的DMA庫函數

void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx,DMA_InitTypeDef* DMA_InitStruct)


typedef struct
{
  uint32_t DMA_PeripheralBaseAddr; //外設基地址
  uint32_t DMA_MemoryBaseAddr; //存儲器基地址
  uint32_t DMA_DIR;         //數據傳輸方向
  uint32_t DMA_BufferSize;  //通道傳輸數據量
  uint32_t DMA_PeripheralInc;//外設增量模式
  uint32_t DMA_MemoryInc;  //存儲器增量模式
  uint32_t DMA_PeripheralDataSize; //外設數據寬度
  uint32_t DMA_MemoryDataSize; //存儲器數據寬度
  uint32_t DMA_Mode;  //模式:是否循環
  uint32_t DMA_Priority; //優先級
  uint32_t DMA_M2M;    //是否存儲器到存儲器方式     

}DMA_InitTypeDef;


void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx,FunctionalState NewState);

void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx,uint32_t DMA_IT, FunctionalState NewState);

void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx,uint16_t DataNumber); 

uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);

FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);

void DMA_ClearFlag(uint32_t DMAy_FLAG);

ITStatus DMA_GetITStatus(uint32_t DMAy_IT);

void DMA_ClearITPendingBit(uint32_t DMAy_IT);


DMA配置程序過程
① 使能DMA時鐘
   RCC_AHBPeriphClockCmd();
② 初始化DMA通道參數
   DMA_Init();
③使能串口DMA發送,串口DMA使能函數:
   USART_DMACmd();
④使能DMA1通道,啓動傳輸。
   DMA_Cmd();
⑤查詢DMA傳輸狀態
  DMA_GetFlagStatus();
⑥獲取/設置通道當前剩餘數據量:
  DMA_GetCurrDataCounter();
  DMA_SetCurrDataCounter();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章