====== 13. DMA ======
===== Cíle cvičení =====
- 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í =====
{{ :courses:b2m37mam:labs:stm32f401re.pdf | Datasheet STM32F401 }}
{{ :courses:b2m37mam:stm32f401_refmanual.pdf | Referenční manuál STM32F401 }}
{{ :courses:b2m37mam:nucleo_64_pins.pdf | Datasheet Nucleo F401RE}}
[[courses:b2m37mam:tutorials:dev_kits:nucleof401| 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;
}
}
}