Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F373 ADC 12 BIT калибровка
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Alex_Golubev
Привет.
Столкнулся с проблемой калибровки 12 битного АЦП stm32f373.

Делаю как написано в rm0313.

При выключенном бите ADON = 0;

Пишу следующий код:
Код ADC1->CR2 |= ADC_CR2_CAL; // устанавливаю CAL в 1
while (ADC1->CR2 & ADC_CR2_CAL); // жду сброса CAL в 0

Программа зависает на строчки while (ADC1->CR2 & ADC_CR2_CAL); CAL в нуль не переходит.
VladislavS
В других чипах такой же АЦП рекомендуют во включенном состоянии калибровать, что более логично. Ну какая калибровка может быть, если АЦП в power down находится при ADON=0.
Alex_Golubev
Тогда не ясно почему в доки сказано:
Note: It is recommended to perform a calibration after each power-up.
Before starting a calibration the ADC must have been in power-off state (ADON bit = ‘0’) for
at least two ADC clock cycles.

И да при ADON = 1 все работает.
ataradov
Это применимо если АЦП был включен и выполнял преобразования до этого. Калибровку нужно выполнять после выключения и включения. Ну и при калибровке при перезапуске он и так будет выключен естественно.
VladislavS
Не поленился посмотреть как это в 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 */


Включают они его, естественно, перед калибровкой.
Timmy
Цитата(Alex_Golubev @ May 9 2018, 06:27) *
Тогда не ясно почему в доки сказано:
Note: It is recommended to perform a calibration after each power-up.
Before starting a calibration the ADC must have been in power-off state (ADON bit = ‘0’) for
at least two ADC clock cycles.

И да при ADON = 1 все работает.

В доке всё чётко сказано. have been - это форма глагола Present Perfect, которая обозначает действие, полностью завершившееся к настоящему времени, то есть во время калибровки АЦП уже не должен быть в power-off.
ViKo
Цитата(Timmy @ May 10 2018, 09:21) *
В доке всё чётко сказано. have been - это форма глагола Present Perfect, которая обозначает действие, полностью завершившееся к настоящему времени, то есть во время калибровки АЦП уже не должен быть в power-off.

Сказано, что АЦП должен пробыть в выключенном состоянии, как минимум, два такта. Но не сказано, что уже надо включить. Хотя, похоже, надо.
Timmy
Цитата(ViKo @ May 10 2018, 10:15) *
Сказано, что АЦП должен пробыть в выключенном состоянии, как минимум, два такта. Но не сказано, что уже надо включить. Хотя, похоже, надо.

Да, здесь наверное более уместно было бы Past Perfect, надо у лингвистов спроситьsm.gif.
ViKo
Для STM32F303 я запускал калибровку перед включением АЦП.
Andy_F
У 373-го калибровка 12 битного ADC не работает (у меня, по крайней мере ) ).
Jenya7
Цитата(ViKo @ May 10 2018, 16:49) *
Для STM32F303 я запускал калибровку перед включением АЦП.

а у меня в коде для STM32F303
Код
/* Calibration procedure for ADC1*/  
ADC_VoltageRegulatorCmd(ADC1, ENABLE);
TIM_Delay_us(TIM6, 20);
        
ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC1);
        
while(ADC_GetCalibrationStatus(ADC1) != RESET );
calibration_value1 = ADC_GetCalibrationValue(ADC1)

/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
сначала калибруется потом включается. так неправильно?
ViKo
Цитата(Jenya7 @ May 13 2018, 23:24) *
а у меня в коде для STM32F303
...
сначала калибруется потом включается. так неправильно?

А я разве не так написал? rolleyes.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.