DMA 是 Direct Memory Access 的簡稱,顧名思義是直接對記憶體進行存取,主要是將數據從一個地址空間複製到另一個地址空間,提供在外部設備和記憶體之間,或者是記憶體和記憶體之間進行高速數據傳輸,傳輸由 DMA 控制器來管理,不需佔用 CPU 的資源,即使在傳送數據時,CPU 仍可以繼續其他的工作。
STM32F1 有兩個 DMA 控制器,DMA1 有 7 個通道,DMA2 有 5 個,共有 12 個獨立可配置的通道(請求)。每個通道用來管理一或多個外設對記憶體的請求,且有一個仲裁器(Arbiter)來協調各 DMA 間的優先權。其他特性還包括:
DMA 控制器獨立於內核,屬於一個單獨的外設,結構比較簡單,從編程的角度來看,我們只需掌握結構框圖中的三部分內容即可。如圖所示(大家也可以查看《STM32F10x中文參考手冊》-10 DMA 控制器(DMA)章節內容)。
① DMA 請求:如果外部設備想通過 DMA 來傳輸數據,必須先給 DMA 控制器發送 DMA 請求,DMA 收到後,控制器會給外設一個應答信號,當外設應答且 DMA 控制器收到應答信號後,就會啟動 DMA 的傳輸,直到傳輸完畢。
不同的 DMA 控制器的通道對應著不同的外設請求,從 DMA 請求對照圖中可以知道各通道所對應的外設請求,下圖分別是 DMA1 和 DMA2 請求對照圖:
② Arbiter 仲裁器:當多個 DMA 通道提出請求時,就交由仲裁器管理先後處理順序的問題,仲裁器管理 DMA 通道請求分為兩個階段:
第一階段由 DMA_CCRx 暫存器中值來決定,比較 4 個等級:非常高、高、中和低四個優先級。第二階段由比較通道編號,當兩個或以上的 DMA 通道請求的優先級一樣時,會取決於通道編號,編號越低優先權越高,比如通道 0 高於通道1。在大容量產品和互聯型產品中,DMA1 控制器高於 DMA2 控制器的優先級。
③ DAM 通道:DMA1 有7 個通道,DMA2 有 5 個通道,每個通道對應不同的外設的 DMA 請求。但是同一時間只能接收一個請求。
DMA 通道有一個設定暫存器(configuration register)用來設定 DMA 的環境:DMA_CCRx(x = 1…7),代表 7 個通道。
將 DMA 設定為預設值。
- 引數 DMAy_Channelx 是 DMA 通道。y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。例如:DMA2_Channel3。
✈ void DMA_Init(DMA_Channel_TypeDef *DMAy_Channelx, DMA_InitTypeDef *DMA_InitStruct)
對 DMA 進行初始化,定義在標準函式庫的 stm32f10x_dma.h 文件中,需先定義並填入一個 DMA_InitTypeDef 類型的結構體。
- 引數 DMAy_Channelx 是 DMA 通道。y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。例如:DMA2_Channel3。
✈ void DMA_Cmd(DMA_Channel_TypeDef *DMAy_Channelx, FunctionalState NewState)
啟用或停用指定的 DMA 通道。
- 引數 DMAy_Channelx 是 DMA 通道。y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。例如:DMA2_Channel3。
- 引數 NewState:設定為啟用 ENABLE 或停用 DISABLE。
✈ void DMA_ClearFlag(uint32_t DMAy_FLAG)
清除 DMAy 通道的旗幟。
- 引數 DMAy_FLAG:是 DMA 通道。以下內容 y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。例如:DMA2_Channel3。
✈ void DMA_ITConfig(DMA_Channel_TypeDef *DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState)
啟用或停用指定的 DMA 通道中斷。
- 引數 DMAy_Channelx:是 DMA 通道。y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。例如:DMA2_Channel3。
- 引數 DMA_IT:指定要啟用或停用的 DMA 中斷源。可以是以下值:
✈ ITStatus DMA_GetITStatus(uint32_t DMAy_IT)
檢查指定的 DMA 通道是否發生中斷。
- 引數 DMAy_IT:檢查中斷的狀態,以下內容 y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。
✈ void ADC_DMACmd(ADC_TypeDef *ADCx, FunctionalState NewState)
啟動或停用指定的 ADC DMA 要求。
- 引數 ADCx:x 可以是 1 或 3 來選擇 ADC 外設。註:ADC2 不具備 DMA 能力。
- 引數 NewState:啟動 ENABLE 或停用 DISABLE 選定的 ADC 對 DMA 的傳送。
上述指令是將外設啟用或停用 DMA 的要求,除了本篇實做的 ADC 外,還有 USART、I2C、TIM 等幾種外設使用 DMA 紀錄讀取值,之後再找時間來試看看各項外設使用 DMA 的功能。
下一篇:STM32筆記(23):使用 ADC 及 DMA 多通道讀取電壓值(下)
STM32F1 有兩個 DMA 控制器,DMA1 有 7 個通道,DMA2 有 5 個,共有 12 個獨立可配置的通道(請求)。每個通道用來管理一或多個外設對記憶體的請求,且有一個仲裁器(Arbiter)來協調各 DMA 間的優先權。其他特性還包括:
- 支援迴圈的緩衝器管理。
- 快閃記憶體、SRAM、外設的 SRAM 、APB1、APB2 和 AHB 外設均可作為存取的來源和目標。
- 可程式設定請求的優先權(共有四級:VeryHigh、High、Medium 和 Low),如果優先權相等時,由硬體通道決定(數字越小,優先序越高,請求 0 優先於請求 1) 。
- 可設定 3 種來源和目標資料區的傳輸寬度(Byte 位元組、HalfWord 半字、Word 全字),來源和目標的傳輸寬度可以不同,英文手冊表76(頁279)有不同寬度的資料傳輸方式。
- 每個通道都有 3 個事件標誌:半傳輸(Half Transfer,HE)、傳輸完成(Transfer Complete,TC) 及傳輸出錯(Transfer Error,TE)。
- 可程式控制資料傳輸數目,資料可以從 1~65535 個。
[DMA方框圖]
DMA 控制器獨立於內核,屬於一個單獨的外設,結構比較簡單,只需掌握結構框圖中的三部分內容即可,如下圖(也可參考《STM32F10x Reference manual》-13 DMA 控制器)。DMA 控制器獨立於內核,屬於一個單獨的外設,結構比較簡單,從編程的角度來看,我們只需掌握結構框圖中的三部分內容即可。如圖所示(大家也可以查看《STM32F10x中文參考手冊》-10 DMA 控制器(DMA)章節內容)。
① DMA 請求:如果外部設備想通過 DMA 來傳輸數據,必須先給 DMA 控制器發送 DMA 請求,DMA 收到後,控制器會給外設一個應答信號,當外設應答且 DMA 控制器收到應答信號後,就會啟動 DMA 的傳輸,直到傳輸完畢。
不同的 DMA 控制器的通道對應著不同的外設請求,從 DMA 請求對照圖中可以知道各通道所對應的外設請求,下圖分別是 DMA1 和 DMA2 請求對照圖:
② Arbiter 仲裁器:當多個 DMA 通道提出請求時,就交由仲裁器管理先後處理順序的問題,仲裁器管理 DMA 通道請求分為兩個階段:
第一階段由 DMA_CCRx 暫存器中值來決定,比較 4 個等級:非常高、高、中和低四個優先級。第二階段由比較通道編號,當兩個或以上的 DMA 通道請求的優先級一樣時,會取決於通道編號,編號越低優先權越高,比如通道 0 高於通道1。在大容量產品和互聯型產品中,DMA1 控制器高於 DMA2 控制器的優先級。
③ DAM 通道:DMA1 有7 個通道,DMA2 有 5 個通道,每個通道對應不同的外設的 DMA 請求。但是同一時間只能接收一個請求。
DMA 通道有一個設定暫存器(configuration register)用來設定 DMA 的環境:DMA_CCRx(x = 1…7),代表 7 個通道。
位元Bits | 名稱 | 說明 | 值 |
---|---|---|---|
14 | MEM2MEM | 記憶體對記憶體存取模式 | 0 表示停用 1 表示啟用 |
13:12 | PL[1:0] | 通道優先等級 | 00: 低 Low 01: 中 Medium 10: 高 High 11: 非常高 Very high |
11:10 | MSIZE[1:0] | 記憶體數據傳輸寬度 | 00: 8-bits (Byte 位元組) 01: 16-bits (HalfWord 半字) 10: 32-bits (Word 全字) 11: Reserved 保留 |
9:8 | PSIZE[1:0] | 外設數據傳輸寬度 | 00: 8-bits (Byte 位元組) 01: 16-bits (HalfWord 半字) 10: 32-bits (Word 全字) 11: Reserved 保留 |
6 | PINC | 外設增加模式 | 0 表示停用,1 表示啟用。 |
5 | CIRC | 循環模式 | 0 表示停用,1 表示啟用。 |
4 | DIR | 資料傳輸方向 | 0 表示從外設讀取,1 表示從記憶體讀取。 |
3 | TEIE | 傳輸錯誤中斷 | 0 表示停用,1 表示啟用。 |
2 | HTIE | 傳輸一半中斷 | 0 表示停用,1 表示啟用。 |
1 | TCIE | 傳輸完成中斷 | 0 表示停用,1 表示啟用。 |
0 | EN | 設定通道是否啟用? | 0 表示通道停用,1 表示通道啟用。 |
[DMA常用函式]
✈ void DMA_DeInit (DMA_Channel_TypeDef *DMAy_Channelx)將 DMA 設定為預設值。
- 引數 DMAy_Channelx 是 DMA 通道。y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。例如:DMA2_Channel3。
✈ void DMA_Init(DMA_Channel_TypeDef *DMAy_Channelx, DMA_InitTypeDef *DMA_InitStruct)
對 DMA 進行初始化,定義在標準函式庫的 stm32f10x_dma.h 文件中,需先定義並填入一個 DMA_InitTypeDef 類型的結構體。
- 引數 DMAy_Channelx 是 DMA 通道。y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。例如:DMA2_Channel3。
DMA_InitTypeDef DMA_InitStructure;DMA_InitStructure 這個結構體有以下 11 個引數:
引數名稱 | 說明 |
---|---|
DMA_InitStructure.DMA_PeripheralBaseAddr = par; | DMA 外設地址。 |
DMA_InitStructure.DMA_MemoryBaseAddr = mar; | 指定記憶體地址給 DMA 通道。 |
DMA_InitStructure.DMA_DIR = xxx; | 指定傳輸方向,記憶體到外設模式是來源或目的,可以設定為 DMA_DIR_PeripheralDST 或 DMA_DIR_PeripheralSRC |
DMA_InitStructure.DMA_BufferSize = ndtr; | 設定資料傳輸量,可以依傳送方向設定是否與 DMA_PeripheralDataSize 或 DMA_MemoryDataSize相同的設定 |
DMA_InitStructure.DMA_PeripheralInc = xxx; | 外設非增量模式,可以設定為 DMA_PeripheralInc_Enable 或 DMA_PeripheralInc_Disable |
DMA_InitStructure.DMA_MemoryInc = xxx; | 指定記憶體增量模式,xxx 可以設定為啟用 DMA_MemoryInc_Enable 或停用 DMA_MemoryInc_Disable。 |
DMA_InitStructure.DMA_PeripheralDataSize = xxx; | 指定外設資料寬度,xxx 可以是以下幾種: DMA_PeripheralDataSize_Byte DMA_PeripheralDataSize_HalfWord DMA_PeripheralDataSize_Word |
DMA_InitStructure.DMA_MemoryDataSize = xxx; | 設定記憶體資料寬度,xxx 可以是以下幾種: DMA_MemoryDataSize_Byte DMA_MemoryDataSize_HalfWord DMA_MemoryDataSize_Word |
DMA_InitStructure.DMA_Mode = xxx; | 指定 DMA 通道的運作模式,xxx 可以是 DMA_Mode_Circular 或 DMA_Mode_Norma |
DMA_InitStructure.DMA_Priority = xxx; | 指定 DMA 通道的軟體優先順序,xxx 可以是以下 4 種: DMA_Priority_VeryHigh DMA_Priority_High DMA_Priority_Medium DMA_Priority_Low |
DMA_InitStructure.DMA_M2M = xxx; | 指定 DMA 通道是否可用記憶體對記憶體傳輸,xxx 可以設定為啟用 DMA_M2M_Enable 或停用 DMA_M2M_Disable |
✈ void DMA_Cmd(DMA_Channel_TypeDef *DMAy_Channelx, FunctionalState NewState)
啟用或停用指定的 DMA 通道。
- 引數 DMAy_Channelx 是 DMA 通道。y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。例如:DMA2_Channel3。
- 引數 NewState:設定為啟用 ENABLE 或停用 DISABLE。
✈ void DMA_ClearFlag(uint32_t DMAy_FLAG)
清除 DMAy 通道的旗幟。
- 引數 DMAy_FLAG:是 DMA 通道。以下內容 y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。例如:DMA2_Channel3。
- DMAy_FLAG_GLx:DMAy 通道 x 的全部旗幟
- DMAy_FLAG_TCx:DMAy 通道 x 傳輸完成旗幟
- DMAy_FLAG_HTx:DMAy 通道 x 傳輸一半旗幟
- DMAy_FLAG_TEx:DMAy 通道 x 傳輸錯誤旗幟
✈ void DMA_ITConfig(DMA_Channel_TypeDef *DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState)
啟用或停用指定的 DMA 通道中斷。
- 引數 DMAy_Channelx:是 DMA 通道。y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。例如:DMA2_Channel3。
- 引數 DMA_IT:指定要啟用或停用的 DMA 中斷源。可以是以下值:
- DMA_IT_TC:傳輸完成中斷
- DMA_IT_HT:傳輸一半中斷
- DMA_IT_TE:傳輸錯誤中斷
✈ ITStatus DMA_GetITStatus(uint32_t DMAy_IT)
檢查指定的 DMA 通道是否發生中斷。
- 引數 DMAy_IT:檢查中斷的狀態,以下內容 y 可以是 1 或 2,代表 DMA1 或 DMA2 ,設定 DMA1 時,x 值可以是 1~7 ,設定 DMA2 時,x 值可以是 1~5。
- DMAy_IT_GLx:DMAy 通道 x 的全部中斷
- DMAy_IT_TCx:DMAy 通道 x 傳輸完成中斷
- DMAy_IT_HTx:DMAy 通道 x 傳輸一半中斷
- DMAy_IT_TEx:DMAy 通道 x 傳輸錯誤中斷
✈ void ADC_DMACmd(ADC_TypeDef *ADCx, FunctionalState NewState)
啟動或停用指定的 ADC DMA 要求。
- 引數 ADCx:x 可以是 1 或 3 來選擇 ADC 外設。註:ADC2 不具備 DMA 能力。
- 引數 NewState:啟動 ENABLE 或停用 DISABLE 選定的 ADC 對 DMA 的傳送。
上述指令是將外設啟用或停用 DMA 的要求,除了本篇實做的 ADC 外,還有 USART、I2C、TIM 等幾種外設使用 DMA 紀錄讀取值,之後再找時間來試看看各項外設使用 DMA 的功能。
- void USART_DMACmd(USART_TypeDef *USARTx, uint16_t USART_DMAReq, FunctionalState NewState)
- void I2C_DMACmd(I2C_TypeDef *I2Cx, FunctionalState NewState)
- void SPI_I2S_DMACmd(SPI_TypeDef *SPIx, uint16_t SPI_I2S_DMAReq,FunctionalState NewState)
- void TIM_DMACmd(TIM_TypeDef *TIMx, uint16_t TIM_DMASource, FunctionalState NewState)
下一篇:STM32筆記(23):使用 ADC 及 DMA 多通道讀取電壓值(下)
張貼留言