AnsweredAssumed Answered

STM32F072 ADC with reduced PCLK

Question asked by Jack on Aug 31, 2016
Latest reply on Sep 1, 2016 by Jack
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 Rain of 4k7, and running the ADC off the HSI14.

From the equation in AN2834 Rain_max = Ts / [fadc * Cadc * ln(2n+1)] - Radc_max 

I calculated Ts to be 5.75, and set Ts to be 7.5 cycles in software

Ts = (Rain_max + Radc_max) * [fadc * Cadc * ln(2n+1)]
Ts = (4700 + 1000) * [14MHz * 8pF * ln(212+1)] 
Ts = 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 / 4095.0 * 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();
  }
 
}


Outcomes