Table of Contents

13. DMA

Cíle cvičení

  1. Seznámit se s konfigurací přímého přístupu do paměti (Direct Memory Access - DMA), který bude ukládat data z AD převodníku do paměti bez zásahu programu

Co je třeba si připravit

Podklady pro cvičení

Datasheet STM32F401

Referenční manuál STM32F401

Datasheet Nucleo F401RE

Podklady pro Nucleo STM32F401

Projekty

Kódy pro cvičení

Inicializace DMA s TIM2

uint16_t ADC1_DMA_Result;
 
void initADC1_DMA(void){
	RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
 
	ADC1->CR2   |= ADC_CR2_ADON;		                        // povoleni ADC
	ADC1->SQR3  |= 0 << ADC_SQR3_SQ1_Pos;		                // vyber CH0 do sekvence SQ0
	ADC1->SMPR2 |= 7 << ADC_SMPR2_SMP0_Pos;		                // nastaveni prevodu CH0 na 480 cyklu
	ADC1->CR2   |= 0x06 << ADC_CR2_EXTSEL_Pos;	                // zdrojem udalosti je TIM2 TRGO
	ADC1->CR2   |= 0x01 << ADC_CR2_EXTEN_Pos;	                // reakce event triggeru na nabeznou hranu
 
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
	GPIOA->MODER |= GPIO_MODE_ANALOG << GPIO_MODER_MODE0_Pos;	// Nastaveni PA0 na analogovy mod
 
	// DMA cast nastaveni
	ADC1->CR2 |= ADC_CR2_DMA;					// povoleni ADC pro DMA prenos
	//ADC1->CR2 |= ADC_CR2_CONT;					// povoleni kontinualniho rezimu
	ADC1->CR2 |= ADC_CR2_DDS;					// povoleni dalsich DMA pozadavku
	RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;				// povoleni hodin do DMA2
 
 
	DMA2_Stream0->CR = (0x00 << DMA_SxCR_CHSEL_Pos); 	        // vyber kanalu CH0 jako zdroj DMA pozadavku
	DMA2_Stream0->CR |= 0x01 << DMA_SxCR_MSIZE_Pos;		        // nastaveni velikosti dat v pameti bude 16 bitu
	DMA2_Stream0->CR |= 0x01 << DMA_SxCR_PSIZE_Pos;		        // nastaveni velikosti dat periferie na 16 bitu
	DMA2_Stream0->CR |= DMA_SxCR_CIRC;				// nastaveni DMA na kruhovy rezim
	DMA2_Stream0->CR |= (0x00 << DMA_SxCR_DIR_Pos);		        // nastaveni smeru toku dat P->M
	DMA2_Stream0->NDTR = 1;						// velikost bufferu dat
 
	DMA2_Stream0->M0AR = &ADC1_DMA_Result;				// adresa pro ulozeni dat z DMA (do pameti)
	DMA2_Stream0->PAR  = &ADC1->DR;					// adresa zdroje dat pro DMA (z periferie)
 
	DMA2_Stream0->CR |= DMA_SxCR_EN;				// spusteni DMA
 
	//ADC1->CR2 |= ADC_CR2_SWSTART;					// spusteni A/D prevodniku
}

Inicializace TIM2

void initTIM2forADC(void){
	RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;	// povoleni hodin do bloku TIM2
 
	TIM2->PSC = 16000;
	TIM2->ARR = 1000;
	TIM2->CR2 |= 0x02 << TIM_CR2_MMS_Pos;	// Preteceni jako spoustec 
	TIM2->CR1 |= TIM_CR1_CEN;		// povolime casovac TIM2
}

Hlaní program

int main(void){
 
  initADC1_DMA();
  initTIM2forADC(); 
 
  while (1){
	  if(DMA2->LISR & DMA_LISR_TCIF0){
		  DMA2->LIFCR |= DMA_LIFCR_CTCIF0;
		  // zpracovani dat - data jsou ulozena v promenne ADC1_DMA_Result;
	  }
  }
}