You're likely configuring your external trigger in the ADC wrong: //External Event TIM2 TRGO ADC1->CR2 &= ~(1<<3); ADC1->CR2 |= (1<<2); ADC1->CR2 |= (1<<1); ADC1->CR2 &= ~(1<<0); The bit positions are 24-27. I'd like to recommend using the processor defines to prevent such mistakes: //External Event TIM2 TRGO const uint32_t TIM2_TRGO = ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1; // 0110 ADC1->CR2 &= ~(ADC_CR2_EXTSEL); // remove all selections ADC1->CR2 |= TIM2_TRGO; ---------- I'm not very familiar with online courses, the reference manual did a good job providing all the info I needed to get DMA working as well. There is often a section about DMA for each peripheral and then there is the chapter about the whole DMA controller. It's easiest if you work with same width transfers at first, so if you need bytes in the peripheral use a byte array in the memory. Often it goes something like this: - Configure the channel to the correct peripheral source (different DMA channels or streams can only be connected to certain peripherals). - Set the correct peripheral address (data register), peripheral size, memory address and memory size. Set the correct direction (transfer from or to the peripheral) - Set if the memory or peripheral address shall be incremented with each transfer (usually memory yes and peripheral no for an array in memory) - Set the number of transfers - enable the DMA channel - enable the DMA request generation in the peripheral If you get that working (like have 10 samples of the ADC in an 16 bit array) you can try out different things like a circular buffer with the DMA or different sizes, get the data from ADC directly in 32 bit wide arrays. Stuff like that.