2016-11-03 07:41 AM
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;
}
#!stm32-!adc
2016-11-03 08:25 AM
I'm confused. You're using external trigger AND software start&poll?
2016-11-03 08:48 AM
Why wouldn't one use DMA for this, and process the buffer with all the data at the 50Hz / 20ms interval ? Or at least decimate, so as not to grind in loops sucking power.
At some point your current code is going to saturate.Suggest you look at the other ADC flags, probably overrunning