2016-06-21 04:55 AM
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-vrefint2016-06-28 07:02 AM
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.Regards2016-06-29 05:18 AM
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-
2016-08-16 11:31 PM
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