cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F072 ADC with reduced PCLK

Posted on August 31, 2016 at 14:17

I'm having a problem getting an accurate reading from the ADC with a reduced PCLK. The readings are about 800 values higher than what is expected (using 12bit ADC). When the microcontroller is running at 48MHz I have an accurate reading.

I currently have the microcontroller running at 6MHz (12MHz external crystal), a R ain of 4k7, and running the ADC off the HSI From the equation in AN2834 R ain_max = T s/ [f adc* C adc* ln(2 n+1)] - R adc_max I calculatedT sto be 5.75, and set T sto be 7.5 cycles in software T s= (R ain_max +R adc_max) * [f adc* C adc* ln(2 n+1)] T s= (4700 + 1000) * [14MHz * 8pF * ln(2 12+1)] T s= 5.75 Here is my code if anyone could lend a hand.

uint32_t adc_value;
float voltage;
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC_Init();
/* USER CODE BEGIN 2 */
HAL_RCC_MCOConfig(RCC_MCO, RCC_MCO1SOURCE_HSI14, RCC_MCODIV_1);
HAL_ADC_Start(&hadc);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(HAL_ADC_PollForConversion(&hadc, 10) == HAL_OK){
adc_value = HAL_ADC_GetValue(&hadc);
voltage = adc_value / 40 * 3.3;
HAL_ADC_Start(&hadc);
}
}
/* USER CODE END 3 */
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI14|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSI14State = RCC_HSI14_ADC_CONTROL; 
RCC_OscInitStruct.HSI14CalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;
RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
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_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV8;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != 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);
}
/* ADC init function */
static void MX_ADC_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
RCC->CR2 |= RCC_CR2_HSI14ON;
while((RCC->CR2 & RCC_CR2_HSI14RDY) == 0); 
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.LowPowerAutoWait = ENABLE;
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 = ADC_OVR_DATA_PRESERVED;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
} 
if(HAL_ADCEx_Calibration_Start(&hadc) != HAL_OK){
Error_Handler();
}
/**Configure for the selected ADC regular channel to be converted. 
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
}

1 REPLY 1
Posted on September 01, 2016 at 15:55

After looking into it more, I found the cause of the problem.  I'm currently using PA1 as an output.  When this pin is configured as an output, the reading of the ADC jumps up, until it's configured as an input again.  It seems to have an affect on the entire ADC.

When PA1 is set high as an output, the readings on the ADC are normal.  The ADC becomes problematic when the pin is set low.  There are no shorts between the pins.  I've also made sure there's no voltage difference between VSSA and VSS.  I've also tried putting a series resistor to PA1.

Any suggestions to what could be done here other than using a different pin as PA1 for my output?