cancel
Showing results for 
Search instead for 
Did you mean: 

How can I read analog data using adc with low layer libraries?

MOB1
Associate II

Hello, I want to read an analog data and I didnt figure out how to use low layer libraries properly?

I am using stm32wb55rgv6 nucleo board

Code :

#include <stm32wbxx_ll_bus.h>

#include <stm32wbxx_ll_rcc.h>

#include <stm32wbxx_ll_gpio.h>

#include <stm32wbxx_ll_tim.h>

#include <stm32wbxx_ll_utils.h>

#include <stm32wbxx_ll_adc.h>

#include <stdio.h>

void SystemClock_Config(void);

void ADC_Clock_Config(void);

void adc1_init(void);

/*

 * PC0 : ADC1_IN1 pin of the stm32

 *

 * */

uint32_t volatile sensor_value = 0;

int main(void)

{

SystemClock_Config();

ADC_Clock_Config();

adc1_init();

while(1)

{

/*1) Start adc conversion */

/*

* On this STM32 series, this function is relevant for both internal trigger (SW start)

* and external trigger.

* */

LL_ADC_REG_StartConversion(ADC1);

/*2) wait for conversion to be complete

* End of Sequence

* */

while(!(LL_ADC_IsActiveFlag_EOC(ADC1)))

{

}

/*3) read converted value */

sensor_value = LL_ADC_REG_ReadConversionData32(ADC1);

}

}

/* System Clock Configurations

 * SYSCLK : 32 MHz

 * HCLK : 16 MHz

 * APB1 : 16 MHz

 * APB2 : 16 MHz

 * */

void SystemClock_Config(void)

{

/* Setting Flash Latency and wait for set

* We set latency cause flash has to be delayed due to read write operation in it

* */

LL_FLASH_SetLatency(LL_FLASH_LATENCY_1);

while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_1)

{

}

/* Enable the MSI and waiting for enable*/

LL_RCC_MSI_Enable();

while(LL_RCC_MSI_IsReady() != 1)

{

}

/* Setting MSI range MSI works between 100kHz to 48 MHZ

* LL_RCC_MSIRANGE_10 : 32 MHz

* */

LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_10);

/* Configs on CPU1 prescaler

* We set MSI TO 32 MHz BY division 1 we get 32 MHZ for CPU1

* */

LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);

/* Set CPU2 prescaler which is for BLE CPU2 runs at 32 MHZ

* BLE operations requires at least 16 MHZ on HCLK2

* */

LL_C2_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);

/* Setting System Clock Sourse as MSI which is configured as 32MHz

* and waiting for enabled

* */

LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI);

while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI)

{

}

/* Set AHB SHARED prescaler*/

LL_RCC_SetAHB4Prescaler(LL_RCC_SYSCLK_DIV_1);

/* Set APB1 prescaler

* APB1 bus clock frequency is CPU1 frequency which is 32 MHz

* we divide by CPU freq by 1

* */

LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);

/* Set APB2 prescaler

* APB2 bus clock frequency is CPU1 frequency which is 32 MHz

* we divide by CPU freq by 1

* */

LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);

 /* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function)

  * It sets the HCLK frequency

  * */

LL_SetSystemCoreClock(32000000);

}

void ADC_Clock_Config(void)

{

LL_RCC_PLLSAI1_ConfigDomain_ADC(LL_RCC_PLLSOURCE_MSI, LL_RCC_PLLM_DIV_2, 8, LL_RCC_PLLSAI1R_DIV_2);

LL_RCC_PLLSAI1_Enable();

LL_RCC_PLLSAI1_EnableDomain_ADC();

/* Wait till PLLSAI1 is ready */

while(LL_RCC_PLLSAI1_IsReady() != 1)

{

}

}

void adc1_init(void)

{

/* Setting ADC clock source as PLLSAI*/

LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1);

/* 1-) Enable clock access to adc module*/

LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC);

/* 2-) Enable clock acces to adc channel port*/

/* Enable peripheral clock */

LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);

/* 3-) Set adc channel pin mode to analog */

/* ADC_IN1 PC0*/

LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_0, LL_GPIO_MODE_ANALOG);

/* 4-) Set adc trigger */

/* We want to trigger by software we can use EXTI_TIM or EXTI_LINE or */

LL_ADC_REG_SetTriggerSource(ADC1, LL_ADC_REG_TRIG_SOFTWARE);

/* 5-) Set sampling sequence */

/* For now we deal with one channel so our rank should be 1 later will see details of it*/

LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1,LL_ADC_CHANNEL_1);

/* 6-) Set Sequence length */

LL_ADC_REG_SetSequencerLength(ADC1, LL_ADC_REG_SEQ_SCAN_DISABLE);

/* If we have multiple channels we use LL_ADC_REG_SEQ_SCAN_2RANKS or more ranks depending on how many channels we have*/

/* 7-) Enable adc*/

LL_ADC_Enable(ADC1);

}

When I debugging the code is stuck at while(!LL_ADC_IsActiveFlag_EOC(ADC1))

What is the problem and how can I read analog data properly:pensive_face: ?

Thanks for helps

1 ACCEPTED SOLUTION

Accepted Solutions
Chris1
Senior III

Also, after ADC Enable, a delay may be needed, for example [STM32L4 devices]:

On this STM32 serie, after ADC enable, a delay for

 *        ADC internal analog stabilization is required before performing a ADC conversion start.

 *        Refer to device datasheet, parameter tSTAB.

 * @note  On this STM32 serie, flag LL_ADC_FLAG_ADRDY is raised when the ADC is enabled and when conversion clock is active.

 *        (not only core clock: this ADC has a dual clock domain)

View solution in original post

3 REPLIES 3
Chris1
Senior III

I am not familiar with stm32wb55, but other STM32 ADCs require configuration of things like resolution (e.g., 8-bit, 10-bit, etc.), data alignment, scan conversion mode, EOC Selection, sampling time, number of conversions, etc.

Chris1
Senior III

Also, after ADC Enable, a delay may be needed, for example [STM32L4 devices]:

On this STM32 serie, after ADC enable, a delay for

 *        ADC internal analog stabilization is required before performing a ADC conversion start.

 *        Refer to device datasheet, parameter tSTAB.

 * @note  On this STM32 serie, flag LL_ADC_FLAG_ADRDY is raised when the ADC is enabled and when conversion clock is active.

 *        (not only core clock: this ADC has a dual clock domain)

Thank you so much . The problem is about tSTAB parameter. Your comment helped me a lot 😍