cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F042 Vrefint reading

ali ergin gursoy
Associate II
Posted on June 21, 2016 at 13:55

Hi everyone,

I am working on a project and need to measure analog voltage on some channels. To do so I use CubeMx version 4.15.1, but the readings on channels are significantly different than the applied voltage (about 40mV to 100mV). So I decided to use Vrefint to calculate the more accurate result where it is written in the reference manual as:

Vchannel_x = (3.3 * Vrefint_cal * ADC_Data) / (Vrefint_data * Fullscale)

Unfortunately, I always read the Vrefint as 4095. I could not figure it out what I am doing wrong. Could you please guide me to right path?

The HSI14 is used to clock ADC, and I wish to start and stop the conversion. So the initialization of system clock and adc are like:

/* ADC init function */

void MX_ADC_Init(void)

{

/* Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)

*/

hadc.Instance = ADC1;

hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;

hadc.Init.Resolution = ADC_RESOLUTION12b;

hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;

hadc.Init.EOCSelection = EOC_SINGLE_CONV;

hadc.Init.LowPowerAutoWait = DISABLE;

hadc.Init.LowPowerAutoPowerOff = DISABLE;

hadc.Init.ContinuousConvMode = DISABLE;

hadc.Init.DiscontinuousConvMode = DISABLE;

hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc.Init.DMAContinuousRequests = DISABLE;

hadc.Init.Overrun = OVR_DATA_PRESERVED;

if (HAL_ADC_Init(&hadc) != HAL_OK)

{

Error_Handler();

}

sConfig.Channel = ADC_CHANNEL_VREFINT;

sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;

if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

{

Error_Handler();

}

}

/* System Clock Configuration

 */

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct;

RCC_ClkInitTypeDef RCC_ClkInitStruct;

RCC_PeriphCLKInitTypeDef PeriphClkInit;

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI14

                             |RCC_OSCILLATORTYPE_LSI;

RCC_OscInitStruct.HSIState = RCC_HSI_ON;

RCC_OscInitStruct.HSI14State = RCC_HSI14_ON;

RCC_OscInitStruct.HSICalibrationValue = 16;

RCC_OscInitStruct.HSI14CalibrationValue = 16;

RCC_OscInitStruct.LSIState = RCC_LSI_ON;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

  Error_Handler();

}

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

                             |RCC_CLOCKTYPE_PCLK1;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)

{

  Error_Handler();

}

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1|RCC_PERIPHCLK_RTC;

PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI;

PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;

if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)

{

   Error_Handler();

}

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

/* SysTick_IRQn interrupt configuration */

HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

}

int main(void)

{

/* here I am collecting the adc converted value and calculate the average

 */

if (getChannelConvertedValue(ADC_CHANNEL_VREFINT, adc_samp_arr, SAMPLE_ARRAY_LENGTH, MEDIAN_LENGTH, &adc_supply_voltage) == RC_OK)

{

}

}

RC_TypeDef getChannelConvertedValue(uint32_t channel, uint16_t array[], uint32_t len, uint32_t median_len, float *value)

{

if (value == NULL)

{

return RC_NULL_ARG;

}

/* initialize the memory area of the channel

*/

int i;

for (i = 0; i < 99; i++)

{

array[i] = 0;

}

uint16_t adc_val = 0;

for (i = 0; i < 33; i++)

{

HAL_ADCEx_Calibration_Start(&hadc);

if (HAL_ADC_Start(&hadc) == HAL_OK)

{

HAL_ADC_PollForConversion(&hadc, 100);

adc_val = HAL_ADC_GetValue(&hadc);

HAL_ADC_Stop(&hadc);

}

}

for (i = 0; i < 99; i++)

{

HAL_ADCEx_Calibration_Start(&hadc);

if (HAL_ADC_Start(&hadc) == HAL_OK)

{

HAL_ADC_PollForConversion(&hadc, 1000);

adc_val = HAL_ADC_GetValue(&hadc);

HAL_ADC_Stop(&hadc);

array[i] = adc_val;

}

else

{

*value = 0;

return RC_NOT_OK;

}

}

/* store the converted value

*/

*value = MedianAverage(array, len, median_len);

return RC_OK;

}

#!stm32-!cubemx #stm32f042 #adc-vrefint
3 REPLIES 3
ali ergin gursoy
Associate II
Posted on June 28, 2016 at 16:02

Hi,

Nobody interested about the issue I believe but I found the mistake that I made.

I had tried to read from 7 channels but it was tried to do one by one. However, I realize that when I call HAL_ADC_ConfigChannel() function to configure the relevant channel, there is a bitwise or operation on channel selector. Instead of getting values from regular group, I want to read from each channel seperately. So I modified the bitwise or operation by equal operation and my problem was solved.

Regards

Walid FTITI_O
Senior II
Posted on June 29, 2016 at 14:18

Hi ,

Thanks for sharing you result . For the good to other users, can you give in details the modification that you have done to get it work. So,as Iunderstand, youhave modifed the following part:

sConfig.Channel = ADC_CHANNEL_VREFINT; 
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; 
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; 
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

How you implimented ''the equal operation'' as you said ? Thanks. -Hannibal-
ali ergin gursoy
Associate II
Posted on August 17, 2016 at 08:31

Hi,

You are right Hannibal, I had modified the part you mentioned. In the HAL_ADC_ConfigChannel() function, I have modified to following part:

'hadc->Instance->CHSELR |= ADC_CHSELR_CHANNEL(sConfig->Channel);'

In my application I have 7 ADC channels but I do not use all of them at the same time, so I had decided to read value from each channels seperately, so I started to re-configure the relevant channel before HAL_ADC_Start().

On the other hand, I was not aware of getting ADC samples through DMA. I think it is a better solution using DMA to read ADC values from multiple channles.

Regards