cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to read second ADC channel

x4ce
Associate II

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

5 REPLIES 5
raptorhal2
Lead

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.

liaifat85
Senior III

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.

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

Thanks for responding.

It is properly connected to GND.

TDK
Guru

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.

If you feel a post has answered your question, please click "Accept as Solution".