Skip to main content
Graduate
August 11, 2024
Question

Unable to read second ADC channel

  • August 11, 2024
  • 3 replies
  • 1217 views

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

    This topic has been closed for replies.

    3 replies

    Graduate
    August 11, 2024

    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.

    x4ceAuthor
    Graduate
    August 11, 2024

    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

    Visitor II
    August 11, 2024

    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.

    x4ceAuthor
    Graduate
    August 11, 2024

    Thanks for responding.

    It is properly connected to GND.

    Super User
    August 12, 2024

    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.