Перейти к содержанию
    

STM32F373 ADC 12 BIT калибровка

Привет.

Столкнулся с проблемой калибровки 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 в нуль не переходит.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В других чипах такой же АЦП рекомендуют во включенном состоянии калибровать, что более логично. Ну какая калибровка может быть, если АЦП в power down находится при ADON=0.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда не ясно почему в доки сказано:

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 все работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это применимо если АЦП был включен и выполнял преобразования до этого. Калибровку нужно выполнять после выключения и включения. Ну и при калибровке при перезапуске он и так будет выключен естественно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не поленился посмотреть как это в HAL сделано. Пробрался сквозь дебри калокуба.

 

#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 */

 

Включают они его, естественно, перед калибровкой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда не ясно почему в доки сказано:

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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В доке всё чётко сказано. have been - это форма глагола Present Perfect, которая обозначает действие, полностью завершившееся к настоящему времени, то есть во время калибровки АЦП уже не должен быть в power-off.

Сказано, что АЦП должен пробыть в выключенном состоянии, как минимум, два такта. Но не сказано, что уже надо включить. Хотя, похоже, надо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сказано, что АЦП должен пробыть в выключенном состоянии, как минимум, два такта. Но не сказано, что уже надо включить. Хотя, похоже, надо.

Да, здесь наверное более уместно было бы Past Perfect, надо у лингвистов спросить:).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для STM32F303 я запускал калибровку перед включением АЦП.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для 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);

сначала калибруется потом включается. так неправильно?

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а у меня в коде для STM32F303

...

сначала калибруется потом включается. так неправильно?

А я разве не так написал? :rolleyes:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...