# STM32F4 Discovery ADC trigger using Timer 2 and DMA | CMSIS Core

Here is the Timer configuration which I am doing for STM32F407 board at 168Mhz Clock

void TIM2_Configuration(void){
// enable TIM2 clock (bit0)
RCC->APB1ENR |= (1 << 0);
//TIM2->PSC = 1749; //FOR DISCOVERY
//TIM2->PSC = 1874; //FOR NECLUEO

TIM2->PSC = 8399;   //For 84Mhz
TIM2->ARR = 10000; //it will get one second delay

/* Reset the MMS Bits */
TIM2->CR2 &= (uint16_t)~TIM_CR2_MMS;
/* Select the TRGO source */
TIM2->CR2 |=  TIM_CR2_MMS_1; //UPDATE EVENT

// Update Interrupt Enable
TIM2->DIER |= (1 << 0);

// enable TIM2 IRQ from NVIC
NVIC_EnableIRQ(TIM2_IRQn);

// Enable Timer 2 module (CEN, bit0)
TIM2->CR1 |= (1 << 0);

}



and this is how I am configuring my ADC


{
RCC->AHB1ENR|=RCC_AHB1ENR_GPIOCEN;  //GPIOC clock enable
GPIOC->MODER|=(3u<<(2*0));  //ADC input pin is analogue mode

ADC1->CR2 |= (1<<28);   //Trigger on Rising edge

//External Event TIM2 TRGO

}


This is how I am doing in IRQ for TIMER 2 which is also working fine

void TIM2_IRQHandler(void)
{

// clear interrupt status
if (TIM2->DIER & 0x01) {
if (TIM2->SR & 0x01) {
TIM2->SR &= ~(1U << 0);
}
}

GPIOD->ODR ^= (1 << 13);

}



and Here in the main while(True) loop I read and send data to usart like this

  while(1)
{

uart_tx(((volts/10000)%10)+48);
uart_tx(((volts/1000)%10)+48);
uart_tx(((volts/100)%10)+48);
uart_tx(((volts/10)%10)+48);
uart_tx(((volts)%10)+48);
uart_tx('\r');
uart_tx('\n');
// slow down
//
delay(300);

}


I am not sure why it is sampling so fast instead of the same rate which happens for the LED at GPIOD-13.

Also I am totally blank about the DMA. I had gone trough the HAL libraries but I am not sure how to test and proceed toward DMA direction from this point. Any guidance or helping material is highly appreciated. I also didn't find any source of help other than the reference manual and the Datasheet. Which although is pretty explainetry but didn't seems friendly to me.

Is there any tutorial series over internet which deals with CMSIS at this advance level (like handling DMAs and multiple interrupts)? I had seen few tutorials but they only deal with little peripherals. Not joining two or more peripherals together like I am doing by using TIMER ADC , DMA and USART together?

• CMSIS only helps with core peripherals not with peripherals from the chip vendor, so there is no coverage of DMA, ADC or interrupts (other then the NVIC). Aug 12, 2020 at 15:09
• Running just the timer numbers: you get a 500 ms update event with 168 MHz. It's a bit hard to diagnose what's wrong if you say "it seems faster", can you be more precise? Like take an actual time measurement between UART outputs for each sample. I've done something similar (trigger DAC with timer (which gets data from DMA) which triggers ADC (which transfers data with DMA)) and it worked like expected. Aug 12, 2020 at 15:17

//External Event TIM2 TRGO


The bit positions are 24-27. I'd like to recommend using the processor defines to prevent such mistakes:

//External Event 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.

• Wow.. Thanks! That works perfectly as expected. Yes, I just miss understood the bit 3:0 number this way. And Now I checked again, The way I was doing actually makes continuous conversions that's why I was seeing the conversions that fast. Now I will try the DMA, Thanks Again. Aug 12, 2020 at 15:54