2024-08-11 09:03 AM - edited 2024-08-11 09:10 AM
Hi,
I am using STM32F030 for a project where I need to trigger ADC conversion every 100us. I am running this SoC on 8MHz HSI. I am using TIM3 TRG for initiating ADC conversion every 100us. I am obtain ADC every 100us with ADC_CH5 which is set to 3V3 and getting result in 4024 decimals. But I am unable to get readings from ADC_CH7 which is set to GND and I always get same reading as of ADC_CH5.
May be I am not correctly configuring ADC_CH7 or there is an issue in interrupt handling. I have attached my code for your ready reference please.
ADC Configuration:
void adc_tg0_init(void)
{
// Enable Clock to GPIOA
RCC->AHBENR |= GPIOA_EN;
// PA5 as analog input
GPIOA->MODER |= (1U<<10);
GPIOA->MODER |= (1U<<11);
// PA7 as analog input
GPIOA->MODER |= (1U<<14);
GPIOA->MODER |= (1U<<15);
// Enable Clock to ADC
RCC->APB2ENR |= ADC_EN;
// Enable external trigger on rising edge
ADC1->CFGR1 |= (1U<<10);
ADC1->CFGR1 &= ~(1U<<11);
// Select Timer 3 TRG0 [TRG3] event as external trigger
ADC1->CFGR1 |= (1U<<6);
ADC1->CFGR1 |= (1U<<7);
ADC1->CFGR1 &= ~(1U<<8);
/* ADC Enable Procedure */
if ((ADC1->ISR & ADC_ISR_ADRDY) != 0)
{
ADC1->ISR |= ADC_ISR_ADRDY;
}
ADC1->CR |= ADC_CR_ADEN;
while ((ADC1->ISR & ADC_ISR_ADRDY) ==0) {}
/* Channel Selection */
ADC1->CHSELR |= ADC_CHSELR_CHSEL5 | ADC_CHSELR_CHSEL7;
/* Sampling Mode Selection */
ADC1->SMPR |= ADC_SMPR_SMP_1 |
ADC_SMPR_SMP_2;
/* Enable Interrupts */
ADC1->IER = ADC_IER_EOCIE | ADC_IER_EOSEQIE |
ADC_IER_OVRIE;
/* Set/ Enable VRef to Internal */
ADC->CCR |= ADC_CCR_VREFEN;
/* Enable NVIC */
NVIC_EnableIRQ(ADC1_COMP_IRQn);
// Start ADC
ADC1->CR |= ADC_CR_ADSTART;
// Start Timer 3
TIM3->CR1 |= TIM_CR1_CEN;
}
ADC Interrupt:
void ADC_IRQHandler(void)
{
if (ADC1->ISR & ADC_ISR_EOC)
{
adc_raw_data[adc_idx] = ADC1->DR;
adc_idx++;
pa6_toggle();
ADC1->ISR |= ADC_ISR_EOC;
}
if (ADC1->ISR & ADC_ISR_EOSEQ)
{
ADC1->ISR |= ADC_ISR_EOSEQ;
}
if (ADC1->ISR & ADC_ISR_OVR)
{
adc_ovr = true;
ADC1->ISR |= ADC_ISR_OVR;
}
}
Regards
2024-08-11 09:24 AM
I'm not an expert on register programming, but if you are not using DMA, you need to reconfigure the ADC channel selection and restart the ADC to convert the second channel after the first conversion.
There is only one ADC register to hold the conversion result. To convert more than one channel with one start, use DMA to save each conversion to your selected buffer.
2024-08-11 09:36 AM
The channel connected to GND (ADC_CH7) should be properly connected and have a good grounding. Any loose connections or improper grounding can cause unexpected readings.
2024-08-11 09:39 AM
Thanks for responding but it converts each channel in sequence & EOC event/ flag is generated to indicate each channel conversion. I may switch to DMA but I need to clear this step before proceeding to next.
Regards
2024-08-11 09:39 AM
Thanks for responding.
It is properly connected to GND.
2024-08-11 06:08 PM
Probably a data overrun due to not reading the ADC in time. Does the OVR flag get set?
Use DMA to convert multiple channels. Or slow down the conversion enough that you can handle it before it overruns.