title: Individually read distinct inputs with STM32F0 ADC
body: <p>STM32F072CBU microcontroller.</p>
  
  <p>I have multiple inputs to the ADC and would like to read them individually and separately. STMcubeMX produces boilerplate code which assumes I wish to read all of the inputs sequentially, and I have not been able to figure out how to correct this.</p>
  
  <p><a href="http://blog.koepi.info/2015/05/stm32-adc-some-weird-behaviours.html" rel="nofollow noreferrer">This blog post</a> expresses the same problem I am having, but the solution given doesn't seem to work. Turning the ADC on and off for each conversion correlates with error in the returned value. Only when I configure a single ADC input in STMcubeMX and then poll without de-initializing the ADC are accurate readings returned.</p>
  
  <p>cubeMX's adc_init function:</p>
  
  <pre><code>/* ADC init function */
  static void MX_ADC_Init(void)
  {
  
    ADC_ChannelConfTypeDef sConfig;
  
      /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
      */
    hadc.Instance = ADC1;
    hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    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 = DISABLE;
    hadc.Init.LowPowerAutoPowerOff = DISABLE;
    hadc.Init.ContinuousConvMode = DISABLE;
    hadc.Init.DiscontinuousConvMode = DISABLE;
    hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    hadc.Init.DMAContinuousRequests = DISABLE;
    hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
    if (HAL_ADC_Init(&amp;hadc) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
      /**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_41CYCLES_5;
    if (HAL_ADC_ConfigChannel(&amp;hadc, &amp;sConfig) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
      /**Configure for the selected ADC regular channel to be converted. 
      */
    sConfig.Channel = ADC_CHANNEL_1;
    if (HAL_ADC_ConfigChannel(&amp;hadc, &amp;sConfig) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
      /**Configure for the selected ADC regular channel to be converted. 
      */
    sConfig.Channel = ADC_CHANNEL_2;
    if (HAL_ADC_ConfigChannel(&amp;hadc, &amp;sConfig) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
      /**Configure for the selected ADC regular channel to be converted. 
      */
    sConfig.Channel = ADC_CHANNEL_3;
    if (HAL_ADC_ConfigChannel(&amp;hadc, &amp;sConfig) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
      /**Configure for the selected ADC regular channel to be converted. 
      */
    sConfig.Channel = ADC_CHANNEL_4;
    if (HAL_ADC_ConfigChannel(&amp;hadc, &amp;sConfig) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
      /**Configure for the selected ADC regular channel to be converted. 
      */
    sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
    if (HAL_ADC_ConfigChannel(&amp;hadc, &amp;sConfig) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
      /**Configure for the selected ADC regular channel to be converted. 
      */
    sConfig.Channel = ADC_CHANNEL_VREFINT;
    if (HAL_ADC_ConfigChannel(&amp;hadc, &amp;sConfig) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
  }
  </code></pre>
  
  <p>main.c</p>
  
  <pre><code>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();
  
    /* USER CODE BEGIN Init */
  
    /* USER CODE END Init */
  
    /* Configure the system clock */
    SystemClock_Config();
  
    /* USER CODE BEGIN SysInit */
  
    /* USER CODE END SysInit */
  
    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_ADC_Init();
    MX_USART1_UART_Init();
  
    /* USER CODE BEGIN 2 */
    //HAL_TIM_Base_Start_IT(&amp;htim3);
    init_printf(NULL, putc_wrangler);
    HAL_ADCEx_Calibration_Start(&amp;hadc);
    HAL_ADC_DeInit(&amp;hadc); // ADC is initialized for every channel change
    schedule_initial_events();
    /* USER CODE END 2 */
  
    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    event_loop();
    /* USER CODE END WHILE */
  
    /* USER CODE BEGIN 3 */
  
    /* USER CODE END 3 */
  
  }
  </code></pre>
  
  <p>My process right now for turning the ADC off and reinitializing to change channels:</p>
  
  <pre><code>// Set up
    ADC_ChannelConfTypeDef channelConfig;
  
    channelConfig.SamplingTime = samplingT;
    channelConfig.Channel = sensorChannel;
    channelConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  
    if (HAL_ADC_Init(&amp;hadc) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
    if (HAL_ADC_ConfigChannel(&amp;hadc, &amp;channelConfig) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
  // Convert
    uint16_t retval;
  
    if (HAL_ADC_Start(&amp;hadc) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
    if (HAL_ADC_PollForConversion(&amp;hadc, 1) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
    if (HAL_ADC_GetError(&amp;hadc) != HAL_ADC_ERROR_NONE)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
    retval = (uint16_t) HAL_ADC_GetValue(&amp;hadc);
  
    if (HAL_ADC_Stop(&amp;hadc) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
  
  // Close
    HAL_ADC_DeInit(&amp;hadc);
  </code></pre>
  
  <p>At this point I'm not really sure that there's a way to accomplish what I want, STM32 seems dead set on active ADC lines being in the regular group and being converted in order.</p>