Не поленился посмотреть как это в HAL сделано. Пробрался сквозь дебри калокуба.
CODE
#if defined(STM32F373xC) || defined(STM32F378xx)
/**
* @brief Perform an ADC automatic self-calibration
* Calibration prerequisite: ADC must be disabled (execute this
* function before HAL_ADC_Start() or after HAL_ADC_Stop() ).
* During calibration process, ADC is enabled. ADC is let enabled at
* the completion of this function.
* @param hadc ADC handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc)
{
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
uint32_t tickstart;
__IO uint32_t wait_loop_index = 0U;
/* Check the parameters */
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
/* Process locked */
__HAL_LOCK(hadc);
/* 1. Calibration prerequisite: */
/* - ADC must be disabled for at least two ADC clock cycles in disable */
/* mode before ADC enable */
/* Stop potential conversion on going, on regular and injected groups */
/* Disable ADC peripheral */
tmp_hal_status = ADC_ConversionStop_Disable(hadc);
/* Check if ADC is effectively disabled */
if (tmp_hal_status == HAL_OK)
{
/* Set ADC state */
ADC_STATE_CLR_SET(hadc->State,
HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
HAL_ADC_STATE_BUSY_INTERNAL);
/* Wait two ADC clock cycles */
while(wait_loop_index < ADC_CYCLE_WORST_CASE_CPU_CYCLES *2U)
{
wait_loop_index++;
}
/* 2. Enable the ADC peripheral */
ADC_Enable(hadc);
/* 3. Resets ADC calibration registers */
SET_BIT(hadc->Instance->CR2, ADC_CR2_RSTCAL);
tickstart = HAL_GetTick();
/* Wait for calibration reset completion */
while(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_RSTCAL))
{
if((HAL_GetTick() - tickstart) > ADC_CALIBRATION_TIMEOUT)
{
/* Update ADC state machine to error */
ADC_STATE_CLR_SET(hadc->State,
HAL_ADC_STATE_BUSY_INTERNAL,
HAL_ADC_STATE_ERROR_INTERNAL);
/* Process unlocked */
__HAL_UNLOCK(hadc);
return HAL_ERROR;
}
}
/* 4. Start ADC calibration */
SET_BIT(hadc->Instance->CR2, ADC_CR2_CAL);
tickstart = HAL_GetTick();
/* Wait for calibration completion */
while(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_CAL))
{
if((HAL_GetTick() - tickstart) > ADC_CALIBRATION_TIMEOUT)
{
/* Update ADC state machine to error */
ADC_STATE_CLR_SET(hadc->State,
HAL_ADC_STATE_BUSY_INTERNAL,
HAL_ADC_STATE_ERROR_INTERNAL);
/* Process unlocked */
__HAL_UNLOCK(hadc);
return HAL_ERROR;
}
}
/* Set ADC state */
ADC_STATE_CLR_SET(hadc->State,
HAL_ADC_STATE_BUSY_INTERNAL,
HAL_ADC_STATE_READY);
}
/* Process unlocked */
__HAL_UNLOCK(hadc);
/* Return function status */
return tmp_hal_status;
}
/**
* @brief Enable the selected ADC.
* @note Prerequisite condition to use this function: ADC must be disabled
* and voltage regulator must be enabled (done into HAL_ADC_Init()).
* @param hadc ADC handle
* @retval HAL status.
*/
static HAL_StatusTypeDef ADC_Enable(ADC_HandleTypeDef* hadc)
{
uint32_t tickstart = 0U;
__IO uint32_t wait_loop_index = 0U;
/* ADC enable and wait for ADC ready (in case of ADC is disabled or */
/* enabling phase not yet completed: flag ADC ready not yet set). */
/* Timeout implemented to not be stuck if ADC cannot be enabled (possible */
/* causes: ADC clock not running, ...). */
if (ADC_IS_ENABLE(hadc) == RESET)
{
/* Enable the Peripheral */
__HAL_ADC_ENABLE(hadc);
/* Delay for ADC stabilization time */
/* Compute number of CPU cycles to wait for */
wait_loop_index = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U));
while(wait_loop_index != 0U)
{
wait_loop_index--;
}
/* Get tick count */
tickstart = HAL_GetTick();
/* Wait for ADC effectively enabled */
while(ADC_IS_ENABLE(hadc) == RESET)
{
if((HAL_GetTick() - tickstart) > ADC_ENABLE_TIMEOUT)
{
/* Update ADC state machine to error */
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
/* Set ADC error code to ADC IP internal error */
SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
/* Process unlocked */
__HAL_UNLOCK(hadc);
return HAL_ERROR;
}
}
}
/* Return HAL status */
return HAL_OK;
}
/**
* @brief Enable the ADC peripheral
* @note ADC enable requires a delay for ADC stabilization time
* (refer to device datasheet, parameter tSTAB)
* @note On STM32F37x devices, if ADC is already enabled this macro trigs
* a conversion SW start on regular group.
* @param __HANDLE__ ADC handle
* @retval None
*/
#define __HAL_ADC_ENABLE(__HANDLE__) \
(SET_BIT((__HANDLE__)->Instance->CR2, (ADC_CR2_ADON)))
#endif /* STM32F373xC || STM32F378xx */
Включают они его, естественно, перед калибровкой.