cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 HAL ADC Library Issues with HAL_ADC_Init and HAL_ADC_ConfigChannel functions

tpailevanian
Associate
    if ((ADC_IS_ENABLE(hadc) == RESET)   &&
        (ADC_ANY_OTHER_ENABLED(hadc) == RESET) )
    {
      /* Reset configuration of ADC common register CCR:                      */
      /*                                                                      */
      /*   - ADC clock mode and ACC prescaler (CKMODE and PRESC bits)are set  */
      /*     according to adc->Init.ClockPrescaler. It selects the clock      */
      /*    source and sets the clock division factor.                        */
      /*                                                                      */
      /* Some parameters of this register are not reset, since they are set   */
      /* by other functions and must be kept in case of usage of this         */
      /* function on the fly (update of a parameter of ADC_InitTypeDef        */
      /* without needing to reconfigure all other ADC groups/channels         */
      /* parameters):                                                         */
      /*   - when multimode feature is available, multimode-related           */
      /*     parameters:DELAY,DUAL(set by API                                 */
      /*     HAL_ADCEx_MultiModeConfigChannel())                              */
      /*   - internal measurement paths: Vbat, temperature sensor, Vref       */
      /*     (set into HAL_ADC_ConfigChannel() or                             */
      /*     HAL_ADCEx_InjectedConfigChannel() )                              */
 
      MODIFY_REG(tmpADC_Common->CCR, ADC_CCR_PRESC|ADC_CCR_CKMODE, hadc->Init.ClockPrescaler);
    }

In the case that ADC1 and ADC2 are disabled but ADC3 is enabled, and you are trying to change the clock prescaler, the hal library will report HAL_OK but section of code that is changing the clock prescaler will not execute. According to the reference manual, only ADC1 and ADC2 should be disabled when changing the ADC12 common register.

	 if(hadc->Instance == ADC3)
	 {
        /* Software is allowed to change common parameters only when all ADCs   */
        /* of the common group are disabled.                                    */
        if ((ADC_IS_ENABLE(hadc) == RESET)   &&
           (ADC_ANY_OTHER_ENABLED(hadc) == RESET) )
        {
          /* Enable Temperature sensor measurement path (channel 18)            */
          /* Note: Temp. sensor internal channels available on ADC3    */
          if ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) && ((hadc->Instance == ADC3)))
          {
             SET_BIT(tmpADC_Common->CCR, ADC_CCR_TSEN);
    
            /* Wait loop initialization and execution */
            /* Note: Variable divided by 2 to compensate partially          */
            /*       CPU processing cycles.                                 */
            wait_loop_index = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / (1000000 * 2)));
            while(wait_loop_index != 0)
            {
              wait_loop_index--;
            }
          }
          /* If Channel 18 is selected, enable VBAT measurement path.           */
          /* Note: VBAT internal internal channels available on ADC1 and ADC3   */
          else if ((sConfig->Channel == ADC_CHANNEL_VBAT_DIV4) && ((hadc->Instance == ADC3)))
          {
            SET_BIT(tmpADC_Common->CCR, ADC_CCR_VBATEN);
          }
          /* If Channel 19 is selected, enable VREFINT measurement path          */
          /* Note: VBAT internal internal channels available on ADC1 only       */
          else if ((sConfig->Channel == ADC_CHANNEL_VREFINT) && (hadc->Instance == ADC3))
          {
            SET_BIT(tmpADC_Common->CCR, ADC_CCR_VREFEN);
          }
        }
 
        /* If the requested internal measurement path has already been          */
        /* enabled and other ADC of the common group are enabled, internal      */
        /* measurement paths cannot be enabled.                                 */
        else
        {
          /* Update ADC state machine to error */
          SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
    
          tmp_hal_status = HAL_ERROR;
        }
	 }

In the config channel function, the code should check if the instance is ADC3 before trying to configure the internal ADC channels. There was an instance where my adc was channel 18 on ADC1, but the software tried to configure it since I was also using the internal temperature sensor. I added an if statement to check if the ADC was ADC3 before trying to configure the channel to patch up the code temporarily but this is not a good fix for the drivers.

For the ADC init function, I had to disable ADC3 as a quick fix but in a situation where you would not want to disable ADC3 in order to change the sample rate of ADC1 or ADC2, this would be a big issue.

0 REPLIES 0