2024-02-05 04:59 AM - last edited on 2024-02-05 05:11 AM by SofLit
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){
}
}
Solved! Go to Solution.
2024-02-05 06:15 AM
> 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?
2024-02-05 05:30 AM
> 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?
2024-02-05 06:02 AM
I tried setting sampletime to max but nothing changed.
Shorting to GND or Vref also makes no difference.
2024-02-05 06:15 AM
> 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?
2024-02-05 06:25 AM
@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.