cancel
Showing results for 
Search instead for 
Did you mean: 

ADC with external trigger source via a timer. STM32G431 with NUCLEO G431RB

MJo.4
Associate II

Hello guys, I'm new to the ST controllers. My question would be how can I initialize an ADC that is waiting for an external signal from a timer. I have initialized a timer interrupt that is triggered every 1 ms at 170 Mhz clock frequency. The timer also works, but there is no ADC conversion, the conversion should be triggered each time via a timer. I work with direct access to the registers without using the hal library because I want to save memory. I've looked through the St examples a bit, but they're all made with the HAL library. I want to use Timer 2 and ADC channel 0 on GPIOA PA0. The timer is only running, my ADC(adc_value is empty) is not working can someone help me with what I have initialized incorrectly here or what is still missing. Thanks for your help guys, I'll post the code here.

Kind regards, Markus

void initADC()
{
 
	// Enable ADC clock
	RCC->AHB2ENR |= RCC_AHB2ENR_ADC12EN;
 
	// Configure GPIO pin as analog input
	GPIOA->MODER |= (0b11<<(0 * 2U));
 
	// Disable ADC deep power-down mode and enable ADC voltage regulator
	ADC1->CR &= ~ADC_CR_DEEPPWD;
	ADC1->CR |= ADC_CR_ADVREGEN;
	
	//wait for voltage 2ms
    for(uint32_t i = 0;i < 340000;i++);		//170Mhz ->340000 2ms
 
    // Configure ADC trigger source and mode
    ADC1->CFGR |= (ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTSEL_0 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_3); // Trigger on rising edge + Trigger TIM2_TRGO
    ADC2->CFGR |= (ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTSEL_0 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_3); // Trigger on rising edge + Trigger TIM2_TRGO
 
    ADC1->SQR1 |= (ADC_SQR1_SQ1_0 | ADC_SQR1_L_0 );
 
	// Enable ADC
	ADC1->CR |= ADC_CR_ADEN;
	// Start ADC conversion on Timer 2 TRGO event
	ADC1->CR |= ADC_CR_ADSTART;
 
 
 
}
 
void initCPU_Timer1()
{
 
 
	  RCC->APB1ENR1 |= RCC_APB1ENR1_TIM2EN;
 
	  TIM2->PSC = 169; 
	  TIM2->ARR = 999;
	  TIM2->CR1 = TIM_CR1_ARPE | TIM_CR1_URS; 
	  TIM2->DIER = TIM_DIER_UIE; // Enable Interrupt
	  TIM2->EGR = TIM_EGR_UG; // Update Event 
 
	  TIM2->CR2 |= TIM_CR2_MMS_2;
 
	  // Interrupt-Config
	  NVIC_SetPriority(TIM2_IRQn, 0);
	  NVIC_EnableIRQ(TIM2_IRQn);     
	  // Timer-start
	  TIM2->CR1 |= TIM_CR1_CEN;
 
}
 
int main(void)
{
 
  HAL_Init();
 
  SystemClock_Config();
 
  initADC();
 
  initCPU_Timer1();
 
  while (1)
  {
 
  }
 
}
 
 
volatile uint16_t adc_value = 0;
 
void TIM2_IRQHandler(void)
{
    if (TIM2->SR & TIM_SR_UIF) // Timer Overflow Event
    {
        ADC1->CR |= ADC_CR_ADSTART; // start ADC
        TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Overflow Flag
 
  	  adc_value = ADC1->DR;
 
    }
 
}

10 REPLIES 10
Kamil Duljas
Senior III

Hmmm in timer handler you start adc again before read data from DR register ​

Dudo
MJo.4
Associate II

Hello Kamil,

i removed line 79 from my timer handler but it doesn't work. I dont know whats wrong there no ADC conversion.

Remove or move as last?​

Dudo
MJo.4
Associate II

I tried both but without success. The timer handler works. Only no conversion is carried out. I think it's up to the ADC configuration, because if I just want to initialize the ADC and then set a software trigger, no conversion works for me either. I don't know how to properly configure the ADC.

MJo.4
Associate II

do you have an example code how i have to configure the adc? I can't find any sample code with direct access to the registers on the STM controller

You must wait for ADRDY flag after enable ADC. Its mandatory. This flag is ADC_ISR register ​

Dudo

After line ​24

Dudo

Look at this:

​ /* Set timer the trigger output (TRGO) */

LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_UPDATE)

Need set trigger ​output in your timer.

Dudo