cancel
Showing results for 
Search instead for 
Did you mean: 

[STM32L475] ADC channel reading problem getting unexpected value

AKAK
Associate II

Hi all,

 

I have a problem which is bugging me as I can't figure out what im doing wrong.

I am trying to read from ADC_IN4 but are reading wrong values. I should be reading apprx. 30000 ADC value but i am reading apprx. 7800. I think that this indicates that i am not reading from the right channel because there is a LM20 temperature sensor connected to PC3 which is ADC_IN4 on stm32L475x and the value does not change if i apply heat or cold.

I want the TIM4_TRGO event to trigger ADC conversions with 16x oversampling, and at sequence end, trigger EOS interrupt where i read the ADC data. Later on i want to connect it to DMA.

I have never really worked with update events on stm32 so I think I am maybe doing something wrong setting up the update events, maybe im mixing up interrupts and events, or the ADC channel configuration is wrong.

I really hope someone can help me.

Thanks.

#include "stm32l475xx.h"
#include "variables.h"
volatile uint32_t count = 0;
volatile uint32_t result = 0;

void sysclk_config(){
    RCC->CR |= RCC_CR_HSEON; // turn on HSE clock
 // wait until hardware sets this bit to indicate HSE is ready
    while(!(RCC->CR & RCC_CR_HSERDY));
    RCC->CFGR |= RCC_CFGR_SW_HSE; // Use HSE as system clock

 // Check status of HSE as system clock
    while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSE);
    RCC->CR &= ~(1<<0); //MSI OFF

PWR->CR1 |= (1U<<9U);
}

void peripheralClk_config(){
    RCC->AHB2ENR |= RCC_AHB2ENR_ADCEN; // Enable clock for ADC.
    
    RCC->CCIPR |= (3U<<28); // set ADC clock as system clock
    
    RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; // Enable clock for DMA1
    
    RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN; // Enable clock for GPIO C
    
    RCC->AHB2ENR |= RCC_AHB2ENR_GPIOHEN; // Enable clock for GPIO H
    
    RCC->APB1ENR1 |= RCC_APB1ENR1_TIM4EN;
}

void GPIOC_setup(){
    GPIOC->MODER |= (0x3U << 0U); // GPIOC Mode register for PC0 = 3 Analog mode
    
    GPIOC->PUPDR &= ~(0x3U << 0U); // No pull up/Pull down
    
    GPIOC->MODER |= (3U << 6U); // GPIOC Mode PC3 = 3 (Analog mode)
    
    GPIOC->PUPDR &= ~(3U << 6U); // No pull-up/pull-down
    
    GPIOC->ASCR |= (1U<<4U); // Analog switch
}

void ADC2_setup() {

    ADC2->CR &= ~ADC_CR_DEEPPWD; // wake up ADC from deep power down

    ADC2->CR |= ADC_CR_ADVREGEN;

    uint32_t wait_loop_index;
    wait_loop_index = (((20UL) * (16000000 / (100000 * 2))) / 10);
    while(wait_loop_index != 0){
        wait_loop_index--;
    }
        // Enable Vref
    (*(volatile uint32_t*)((0x50040300) + (0x08)) |= (1U << 22U)); 
    

    ADC2->CR |= ADC_CR_ADCAL; // Start calibration;


    // EXT Line 12 for TIM4_TRGO
    while (ADC2->CR & ADC_CR_ADCAL); // Wait for calibration to complete
    
    ADC2->CFGR |= (ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2); 
    ADC2->CFGR |= (0x1U << 10U); // Hardware trigger on rising edge
    ADC2->CFGR2 |= (0x3UL << 2U); // 16x oversampling
    ADC2->CFGR2 |= (0x00U << 5U); // no bit shift
    ADC2->CFGR2 |= (1U<<0U); // regular oversampling enable
    ADC2->IER |= ADC_IER_EOSIE; // end of sequence interrupt enable
    ADC2->SQR1 &= ~ADC_SQR1_SQ1; // Clear sequence register
    ADC2->SQR1 |= (0x4U << 6U); // Channel 4 is 1st conversion
    ADC2->SMPR1 &= ~ADC_SMPR1_SMP3; // clear sampletime register
    ADC2->SMPR1 |= (0U << 9U); // 2.5 Sample time for channel 4
    NVIC_EnableIRQ(ADC1_2_IRQn);
    ADC2->CR &=\~ ADC_CR_ADDIS;
    ADC2->CR |= ADC_CR_ADEN;
    while (!(ADC2->ISR & ADC_ISR_ADRDY));
}

void ADC_Start(void){

    ADC2->CR |= ADC_CR_ADSTART;
}

void ADC1_2_IRQHandler(void){
    if (ADC2->ISR & ADC_ISR_EOS){ // Check if end of sequence flag is set

    result = ADC2->DR; // Read from ADC Data Register
    ADC2->ISR &= ~ADC_ISR_EOS; // Clear end of sequence flag.

    ADC2->CR |= ADC_CR_ADSTART;
    }
}
void TIM4_ADC_setup(){ // Function for setting up the ADC timer 16kHz
    TIM4->PSC = 1; // Set prescaler
    TIM4->ARR = 119; // Set auto-reload value
    TIM4->CR1 &= ~(1U<<7U); // ARR not buffered
    TIM4->CR1 &= ~(3U<<8U); // no clock division
    TIM4->CR2 |= TIM_CR2_MMS_1;
    TIM4->EGR |= TIM_EGR_UG; // Update generation
    TIM4->DIER |= TIM_DIER_UIE;

    NVIC_EnableIRQ(TIM4_IRQn);

    TIM4->CR1 |= TIM_CR1_CEN; // Start the timer
}

void TIM4_IRQHandler(void) {
    if (TIM4->SR & TIM_SR_UIF) { // Check if update interrupt flag is set
        TIM4->SR &= ~TIM_SR_UIF; // Clear update interrupt flag
    }
}

int main(void){
    __enable_irq();
    sysclk_config();
    peripheralClk_config();
    GPIOC_setup();
    TIM4_ADC_setup();
    ADC2_setup();
    ADC_Start();
    while(1){
    }
}
1 ACCEPTED SOLUTION

Accepted Solutions

> Shorting to GND or Vref also makes no difference.

Then probably that pin isn't connected to what you think it is, or it's not configured correctly.

> GPIOC->ASCR |= (1U<<4U); // Analog switch

Should be 1U << 3U to set ASC3, yes?

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

View solution in original post

4 REPLIES 4
TDK
Guru

> ADC2->SMPR1 |= (0U << 9U); // 2.5 Sample time for channel 4

This is a very short sample time. Consider increasing it to max. Temperature doesn't change that quickly.

Short the input to GND, do you get 0 (or close to)? Short it to VREF+, do you get 65536, or close to?

 

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

I tried setting sampletime to max but nothing changed. 

Shorting to GND or Vref also makes no difference.

> Shorting to GND or Vref also makes no difference.

Then probably that pin isn't connected to what you think it is, or it's not configured correctly.

> GPIOC->ASCR |= (1U<<4U); // Analog switch

Should be 1U << 3U to set ASC3, yes?

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

@TDK wrote:

> GPIOC->ASCR |= (1U<<4U); // Analog switch

Should be 1U << 3U to set ASC3, yes?


That was the problem. 

As soon as i changed that to 3 instead of 4 it worked..

Thank you so very much.