I am working with a very old problem which is to convert ADC and send to UART via DMA. I am stuck at making the correct sampling time. What I had done so far is to configure TIMER2 and ADC. I Used ADC2 and TIMER2. Timer2 TRGO Update event is used to Trigger the ADC. Everything seems fine. ADC is converting the values and sending to USART is also working properly but the I set the Timer 2 interrupt to happen at every second. I also blinked the LED in interrupt Service Routine. The LED blinks at 2hz rate. But the ADC sampling seems faster then the LED Blinking rate. I also tried to change the Timer 2 interrupt rate by increasing and decreasing the counter values but it doesn't effect the ADC sampling rate. I think I am doing something wrong.
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
void init_ADC(void)
{
RCC->AHB1ENR|=RCC_AHB1ENR_GPIOCEN; //GPIOC clock enable
GPIOC->MODER|=(3u<<(2*0)); //ADC input pin is analogue mode
RCC->APB2ENR|=RCC_APB2ENR_ADC1EN; //ADC clock enable
ADC1->SQR1&=~ADC_SQR1_L; //set number of conversions per sequence to 1
ADC1->SQR3&=~ADC_SQR3_SQ1; //clear channel select bits
ADC1->SQR3|=10; //set channel
ADC1->CR1 &= ~ADC_CR1_SCAN; //SCAN mode disabled
ADC1->CR2 &= ~ADC_CR2_CONT; //Disable continuous conversion
ADC1->CR2 &= ~(1<<29);
ADC1->CR2 |= (1<<28); //Trigger on Rising edge
//External Event TIM2 TRGO
ADC1->CR2 &= ~(1<<3);
ADC1->CR2 |= (1<<2);
ADC1->CR2 |= (1<<1);
ADC1->CR2 &= ~(1<<0);
ADC1->SMPR1 |= ADC_SMPR1_SMP10;
ADC1->CR2|=ADC_CR2_ADON; //enable ADC
ADC1->CR2|=ADC_CR2_SWSTART;
}
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)
{
while((ADC1->SR&ADC_SR_EOC)==0){__NOP();}
unsigned int volts = ADC1->DR;
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?