STM32筆記(23):使用 ADC 及 DMA 多通道讀取電壓值(上)

DMA 是 Direct Memory Access 的簡稱,顧名思義是直接對記憶體進行存取,主要是將數據從一個地址空間複製到另一個地址空間,提供在外部設備和記憶體之間,或者是記憶體和記憶體之間進行高速數據傳輸,傳輸由 DMA 控制器來管理,不需佔用 CPU 的資源,即使在傳送數據時,CPU 仍可以繼續其他的工作。
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名稱說明
14MEM2MEM記憶體對記憶體存取模式0 表示停用
1 表示啟用
13:12PL[1:0]通道優先等級00: 低 Low
01: 中 Medium
10: 高 High
11: 非常高 Very high
11:10MSIZE[1:0]記憶體數據傳輸寬度00: 8-bits (Byte 位元組)
01: 16-bits (HalfWord 半字)
10: 32-bits (Word 全字)
11: Reserved 保留
9:8PSIZE[1:0]外設數據傳輸寬度00: 8-bits (Byte 位元組)
01: 16-bits (HalfWord 半字)
10: 32-bits (Word 全字)
11: Reserved 保留
6PINC外設增加模式0 表示停用,1 表示啟用。
5CIRC循環模式0 表示停用,1 表示啟用。
4DIR資料傳輸方向0 表示從外設讀取,1 表示從記憶體讀取。
3TEIE傳輸錯誤中斷0 表示停用,1 表示啟用。
2HTIE傳輸一半中斷0 表示停用,1 表示啟用。
1TCIE傳輸完成中斷0 表示停用,1 表示啟用。
0EN設定通道是否啟用?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:傳輸錯誤中斷
- 引數 NewState:啟用 ENABLE 或停用 DISABLE 指定的 DMA 中斷。

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 傳輸錯誤中斷
- 回傳值:DMAy_IT 的最新狀態,可以是 SET 或 RESET。

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 多通道讀取電壓值(下)

Post a Comment

較新的 較舊