AnsweredAssumed Answered

STM32F0 ADC Timer Triggered conversion hangs

Question asked by vanoverschelde.b.003 on Nov 3, 2016
Latest reply on Nov 3, 2016 by Clive One
Hello

I am trying to use TIM3 update event to trigger ADC to convert one channel 1000 times @ 50kHz resulting in about 20ms. This is for filtering out net interference.
The problem is when I configure the timer with a frequency of > 10kHz, after several conversions the ADC hangs waiting for EOC bit to be set. sampleADC() is called every 250ms. I disabled interrupts when converting to be sure its not an IRQ related problem. My uC runs at 8MHz,

/* ADC INIT FUNCTION */
void RWA_ADC_Init(uint16_t Gpio_Pins, uint8_t TimerTrigger){
    GPIO_InitTypeDef GPIO_InitStruct;
    /* peripheral clock enable */
    RCC->AHBENR |= (RCC_AHBENR_GPIOAEN);
     
    /*Configure GPIO pins*/
  GPIO_InitStruct.Pin = Gpio_Pins;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
     
    /* Peripheral clock enable */
    RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN);
     
    ADC1->CR |= ADC_CR_ADEN; // enable adc
    ADC1->CFGR1 |= ADC_CFGR1_DISCEN;// | ADC_CFGR1_WAIT;
    if(TimerTrigger)
        ADC1->CFGR1 |= ADC_CFGR1_EXTEN_0 | ADC_CFGR1_EXTSEL_0 | ADC_CFGR1_EXTSEL_1 | ADC_CFGR1_OVRMOD;
    ADC1->SMPR = ADC_SMPR1_SMPR_0 | ADC_SMPR1_SMPR_2;
     
    ADC1->CR |= ADC_CR_ADDIS;       //disable adc
    while(ADC1->CR & ADC_CR_ADEN);
    RWA_ADC_Calibrate();
     
}
 
/* TIM3 INIT FUNCTION */
void RWA_ADC_TIM_Init(uint16_t Period, uint8_t Prescaler){
    TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
 
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = Prescaler;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = Period-1;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim3.Init.RepetitionCounter = 0;
  HAL_TIM_Base_Init(&htim3);
 
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);
     
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);
     
    HAL_TIM_Base_Start(&htim3);
}
 
/* ADC CONVERT FUNCTION*/
uint16_t samplecount;
uint16_t SampleADC(uint16_t SampleCount, uint32_t ADC_Channel)
{
    uint32_t Value =0;
     samplecount= SampleCount;
    __disable_irq();
    ADC1->CR = 0;
    ADC1->CR |= ADC_CR_ADEN; // ADC enable
    ADC1->CR &= ~ADC_CR_ADSTART;
    ADC1->CHSELR = ADC_Channel; // select adc channel
     
    ADC1->CR|=ADC_CR_ADSTART;   // start conversion
 
    while(SampleCount){
        GPIOF->ODR |= GPIO_PIN_0;
        while(!(ADC1->ISR&ADC_ISR_ADRDY)); // wachten tot de ADC klaar is
        //ADC1->CR|=ADC_CR_ADSTART; // start conversion
        //wacht tot conversie is voltooid
        while((ADC1->ISR & ADC_ISR_EOC)!=ADC_ISR_EOC);
         
        Value += ADC1->DR; // haal analoge waarde op
        SampleCount--;
        GPIOF->ODR &= ~GPIO_PIN_0;
    }
    Value /= samplecount; // gemiddelde nemen
 
    ADC1->CR |= ADC_CR_ADDIS;       //disable adc
    __enable_irq();
    return Value&0xFFFF;
}

Outcomes