/** * @brief Returns the last ADC Master&Slave regular conversions results data * in the selected multi mode. * @param hadc: ADC handle of ADC master (handle of ADC slave must not be used) * @retval The converted data value. */ uint32_t HAL_ADCEx_MultiModeGetValue(ADC_HandleTypeDef* hadc) { uint32_t tmpDR = 0; /* Check the parameters */ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance)); /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Note: EOC flag is not cleared here by software because automatically */ /* cleared by hardware when reading register DR. */ /* On STM32F1 devices, ADC1 data register DR contains ADC2 conversions */ /* only if ADC1 DMA mode is enabled. */ tmpDR = hadc->Instance->DR; if (HAL_IS_BIT_CLR(ADC1->CR2, ADC_CR2_DMA)) { tmpDR |= (ADC2->DR << 16); } /* Return ADC converted value */ return tmpDR; }
/** * @brief Start an automatic calibration * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @param SingleDiff: Selection of single-ended or differential input * This parameter can be only of the following values: * @arg ADC_SINGLE_ENDED: Channel in mode input single ended * @retval HAL status */ HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc, uint32_t SingleDiff) { HAL_StatusTypeDef tmp_hal_status = HAL_OK; uint32_t tickstart=0; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Process locked */ __HAL_LOCK(hadc); /* Calibration prerequisite: ADC must be disabled. */ if (ADC_IS_ENABLE(hadc) == RESET) { /* Set ADC state */ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_REG_BUSY, HAL_ADC_STATE_BUSY_INTERNAL); /* Start ADC calibration */ hadc->Instance->CR |= ADC_CR_ADCAL; tickstart = HAL_GetTick(); /* Wait for calibration completion */ while(HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADCAL)) { 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); } else { /* Update ADC state machine to error */ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG); tmp_hal_status = HAL_ERROR; } /* Process unlocked */ __HAL_UNLOCK(hadc); /* Return function status */ return tmp_hal_status; }
/** * @brief Deinitializes the ADCx peripheral registers to their default reset values. * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @retval HAL status */ HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef* hadc) { /* Check ADC handle */ if(hadc == NULL) { return HAL_ERROR; } /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Change ADC state */ hadc->State = HAL_ADC_STATE_BUSY; /* DeInit the low level hardware */ HAL_ADC_MspDeInit(hadc); /* Set ADC error code to none */ hadc->ErrorCode = HAL_ADC_ERROR_NONE; /* Change ADC state */ hadc->State = HAL_ADC_STATE_RESET; /* Return function status */ return HAL_OK; }
/** * @brief Enables ADC, starts conversion of injected group with interruption. * - JEOC (end of conversion of injected group) * Each of these interruptions has its dedicated callback function. * @param hadc: ADC handle * @retval HAL status. */ HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef* hadc) { HAL_StatusTypeDef tmp_hal_status = HAL_OK; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Process locked */ __HAL_LOCK(hadc); /* Enable the ADC peripheral */ tmp_hal_status = ADC_Enable(hadc); /* Start conversion if ADC is effectively enabled */ if (tmp_hal_status != HAL_ERROR) { /* Check if a regular conversion is ongoing */ if(hadc->State == HAL_ADC_STATE_BUSY_REG) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_BUSY_INJ_REG; } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_BUSY_INJ; } /* Process unlocked */ /* Unlock before starting ADC conversions: in case of potential */ /* interruption, to let the process to ADC IRQ Handler. */ __HAL_UNLOCK(hadc); /* Set ADC error code to none */ ADC_CLEAR_ERRORCODE(hadc); /* Clear injected group conversion flag */ /* (To ensure of no unknown state from potential previous ADC operations) */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC); /* Enable end of conversion interrupt for injected channels */ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC); /* Enable conversion of injected group. */ /* If software start has been selected, conversion starts immediately. */ /* If external trigger has been selected, conversion will start at next */ /* trigger event. */ /* If automatic injected conversion is enabled, conversion will start */ /* after next regular group conversion. */ if (ADC_IS_SOFTWARE_START_INJECTED(hadc) && HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) ) { /* Enable ADC software conversion for injected channels */ SET_BIT(hadc->Instance->CR2, ADC_CR2_JSWSTART); } } /* Return function status */ return tmp_hal_status; }
/** * @brief Get ADC injected group conversion result. * @param hadc: ADC handle * @param InjectedRank: the converted ADC injected rank. * This parameter can be one of the following values: * @arg ADC_INJECTED_RANK_1: Injected Channel1 selected * @arg ADC_INJECTED_RANK_2: Injected Channel2 selected * @arg ADC_INJECTED_RANK_3: Injected Channel3 selected * @arg ADC_INJECTED_RANK_4: Injected Channel4 selected * @retval None */ uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef* hadc, uint32_t InjectedRank) { uint32_t tmp_jdr = 0; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); assert_param(IS_ADC_INJECTED_RANK(InjectedRank)); /* Clear injected group conversion flag to have similar behaviour as */ /* regular group: reading data register also clears end of conversion flag. */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC); /* Get ADC converted value */ switch(InjectedRank) { case ADC_INJECTED_RANK_4: tmp_jdr = hadc->Instance->JDR4; break; case ADC_INJECTED_RANK_3: tmp_jdr = hadc->Instance->JDR3; break; case ADC_INJECTED_RANK_2: tmp_jdr = hadc->Instance->JDR2; break; case ADC_INJECTED_RANK_1: default: tmp_jdr = hadc->Instance->JDR1; break; } /* Return ADC converted value */ return tmp_jdr; }
/** * @brief return the ADC state * @param hadc: ADC handle * @retval HAL state */ HAL_ADC_StateTypeDef HAL_ADC_GetState(ADC_HandleTypeDef* hadc) { /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Return ADC state */ return hadc->State; }
/** * @brief Get the calibration factor. * @param hadc: ADC handle. * @param SingleDiff: This parameter can be only: * @arg ADC_SINGLE_ENDED: Channel in mode input single ended. * @retval Calibration value. */ uint32_t HAL_ADCEx_Calibration_GetValue(ADC_HandleTypeDef* hadc, uint32_t SingleDiff) { /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff)); /* Return the ADC calibration value */ return ((hadc->Instance->CALFACT) & 0x0000007F); }
/** * @brief Initializes the ADCx peripheral according to the specified parameters * in the ADC_InitStruct and initializes the ADC MSP. * * @note This function is used to configure the global features of the ADC ( * ClockPrescaler, Resolution, Data Alignment and number of conversion), however, * the rest of the configuration parameters are specific to the regular * channels group (scan mode activation, continuous mode activation, * External trigger source and edge, DMA continuous request after the * last transfer and End of conversion selection). * * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @retval HAL status */ HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc) { /* Check ADC handle */ if(hadc == NULL) { return HAL_ERROR; } /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); assert_param(IS_ADC_CLOCKPRESCALER(hadc->Init.ClockPrescaler)); assert_param(IS_ADC_RESOLUTION(hadc->Init.Resolution)); assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ScanConvMode)); assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); assert_param(IS_ADC_EXT_TRIG(hadc->Init.ExternalTrigConv)); assert_param(IS_ADC_DATA_ALIGN(hadc->Init.DataAlign)); assert_param(IS_ADC_REGULAR_LENGTH(hadc->Init.NbrOfConversion)); assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DMAContinuousRequests)); assert_param(IS_ADC_EOCSelection(hadc->Init.EOCSelection)); assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DiscontinuousConvMode)); if(hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START) { assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge)); } if(hadc->State == HAL_ADC_STATE_RESET) { /* Allocate lock resource and initialize it */ hadc->Lock = HAL_UNLOCKED; /* Init the low level hardware */ HAL_ADC_MspInit(hadc); } /* Initialize the ADC state */ hadc->State = HAL_ADC_STATE_BUSY; /* Set ADC parameters */ ADC_Init(hadc); /* Set ADC error code to none */ hadc->ErrorCode = HAL_ADC_ERROR_NONE; /* Initialize the ADC state */ hadc->State = HAL_ADC_STATE_READY; /* Release Lock */ __HAL_UNLOCK(hadc); /* Return function status */ return HAL_OK; }
/** * @brief Initialize some features of ADC group regular. * @note These parameters have an impact on ADC scope: ADC group regular. * Refer to corresponding unitary functions into * @ref ADC_LL_EF_Configuration_ADC_Group_Regular * (functions with prefix "REG"). * @note The setting of these parameters by function @ref LL_ADC_Init() * is conditioned to ADC state: * ADC instance must be disabled. * This condition is applied to all ADC features, for efficiency * and compatibility over all STM32 families. However, the different * features can be set under different ADC state conditions * (setting possible with ADC enabled without conversion on going, * ADC enabled with conversion on going, ...) * Each feature can be updated afterwards with a unitary function * and potentially with ADC in a different state than disabled, * refer to description of each function for setting * conditioned to ADC state. * @note After using this function, other features must be configured * using LL unitary functions. * The minimum configuration remaining to be done is: * - Set ADC group regular sequencer: * map channel on rank corresponding to channel number. * Refer to function @ref LL_ADC_REG_SetSequencerChannels(); * - Set ADC channel sampling time * Refer to function LL_ADC_SetChannelSamplingTime(); * @param ADCx ADC instance * @param ADC_REG_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure * @retval An ErrorStatus enumeration value: * - SUCCESS: ADC registers are initialized * - ERROR: ADC registers are not initialized */ ErrorStatus LL_ADC_REG_Init(ADC_TypeDef *ADCx, LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct) { ErrorStatus status = SUCCESS; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(ADCx)); assert_param(IS_LL_ADC_REG_TRIG_SOURCE(ADC_REG_InitStruct->TriggerSource)); assert_param(IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(ADC_REG_InitStruct->SequencerDiscont)); assert_param(IS_LL_ADC_REG_CONTINUOUS_MODE(ADC_REG_InitStruct->ContinuousMode)); assert_param(IS_LL_ADC_REG_DMA_TRANSFER(ADC_REG_InitStruct->DMATransfer)); assert_param(IS_LL_ADC_REG_OVR_DATA_BEHAVIOR(ADC_REG_InitStruct->Overrun)); /* Note: Hardware constraint (refer to description of this function): */ /* ADC instance must be disabled. */ if(LL_ADC_IsEnabled(ADCx) == 0U) { /* Configuration of ADC hierarchical scope: */ /* - ADC group regular */ /* - Set ADC group regular trigger source */ /* - Set ADC group regular sequencer discontinuous mode */ /* - Set ADC group regular continuous mode */ /* - Set ADC group regular conversion data transfer: no transfer or */ /* transfer by DMA, and DMA requests mode */ /* - Set ADC group regular overrun behavior */ /* Note: On this STM32 serie, ADC trigger edge is set to value 0x0 by */ /* setting of trigger source to SW start. */ MODIFY_REG(ADCx->CFGR1, ADC_CFGR1_EXTSEL | ADC_CFGR1_EXTEN | ADC_CFGR1_DISCEN | ADC_CFGR1_CONT | ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG | ADC_CFGR1_OVRMOD , ADC_REG_InitStruct->TriggerSource | ADC_REG_InitStruct->SequencerDiscont | ADC_REG_InitStruct->ContinuousMode | ADC_REG_InitStruct->DMATransfer | ADC_REG_InitStruct->Overrun ); } else { /* Initialization error: ADC instance is not disabled. */ status = ERROR; } return status; }
/** * @brief Stop conversion of injected channels, disable interruption of * end-of-conversion. Disable ADC peripheral if no regular conversion * is on going. * @note If ADC must be disabled and if conversion is on going on * regular group, function HAL_ADC_Stop must be used to stop both * injected and regular groups, and disable the ADC. * @note If injected group mode auto-injection is enabled, * function HAL_ADC_Stop must be used. * @param hadc: ADC handle * @retval None */ HAL_StatusTypeDef HAL_ADCEx_InjectedStop_IT(ADC_HandleTypeDef* hadc) { HAL_StatusTypeDef tmp_hal_status = HAL_OK; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Process locked */ __HAL_LOCK(hadc); /* Stop potential conversion and disable ADC peripheral */ /* Conditioned to: */ /* - No conversion on the other group (regular group) is intended to */ /* continue (injected and regular groups stop conversion and ADC disable */ /* are common) */ /* - In case of auto-injection mode, HAL_ADC_Stop must be used. */ if(((hadc->State & HAL_ADC_STATE_REG_BUSY) == RESET) && HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) ) { /* Stop potential conversion on going, on regular and injected groups */ /* Disable ADC peripheral */ __HAL_ADC_DISABLE(hadc); /* Check if ADC is effectively disabled */ if(HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_ADON)) { /* Disable ADC end of conversion interrupt for injected channels */ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC); /* Set ADC state */ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY, HAL_ADC_STATE_READY); } } else { /* Update ADC state machine to error */ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG); tmp_hal_status = HAL_ERROR; } /* Process unlocked */ __HAL_UNLOCK(hadc); /* Return function status */ return tmp_hal_status; }
/** * @brief Disables ADC DMA (multi-ADC mode) and disables ADC peripheral * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @retval HAL status */ HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef* hadc) { HAL_StatusTypeDef tmp_hal_status = HAL_OK; ADC_Common_TypeDef *tmpADC_Common; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Process locked */ __HAL_LOCK(hadc); /* Stop potential conversion on going, on regular and injected groups */ /* Disable ADC peripheral */ __HAL_ADC_DISABLE(hadc); /* Pointer to the common control register to which is belonging hadc */ /* (Depending on STM32F4 product, there may be up to 3 ADC and 1 common */ /* control register) */ tmpADC_Common = ADC_COMMON_REGISTER(hadc); /* Check if ADC is effectively disabled */ if(HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_ADON)) { /* Disable the selected ADC DMA mode for multimode */ tmpADC_Common->CCR &= ~ADC_CCR_DDS; /* Disable the DMA channel (in case of DMA in circular mode or stop while */ /* DMA transfer is on going) */ tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle); /* Disable ADC overrun interrupt */ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR); /* Set ADC state */ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY, HAL_ADC_STATE_READY); } /* Process unlocked */ __HAL_UNLOCK(hadc); /* Return function status */ return tmp_hal_status; }
/** * @brief Stop conversion of injected channels. Disable ADC peripheral if * no regular conversion is on going. * @note If ADC must be disabled with this function and if regular conversion * is on going, function HAL_ADC_Stop must be used preliminarily. * @note In case of auto-injection mode, HAL_ADC_Stop must be used. * @param hadc: ADC handle * @retval None */ HAL_StatusTypeDef HAL_ADCEx_InjectedStop(ADC_HandleTypeDef* hadc) { HAL_StatusTypeDef tmpHALStatus = HAL_OK; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Process locked */ __HAL_LOCK(hadc); /* Stop potential conversion and disable ADC peripheral */ /* Conditioned to: */ /* - No conversion on the other group (regular group) is intended to */ /* continue (injected and regular groups stop conversion and ADC disable */ /* are common) */ /* - In case of auto-injection mode, HAL_ADC_Stop must be used. */ if((hadc->State != HAL_ADC_STATE_BUSY_REG) && (hadc->State != HAL_ADC_STATE_BUSY_INJ_REG) && HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) ) { /* Stop potential conversion on going, on regular and injected groups */ /* Disable ADC peripheral */ tmpHALStatus = ADC_ConversionStop_Disable(hadc); /* Check if ADC is effectively disabled */ if (tmpHALStatus != HAL_ERROR) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_READY; } } else { /* Update ADC state machine to error */ hadc->State = HAL_ADC_STATE_ERROR; tmpHALStatus = HAL_ERROR; } /* Process unlocked */ __HAL_UNLOCK(hadc); /* Return function status */ return tmpHALStatus; }
/** * @brief Initialize some features of ADC instance. * @note These parameters have an impact on ADC scope: ADC instance. * Affects both group regular and group injected (availability * of ADC group injected depends on STM32 families). * Refer to corresponding unitary functions into * @ref ADC_LL_EF_Configuration_ADC_Instance . * @note The setting of these parameters by function @ref LL_ADC_Init() * is conditioned to ADC state: * ADC instance must be disabled. * This condition is applied to all ADC features, for efficiency * and compatibility over all STM32 families. However, the different * features can be set under different ADC state conditions * (setting possible with ADC enabled without conversion on going, * ADC enabled with conversion on going, ...) * Each feature can be updated afterwards with a unitary function * and potentially with ADC in a different state than disabled, * refer to description of each function for setting * conditioned to ADC state. * @note After using this function, some other features must be configured * using LL unitary functions. * The minimum configuration remaining to be done is: * - Set ADC group regular or group injected sequencer: * map channel on the selected sequencer rank. * Refer to function @ref LL_ADC_REG_SetSequencerRanks(). * - Set ADC channel sampling time * Refer to function LL_ADC_SetChannelSamplingTime(); * @param ADCx ADC instance * @param ADC_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure * @retval An ErrorStatus enumeration value: * - SUCCESS: ADC registers are initialized * - ERROR: ADC registers are not initialized */ ErrorStatus LL_ADC_Init(ADC_TypeDef *ADCx, LL_ADC_InitTypeDef *ADC_InitStruct) { ErrorStatus status = SUCCESS; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(ADCx)); assert_param(IS_LL_ADC_RESOLUTION(ADC_InitStruct->Resolution)); assert_param(IS_LL_ADC_DATA_ALIGN(ADC_InitStruct->DataAlignment)); assert_param(IS_LL_ADC_SCAN_SELECTION(ADC_InitStruct->SequencersScanMode)); /* Note: Hardware constraint (refer to description of this function): */ /* ADC instance must be disabled. */ if(LL_ADC_IsEnabled(ADCx) == 0U) { /* Configuration of ADC hierarchical scope: */ /* - ADC instance */ /* - Set ADC data resolution */ /* - Set ADC conversion data alignment */ MODIFY_REG(ADCx->CR1, ADC_CR1_RES | ADC_CR1_SCAN , ADC_InitStruct->Resolution | ADC_InitStruct->SequencersScanMode ); MODIFY_REG(ADCx->CR2, ADC_CR2_ALIGN , ADC_InitStruct->DataAlignment ); } else { /* Initialization error: ADC instance is not disabled. */ status = ERROR; } return status; }
/** * @brief Initialize some features of ADC instance. * @note These parameters have an impact on ADC scope: ADC instance. * Refer to corresponding unitary functions into * @ref ADC_LL_EF_Configuration_ADC_Instance . * @note The setting of these parameters by function @ref LL_ADC_Init() * is conditioned to ADC state: * ADC instance must be disabled. * This condition is applied to all ADC features, for efficiency * and compatibility over all STM32 families. However, the different * features can be set under different ADC state conditions * (setting possible with ADC enabled without conversion on going, * ADC enabled with conversion on going, ...) * Each feature can be updated afterwards with a unitary function * and potentially with ADC in a different state than disabled, * refer to description of each function for setting * conditioned to ADC state. * @note After using this function, some other features must be configured * using LL unitary functions. * The minimum configuration remaining to be done is: * - Set ADC group regular sequencer: * map channel on rank corresponding to channel number. * Refer to function @ref LL_ADC_REG_SetSequencerChannels(); * - Set ADC channel sampling time * Refer to function LL_ADC_SetChannelSamplingTime(); * @param ADCx ADC instance * @param ADC_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure * @retval An ErrorStatus enumeration value: * - SUCCESS: ADC registers are initialized * - ERROR: ADC registers are not initialized */ ErrorStatus LL_ADC_Init(ADC_TypeDef *ADCx, LL_ADC_InitTypeDef *ADC_InitStruct) { ErrorStatus status = SUCCESS; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(ADCx)); assert_param(IS_LL_ADC_CLOCK(ADC_InitStruct->Clock)); assert_param(IS_LL_ADC_RESOLUTION(ADC_InitStruct->Resolution)); assert_param(IS_LL_ADC_DATA_ALIGN(ADC_InitStruct->DataAlignment)); assert_param(IS_LL_ADC_LOW_POWER(ADC_InitStruct->LowPowerMode)); /* Note: Hardware constraint (refer to description of this function): */ /* ADC instance must be disabled. */ if(LL_ADC_IsEnabled(ADCx) == 0U) { /* Configuration of ADC hierarchical scope: */ /* - ADC instance */ /* - Set ADC data resolution */ /* - Set ADC conversion data alignment */ /* - Set ADC low power mode */ MODIFY_REG(ADCx->CFGR1, ADC_CFGR1_RES | ADC_CFGR1_ALIGN | ADC_CFGR1_WAIT | ADC_CFGR1_AUTOFF , ADC_InitStruct->Resolution | ADC_InitStruct->DataAlignment | ADC_InitStruct->LowPowerMode ); } else { /* Initialization error: ADC instance is not disabled. */ status = ERROR; } return status; }
/** * @brief Set the calibration factor to overwrite automatic conversion result. * ADC must be enabled and no conversion is ongoing. * @param hadc: ADC handle * @param SingleDiff: This parameter can be only: * @arg ADC_SINGLE_ENDED: Channel in mode input single ended. * @param CalibrationFactor: Calibration factor (coded on 7 bits maximum) * @retval HAL state */ HAL_StatusTypeDef HAL_ADCEx_Calibration_SetValue(ADC_HandleTypeDef* hadc, uint32_t SingleDiff, uint32_t CalibrationFactor) { HAL_StatusTypeDef tmp_hal_status = HAL_OK; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff)); assert_param(IS_ADC_CALFACT(CalibrationFactor)); /* Process locked */ __HAL_LOCK(hadc); /* Verification of hardware constraints before modifying the calibration */ /* factors register: ADC must be enabled, no conversion on going. */ if ( (ADC_IS_ENABLE(hadc) != RESET) && (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET) ) { /* Set the selected ADC calibration value */ hadc->Instance->CALFACT &= ~ADC_CALFACT_CALFACT; hadc->Instance->CALFACT |= CalibrationFactor; } else { /* Update ADC state machine to error */ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL); /* Update ADC state machine to error */ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL); /* Update ADC state machine to error */ tmp_hal_status = HAL_ERROR; } /* Process unlocked */ __HAL_UNLOCK(hadc); /* Return function status */ return tmp_hal_status; }
/** * @brief De-initialize registers of the selected ADC instance * to their default reset values. * @note To reset all ADC instances quickly (perform a hard reset), * use function @ref LL_ADC_CommonDeInit(). * @param ADCx ADC instance * @retval An ErrorStatus enumeration value: * - SUCCESS: ADC registers are de-initialized * - ERROR: ADC registers are not de-initialized */ ErrorStatus LL_ADC_DeInit(ADC_TypeDef *ADCx) { ErrorStatus status = SUCCESS; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(ADCx)); /* Disable ADC instance if not already disabled. */ if(LL_ADC_IsEnabled(ADCx) == 1U) { /* Set ADC group regular trigger source to SW start to ensure to not */ /* have an external trigger event occurring during the conversion stop */ /* ADC disable process. */ LL_ADC_REG_SetTriggerSource(ADCx, LL_ADC_REG_TRIG_SOFTWARE); /* Set ADC group injected trigger source to SW start to ensure to not */ /* have an external trigger event occurring during the conversion stop */ /* ADC disable process. */ LL_ADC_INJ_SetTriggerSource(ADCx, LL_ADC_INJ_TRIG_SOFTWARE); /* Disable the ADC instance */ LL_ADC_Disable(ADCx); } /* Check whether ADC state is compliant with expected state */ /* (hardware requirements of bits state to reset registers below) */ if(READ_BIT(ADCx->CR2, ADC_CR2_ADON) == 0U) { /* ========== Reset ADC registers ========== */ /* Reset register SR */ CLEAR_BIT(ADCx->SR, ( LL_ADC_FLAG_STRT | LL_ADC_FLAG_JSTRT | LL_ADC_FLAG_EOS | LL_ADC_FLAG_JEOS | LL_ADC_FLAG_AWD1 ) ); /* Reset register CR1 */ #if defined (STM32F103x6) || defined (STM32F103xB) || defined (STM32F105xC) || defined (STM32F107xC) || defined (STM32F103xE) || defined (STM32F103xG) CLEAR_BIT(ADCx->CR1, ( ADC_CR1_AWDEN | ADC_CR1_JAWDEN | ADC_CR1_DUALMOD | ADC_CR1_DISCNUM | ADC_CR1_JDISCEN | ADC_CR1_DISCEN | ADC_CR1_JAUTO | ADC_CR1_AWDSGL | ADC_CR1_SCAN | ADC_CR1_JEOCIE | ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_AWDCH ) ); #else CLEAR_BIT(ADCx->CR1, ( ADC_CR1_AWDEN | ADC_CR1_JAWDEN | ADC_CR1_DISCNUM | ADC_CR1_JDISCEN | ADC_CR1_DISCEN | ADC_CR1_JAUTO | ADC_CR1_AWDSGL | ADC_CR1_SCAN | ADC_CR1_JEOCIE | ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_AWDCH ) ); #endif /* Reset register CR2 */ CLEAR_BIT(ADCx->CR2, ( ADC_CR2_TSVREFE | ADC_CR2_SWSTART | ADC_CR2_EXTTRIG | ADC_CR2_EXTSEL | ADC_CR2_JSWSTART | ADC_CR2_JEXTTRIG | ADC_CR2_JEXTSEL | ADC_CR2_ALIGN | ADC_CR2_DMA | ADC_CR2_RSTCAL | ADC_CR2_CAL | ADC_CR2_CONT | ADC_CR2_ADON ) ); /* Reset register SMPR1 */ CLEAR_BIT(ADCx->SMPR1, ( ADC_SMPR1_SMP17 | ADC_SMPR1_SMP16 | ADC_SMPR1_SMP15 | ADC_SMPR1_SMP14 | ADC_SMPR1_SMP13 | ADC_SMPR1_SMP12 | ADC_SMPR1_SMP11 | ADC_SMPR1_SMP10) ); /* Reset register SMPR2 */ CLEAR_BIT(ADCx->SMPR2, ( ADC_SMPR2_SMP9 | ADC_SMPR2_SMP8 | ADC_SMPR2_SMP7 | ADC_SMPR2_SMP6 | ADC_SMPR2_SMP5 | ADC_SMPR2_SMP4 | ADC_SMPR2_SMP3 | ADC_SMPR2_SMP2 | ADC_SMPR2_SMP1 | ADC_SMPR2_SMP0) ); /* Reset register JOFR1 */ CLEAR_BIT(ADCx->JOFR1, ADC_JOFR1_JOFFSET1); /* Reset register JOFR2 */ CLEAR_BIT(ADCx->JOFR2, ADC_JOFR2_JOFFSET2); /* Reset register JOFR3 */ CLEAR_BIT(ADCx->JOFR3, ADC_JOFR3_JOFFSET3); /* Reset register JOFR4 */ CLEAR_BIT(ADCx->JOFR4, ADC_JOFR4_JOFFSET4); /* Reset register HTR */ SET_BIT(ADCx->HTR, ADC_HTR_HT); /* Reset register LTR */ CLEAR_BIT(ADCx->LTR, ADC_LTR_LT); /* Reset register SQR1 */ CLEAR_BIT(ADCx->SQR1, ( ADC_SQR1_L | ADC_SQR1_SQ16 | ADC_SQR1_SQ15 | ADC_SQR1_SQ14 | ADC_SQR1_SQ13) ); /* Reset register SQR2 */ CLEAR_BIT(ADCx->SQR2, ( ADC_SQR2_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10 | ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7) ); /* Reset register JSQR */ CLEAR_BIT(ADCx->JSQR, ( ADC_JSQR_JL | ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3 | ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1 ) ); /* Reset register DR */ /* bits in access mode read only, no direct reset applicable */ /* Reset registers JDR1, JDR2, JDR3, JDR4 */ /* bits in access mode read only, no direct reset applicable */ } return status; }
/** * @brief Start an automatic calibration * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @param SingleDiff: Selection of single-ended or differential input * This parameter can be only of the following values: * @arg ADC_SINGLE_ENDED: Channel in mode input single ended * @retval HAL status */ HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc, uint32_t SingleDiff) { uint32_t tickstart = 0; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff)); /* Process locked */ __HAL_LOCK(hadc); /* Disable the ADC (if not already disabled) */ if (__HAL_ADC_IS_ENABLED(hadc) != RESET ) { /* Check if conditions to disable the ADC are fulfilled */ if (__HAL_ADC_DISABLING_CONDITIONS(hadc) != RESET) { __HAL_ADC_DISABLE(hadc); } else { hadc->State= HAL_ADC_STATE_ERROR; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } /* Wait for ADC effectively disabled */ /* Get timeout */ tickstart = HAL_GetTick(); /* Wait for disabling completion */ while(HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADEN)) { /* Check for the Timeout */ if(ADC_DISABLE_TIMEOUT != HAL_MAX_DELAY) { if((HAL_GetTick() - tickstart ) > ADC_DISABLE_TIMEOUT) { hadc->State= HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_TIMEOUT; } } } } /* Start ADC calibration */ hadc->Instance->CR |= ADC_CR_ADCAL; /* Get timeout */ tickstart = HAL_GetTick(); /* Wait for calibration completion */ while(HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADCAL)) { /* Check for the Timeout */ if(ADC_CALIBRATION_TIMEOUT != HAL_MAX_DELAY) { if((HAL_GetTick() - tickstart ) > ADC_CALIBRATION_TIMEOUT) { hadc->State= HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_TIMEOUT; } } } /* Process unlocked */ __HAL_UNLOCK(hadc); /* Return function status */ return HAL_OK; }
/** * @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 = 0; /* 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_ERROR) { /* Hardware prerequisite: delay before starting the calibration. */ /* - Computation of CPU clock cycles corresponding to ADC clock cycles. */ /* - Wait for the expected ADC clock cycles delay */ wait_loop_index = ((SystemCoreClock / HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_ADC)) * ADC_PRECALIBRATION_DELAY_ADCCLOCKCYCLES ); while(wait_loop_index != 0) { 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 */ hadc->State = HAL_ADC_STATE_ERROR; /* 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 */ hadc->State = HAL_ADC_STATE_ERROR; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } } } /* Process unlocked */ __HAL_UNLOCK(hadc); /* Return function status */ return tmp_hal_status; }
/** * @brief Wait for injected group conversion to be completed. * @param hadc: ADC handle * @param Timeout: Timeout value in millisecond. * @retval HAL status */ HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout) { uint32_t tickstart; /* Variables for polling in case of scan mode enabled and polling for each */ /* conversion. */ __IO uint32_t Conversion_Timeout_CPU_cycles = 0; uint32_t Conversion_Timeout_CPU_cycles_max = 0; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Get timeout */ tickstart = HAL_GetTick(); /* Polling for end of conversion: differentiation if single/sequence */ /* conversion. */ /* For injected group, flag JEOC is set only at the end of the sequence, */ /* not for each conversion within the sequence. */ /* - If single conversion for injected group (scan mode disabled or */ /* InjectedNbrOfConversion ==1), flag jEOC is used to determine the */ /* conversion completion. */ /* - If sequence conversion for injected group (scan mode enabled and */ /* InjectedNbrOfConversion >=2), flag JEOC is set only at the end of the */ /* sequence. */ /* To poll for each conversion, the maximum conversion time is computed */ /* from ADC conversion time (selected sampling time + conversion time of */ /* 12.5 ADC clock cycles) and APB2/ADC clock prescalers (depending on */ /* settings, conversion time range can be from 28 to 32256 CPU cycles). */ if ((hadc->Instance->JSQR & ADC_JSQR_JL) == RESET) { /* Wait until End of Conversion flag is raised */ while(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_JEOC)) { /* Check if timeout is disabled (set to infinite wait) */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick() - tickstart ) > Timeout)) { /* Update ADC state machine to timeout */ hadc->State = HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } } } } else { /* Poll with maximum conversion time */ /* - Computation of CPU clock cycles corresponding to ADC clock cycles */ /* and ADC maximum conversion cycles on all channels. */ /* - Wait for the expected ADC clock cycles delay */ Conversion_Timeout_CPU_cycles_max = ((SystemCoreClock / HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_ADC)) * ADC_CONVCYCLES_MAX_RANGE(hadc) ); while(Conversion_Timeout_CPU_cycles < Conversion_Timeout_CPU_cycles_max) { /* Check if timeout is disabled (set to infinite wait) */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) { /* Update ADC state machine to timeout */ hadc->State = HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } } Conversion_Timeout_CPU_cycles ++; } } /* Clear injected group conversion flag (and regular conversion flag raised */ /* simultaneously) */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JSTRT | ADC_FLAG_JEOC | ADC_FLAG_EOC); /* Update state machine on conversion status if not in error state */ if(hadc->State != HAL_ADC_STATE_ERROR) { /* Update ADC state machine */ if(hadc->State != HAL_ADC_STATE_EOC_INJ_REG) { if(hadc->State == HAL_ADC_STATE_EOC_REG) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ_REG; } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ; } } } /* Return ADC state */ return HAL_OK; }
/** * @brief Configures the ADC injected group and the selected channel to be * linked to the injected group. * @note Possibility to update parameters on the fly: * This function initializes injected group, following calls to this * function can be used to reconfigure some parameters of structure * "ADC_InjectionConfTypeDef" on the fly, without reseting the ADC. * The setting of these parameters is conditioned to ADC state: * this function must be called when ADC is not under conversion. * @param hadc: ADC handle * @param sConfigInjected: Structure of ADC injected group and ADC channel for * injected group. * @retval None */ HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef* hadc, ADC_InjectionConfTypeDef* sConfigInjected) { HAL_StatusTypeDef tmp_hal_status = HAL_OK; __IO uint32_t wait_loop_index = 0; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); assert_param(IS_ADC_CHANNEL(sConfigInjected->InjectedChannel)); assert_param(IS_ADC_SAMPLE_TIME(sConfigInjected->InjectedSamplingTime)); assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->AutoInjectedConv)); assert_param(IS_ADC_EXTTRIGINJEC(sConfigInjected->ExternalTrigInjecConv)); assert_param(IS_ADC_RANGE(sConfigInjected->InjectedOffset)); if(hadc->Init.ScanConvMode != ADC_SCAN_DISABLE) { assert_param(IS_ADC_INJECTED_RANK(sConfigInjected->InjectedRank)); assert_param(IS_ADC_INJECTED_NB_CONV(sConfigInjected->InjectedNbrOfConversion)); assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->InjectedDiscontinuousConvMode)); } /* Process locked */ __HAL_LOCK(hadc); /* Configuration of injected group sequencer: */ /* - if scan mode is disabled, injected channels sequence length is set to */ /* 0x00: 1 channel converted (channel on regular rank 1) */ /* Parameter "InjectedNbrOfConversion" is discarded. */ /* Note: Scan mode is present by hardware on this device and, if */ /* disabled, discards automatically nb of conversions. Anyway, nb of */ /* conversions is forced to 0x00 for alignment over all STM32 devices. */ /* - if scan mode is enabled, injected channels sequence length is set to */ /* parameter "InjectedNbrOfConversion". */ if (hadc->Init.ScanConvMode == ADC_SCAN_DISABLE) { if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1) { /* Clear the old SQx bits for all injected ranks */ MODIFY_REG(hadc->Instance->JSQR , ADC_JSQR_JL | ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3 | ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1 , ADC_JSQR_RK_JL(sConfigInjected->InjectedChannel, ADC_INJECTED_RANK_1, 0x01) ); } /* If another injected rank than rank1 was intended to be set, and could */ /* not due to ScanConvMode disabled, error is reported. */ else { /* Update ADC state machine to error */ hadc->State = HAL_ADC_STATE_ERROR; tmp_hal_status = HAL_ERROR; } } else { /* Since injected channels rank conv. order depends on total number of */ /* injected conversions, selected rank must be below or equal to total */ /* number of injected conversions to be updated. */ if (sConfigInjected->InjectedRank <= sConfigInjected->InjectedNbrOfConversion) { /* Clear the old SQx bits for the selected rank */ /* Set the SQx bits for the selected rank */ MODIFY_REG(hadc->Instance->JSQR , ADC_JSQR_JL | ADC_JSQR_RK_JL(ADC_JSQR_JSQ1, sConfigInjected->InjectedRank, sConfigInjected->InjectedNbrOfConversion) , ADC_JSQR_JL_SHIFT(sConfigInjected->InjectedNbrOfConversion) | ADC_JSQR_RK_JL(sConfigInjected->InjectedChannel, sConfigInjected->InjectedRank, sConfigInjected->InjectedNbrOfConversion) ); } else { /* Clear the old SQx bits for the selected rank */ MODIFY_REG(hadc->Instance->JSQR , ADC_JSQR_JL | ADC_JSQR_RK_JL(ADC_JSQR_JSQ1, sConfigInjected->InjectedRank, sConfigInjected->InjectedNbrOfConversion) , 0x00000000 ); } } /* Configuration of injected group */ /* Parameters update conditioned to ADC state: */ /* Parameters that can be updated only when ADC is disabled: */ /* - external trigger to start conversion */ /* Parameters update not conditioned to ADC state: */ /* - Automatic injected conversion */ /* - Injected discontinuous mode */ /* Note: In case of ADC already enabled, caution to not launch an unwanted */ /* conversion while modifying register CR2 by writing 1 to bit ADON. */ if (ADC_IS_ENABLE(hadc) == RESET) { MODIFY_REG(hadc->Instance->CR2 , ADC_CR2_JEXTSEL | ADC_CR2_ADON , ADC_CFGR_JEXTSEL(hadc, sConfigInjected->ExternalTrigInjecConv) ); } /* Configuration of injected group */ /* - Automatic injected conversion */ /* - Injected discontinuous mode */ /* Automatic injected conversion can be enabled if injected group */ /* external triggers are disabled. */ if (sConfigInjected->AutoInjectedConv == ENABLE) { if (sConfigInjected->ExternalTrigInjecConv == ADC_INJECTED_SOFTWARE_START) { SET_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO); } else { /* Update ADC state machine to error */ hadc->State = HAL_ADC_STATE_ERROR; tmp_hal_status = HAL_ERROR; } } /* Injected discontinuous can be enabled only if auto-injected mode is */ /* disabled. */ if (sConfigInjected->InjectedDiscontinuousConvMode == ENABLE) { if (sConfigInjected->AutoInjectedConv == DISABLE) { SET_BIT(hadc->Instance->CR1, ADC_CR1_JDISCEN); } else { /* Update ADC state machine to error */ hadc->State = HAL_ADC_STATE_ERROR; tmp_hal_status = HAL_ERROR; } } /* InjectedChannel sampling time configuration */ /* For channels 10 to 17 */ if (sConfigInjected->InjectedChannel >= ADC_CHANNEL_10) { MODIFY_REG(hadc->Instance->SMPR1 , ADC_SMPR1(ADC_SMPR1_SMP10, sConfigInjected->InjectedChannel) , ADC_SMPR1(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel) ); } else /* For channels 0 to 9 */ { MODIFY_REG(hadc->Instance->SMPR2 , ADC_SMPR2(ADC_SMPR2_SMP0, sConfigInjected->InjectedChannel) , ADC_SMPR2(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel) ); } /* If ADC1 InjectedChannel_16 or InjectedChannel_17 is selected, enable Temperature sensor */ /* and VREFINT measurement path. */ if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) || (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT) ) { SET_BIT(hadc->Instance->CR2, ADC_CR2_TSVREFE); } /* Configure the offset: offset enable/disable, InjectedChannel, offset value */ switch(sConfigInjected->InjectedRank) { case 1: /* Set injected channel 1 offset */ MODIFY_REG(hadc->Instance->JOFR1, ADC_JOFR1_JOFFSET1, sConfigInjected->InjectedOffset); break; case 2: /* Set injected channel 2 offset */ MODIFY_REG(hadc->Instance->JOFR2, ADC_JOFR2_JOFFSET2, sConfigInjected->InjectedOffset); break; case 3: /* Set injected channel 3 offset */ MODIFY_REG(hadc->Instance->JOFR3, ADC_JOFR3_JOFFSET3, sConfigInjected->InjectedOffset); break; case 4: default: MODIFY_REG(hadc->Instance->JOFR4, ADC_JOFR4_JOFFSET4, sConfigInjected->InjectedOffset); break; } /* If ADC1 Channel_16 or Channel_17 is selected, enable Temperature sensor */ /* and VREFINT measurement path. */ if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) || (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT) ) { /* For STM32F1 devices with several ADC: Only ADC1 can access internal */ /* measurement channels (VrefInt/TempSensor). If these channels are */ /* intended to be set on other ADC instances, an error is reported. */ if (hadc->Instance == ADC1) { if (READ_BIT(hadc->Instance->CR2, ADC_CR2_TSVREFE) == RESET) { SET_BIT(hadc->Instance->CR2, ADC_CR2_TSVREFE); if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR)) { /* Delay for temperature sensor stabilization time */ /* Compute number of CPU cycles to wait for */ wait_loop_index = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000)); while(wait_loop_index != 0) { wait_loop_index--; } } } } else { /* Update ADC state machine to error */ hadc->State = HAL_ADC_STATE_ERROR; tmp_hal_status = HAL_ERROR; } } /* Process unlocked */ __HAL_UNLOCK(hadc); /* Return function status */ return tmp_hal_status; }
/** * @brief Initialize some features of ADC group regular. * @note These parameters have an impact on ADC scope: ADC group regular. * Refer to corresponding unitary functions into * @ref ADC_LL_EF_Configuration_ADC_Group_Regular * (functions with prefix "REG"). * @note The setting of these parameters by function @ref LL_ADC_Init() * is conditioned to ADC state: * ADC instance must be disabled. * This condition is applied to all ADC features, for efficiency * and compatibility over all STM32 families. However, the different * features can be set under different ADC state conditions * (setting possible with ADC enabled without conversion on going, * ADC enabled with conversion on going, ...) * Each feature can be updated afterwards with a unitary function * and potentially with ADC in a different state than disabled, * refer to description of each function for setting * conditioned to ADC state. * @note After using this function, other features must be configured * using LL unitary functions. * The minimum configuration remaining to be done is: * - Set ADC group regular or group injected sequencer: * map channel on the selected sequencer rank. * Refer to function @ref LL_ADC_REG_SetSequencerRanks(). * - Set ADC channel sampling time * Refer to function LL_ADC_SetChannelSamplingTime(); * @param ADCx ADC instance * @param ADC_REG_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure * @retval An ErrorStatus enumeration value: * - SUCCESS: ADC registers are initialized * - ERROR: ADC registers are not initialized */ ErrorStatus LL_ADC_REG_Init(ADC_TypeDef *ADCx, LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct) { ErrorStatus status = SUCCESS; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(ADCx)); #if defined(ADC3) assert_param(IS_LL_ADC_REG_TRIG_SOURCE(ADCx, ADC_REG_InitStruct->TriggerSource)); #else assert_param(IS_LL_ADC_REG_TRIG_SOURCE(ADC_REG_InitStruct->TriggerSource)); #endif assert_param(IS_LL_ADC_REG_SEQ_SCAN_LENGTH(ADC_REG_InitStruct->SequencerLength)); if(ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE) { assert_param(IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(ADC_REG_InitStruct->SequencerDiscont)); } assert_param(IS_LL_ADC_REG_CONTINUOUS_MODE(ADC_REG_InitStruct->ContinuousMode)); assert_param(IS_LL_ADC_REG_DMA_TRANSFER(ADC_REG_InitStruct->DMATransfer)); /* Note: Hardware constraint (refer to description of this function): */ /* ADC instance must be disabled. */ if(LL_ADC_IsEnabled(ADCx) == 0U) { /* Configuration of ADC hierarchical scope: */ /* - ADC group regular */ /* - Set ADC group regular trigger source */ /* - Set ADC group regular sequencer length */ /* - Set ADC group regular sequencer discontinuous mode */ /* - Set ADC group regular continuous mode */ /* - Set ADC group regular conversion data transfer: no transfer or */ /* transfer by DMA, and DMA requests mode */ /* Note: On this STM32 serie, ADC trigger edge is set when starting */ /* ADC conversion. */ /* Refer to function @ref LL_ADC_REG_StartConversionExtTrig(). */ if(ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE) { MODIFY_REG(ADCx->CR1, ADC_CR1_DISCEN | ADC_CR1_DISCNUM , ADC_REG_InitStruct->SequencerLength | ADC_REG_InitStruct->SequencerDiscont ); } else { MODIFY_REG(ADCx->CR1, ADC_CR1_DISCEN | ADC_CR1_DISCNUM , ADC_REG_InitStruct->SequencerLength | LL_ADC_REG_SEQ_DISCONT_DISABLE ); } MODIFY_REG(ADCx->CR2, ADC_CR2_EXTSEL | ADC_CR2_CONT | ADC_CR2_DMA , ADC_REG_InitStruct->TriggerSource | ADC_REG_InitStruct->ContinuousMode | ADC_REG_InitStruct->DMATransfer ); /* Set ADC group regular sequencer length and scan direction */ /* Note: Hardware constraint (refer to description of this function): */ /* Note: If ADC instance feature scan mode is disabled */ /* (refer to ADC instance initialization structure */ /* parameter @ref SequencersScanMode */ /* or function @ref LL_ADC_SetSequencersScanMode() ), */ /* this parameter is discarded. */ LL_ADC_REG_SetSequencerLength(ADCx, ADC_REG_InitStruct->SequencerLength); } else { /* Initialization error: ADC instance is not disabled. */ status = ERROR; } return status; }
/** * @brief Configures the ADC injected group and the selected channel to be * linked to the injected group. * @note Possibility to update parameters on the fly: * This function initializes injected group, following calls to this * function can be used to reconfigure some parameters of structure * "ADC_InjectionConfTypeDef" on the fly, without reseting the ADC. * The setting of these parameters is conditioned to ADC state: * this function must be called when ADC is not under conversion. * @param hadc: ADC handle * @param sConfigInjected: Structure of ADC injected group and ADC channel for * injected group. * @retval None */ HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef* hadc, ADC_InjectionConfTypeDef* sConfigInjected) { HAL_StatusTypeDef tmpHALStatus = HAL_OK; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); assert_param(IS_ADC_CHANNEL(sConfigInjected->InjectedChannel)); assert_param(IS_ADC_SAMPLE_TIME(sConfigInjected->InjectedSamplingTime)); assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->AutoInjectedConv)); assert_param(IS_ADC_EXTTRIGINJEC(sConfigInjected->ExternalTrigInjecConv)); assert_param(IS_ADC_RANGE(sConfigInjected->InjectedOffset)); if(hadc->Init.ScanConvMode != ADC_SCAN_DISABLE) { assert_param(IS_ADC_INJECTED_RANK(sConfigInjected->InjectedRank)); assert_param(IS_ADC_INJECTED_NB_CONV(sConfigInjected->InjectedNbrOfConversion)); assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->InjectedDiscontinuousConvMode)); } if(sConfigInjected->ExternalTrigInjecConvEdge != ADC_INJECTED_SOFTWARE_START) { assert_param(IS_ADC_EXTTRIGINJEC_EDGE(sConfigInjected->ExternalTrigInjecConvEdge)); } /* Process locked */ __HAL_LOCK(hadc); /* Configuration of injected group sequencer: */ /* - if scan mode is disabled, injected channels sequence length is set to */ /* 0x00: 1 channel converted (channel on regular rank 1) */ /* Parameter "InjectedNbrOfConversion" is discarded. */ /* Note: Scan mode is present by hardware on this device and, if */ /* disabled, discards automatically nb of conversions. Anyway, nb of */ /* conversions is forced to 0x00 for alignment over all STM32 devices. */ /* - if scan mode is enabled, injected channels sequence length is set to */ /* parameter ""InjectedNbrOfConversion". */ if (hadc->Init.ScanConvMode == ADC_SCAN_DISABLE) { if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1) { /* Clear the old SQx bits for all injected ranks */ MODIFY_REG(hadc->Instance->JSQR , ADC_JSQR_JL | ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3 | ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1 , __ADC_JSQR_RK(sConfigInjected->InjectedChannel, ADC_INJECTED_RANK_1, 0x01) ); } /* If another injected rank than rank1 was intended to be set, and could */ /* not due to ScanConvMode disabled, error is reported. */ else { /* Update ADC state machine to error */ hadc->State = HAL_ADC_STATE_ERROR; tmpHALStatus = HAL_ERROR; } } else { /* Since injected channels rank conv. order depends on total number of */ /* injected conversions, selected rank must be below or equal to total */ /* number of injected conversions to be updated. */ if (sConfigInjected->InjectedRank <= sConfigInjected->InjectedNbrOfConversion) { /* Clear the old SQx bits for the selected rank */ /* Set the SQx bits for the selected rank */ MODIFY_REG(hadc->Instance->JSQR , ADC_JSQR_JL | __ADC_JSQR_RK(ADC_JSQR_JSQ1, sConfigInjected->InjectedRank, sConfigInjected->InjectedNbrOfConversion) , __ADC_JSQR_JL(sConfigInjected->InjectedNbrOfConversion) | __ADC_JSQR_RK(sConfigInjected->InjectedChannel, sConfigInjected->InjectedRank, sConfigInjected->InjectedNbrOfConversion) ); } else { /* Clear the old SQx bits for the selected rank */ MODIFY_REG(hadc->Instance->JSQR , ADC_JSQR_JL | __ADC_JSQR_RK(ADC_JSQR_JSQ1, sConfigInjected->InjectedRank, sConfigInjected->InjectedNbrOfConversion) , 0x00000000 ); } } /* Enable external trigger if trigger selection is different of software */ /* start. */ /* Note: This configuration keeps the hardware feature of parameter */ /* ExternalTrigConvEdge "trigger edge none" equivalent to */ /* software start. */ if (sConfigInjected->ExternalTrigInjecConv != ADC_INJECTED_SOFTWARE_START) { MODIFY_REG(hadc->Instance->CR2 , ADC_CR2_JEXTEN | ADC_CR2_JEXTSEL , sConfigInjected->ExternalTrigInjecConv | sConfigInjected->ExternalTrigInjecConvEdge ); } else { MODIFY_REG(hadc->Instance->CR2, ADC_CR2_JEXTEN | ADC_CR2_JEXTSEL , 0x00000000 ); } /* Configuration of injected group */ /* Parameters update conditioned to ADC state: */ /* Parameters that can be updated only when ADC is disabled: */ /* - Automatic injected conversion */ /* - Injected discontinuous mode */ if ((__HAL_ADC_IS_ENABLED(hadc) == RESET)) { hadc->Instance->CR1 &= ~(ADC_CR1_JAUTO | ADC_CR1_JDISCEN ); /* Automatic injected conversion can be enabled if injected group */ /* external triggers are disabled. */ if (sConfigInjected->AutoInjectedConv == ENABLE) { if (sConfigInjected->ExternalTrigInjecConv == ADC_INJECTED_SOFTWARE_START) { SET_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO); } else { /* Update ADC state machine to error */ hadc->State = HAL_ADC_STATE_ERROR; tmpHALStatus = HAL_ERROR; } } /* Injected discontinuous can be enabled only if auto-injected mode is */ /* disabled. */ if (sConfigInjected->InjectedDiscontinuousConvMode == ENABLE) { if (sConfigInjected->AutoInjectedConv == DISABLE) { SET_BIT(hadc->Instance->CR1, ADC_CR1_JDISCEN); } else { /* Update ADC state machine to error */ hadc->State = HAL_ADC_STATE_ERROR; tmpHALStatus = HAL_ERROR; } } } /* InjectedChannel sampling time configuration */ /* For InjectedChannels 0 to 9 */ if (sConfigInjected->InjectedChannel < ADC_CHANNEL_10) { MODIFY_REG(hadc->Instance->SMPR3, __ADC_SMPR3(ADC_SMPR3_SMP0, sConfigInjected->InjectedChannel), __ADC_SMPR3(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel) ); } /* For InjectedChannels 10 to 19 */ else if (sConfigInjected->InjectedChannel < ADC_CHANNEL_20) { MODIFY_REG(hadc->Instance->SMPR2, __ADC_SMPR2(ADC_SMPR2_SMP10, sConfigInjected->InjectedChannel), __ADC_SMPR2(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel) ); } /* For InjectedChannels 20 to 26 for devices Cat.1, Cat.2, Cat.3 */ /* For InjectedChannels 20 to 29 for devices Cat4, Cat.5 */ else if (sConfigInjected->InjectedChannel <= ADC_SMPR1_CHANNEL_MAX) { MODIFY_REG(hadc->Instance->SMPR1, __ADC_SMPR1(ADC_SMPR1_SMP20, sConfigInjected->InjectedChannel), __ADC_SMPR1(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel) ); } /* For InjectedChannels 30 to 31 for devices Cat4, Cat.5 */ else { __ADC_SMPR0_CHANNEL_SET(hadc, sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel); } /* Configure the offset: offset enable/disable, InjectedChannel, offset value */ switch(sConfigInjected->InjectedRank) { case 1: /* Set injected channel 1 offset */ MODIFY_REG(hadc->Instance->JOFR1, ADC_JOFR1_JOFFSET1, sConfigInjected->InjectedOffset); break; case 2: /* Set injected channel 2 offset */ MODIFY_REG(hadc->Instance->JOFR2, ADC_JOFR2_JOFFSET2, sConfigInjected->InjectedOffset); break; case 3: /* Set injected channel 3 offset */ MODIFY_REG(hadc->Instance->JOFR3, ADC_JOFR3_JOFFSET3, sConfigInjected->InjectedOffset); break; case 4: default: MODIFY_REG(hadc->Instance->JOFR4, ADC_JOFR4_JOFFSET4, sConfigInjected->InjectedOffset); break; } /* If ADC1 Channel_16 or Channel_17 is selected, enable Temperature sensor */ /* and VREFINT measurement path. */ if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) || (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT) ) { SET_BIT(ADC->CCR, ADC_CCR_TSVREFE); } /* Process unlocked */ __HAL_UNLOCK(hadc); /* Return function status */ return tmpHALStatus; }
/** * @brief De-initialize registers of the selected ADC instance * to their default reset values. * @note To reset all ADC instances quickly (perform a hard reset), * use function @ref LL_ADC_CommonDeInit(). * @note If this functions returns error status, it means that ADC instance * is in an unknown state. * In this case, perform a hard reset using high level * clock source RCC ADC reset. * Caution: On this STM32 serie, if several ADC instances are available * on the selected device, RCC ADC reset will reset * all ADC instances belonging to the common ADC instance. * Refer to function @ref LL_ADC_CommonDeInit(). * @param ADCx ADC instance * @retval An ErrorStatus enumeration value: * - SUCCESS: ADC registers are de-initialized * - ERROR: ADC registers are not de-initialized */ ErrorStatus LL_ADC_DeInit(ADC_TypeDef *ADCx) { ErrorStatus status = SUCCESS; __IO uint32_t timeout_cpu_cycles = 0UL; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(ADCx)); /* Disable ADC instance if not already disabled. */ if(LL_ADC_IsEnabled(ADCx) == 1UL) { /* Set ADC group regular trigger source to SW start to ensure to not */ /* have an external trigger event occurring during the conversion stop */ /* ADC disable process. */ LL_ADC_REG_SetTriggerSource(ADCx, LL_ADC_REG_TRIG_SOFTWARE); /* Stop potential ADC conversion on going on ADC group regular. */ if(LL_ADC_REG_IsConversionOngoing(ADCx) != 0UL) { if(LL_ADC_REG_IsStopConversionOngoing(ADCx) == 0UL) { LL_ADC_REG_StopConversion(ADCx); } } /* Set ADC group injected trigger source to SW start to ensure to not */ /* have an external trigger event occurring during the conversion stop */ /* ADC disable process. */ LL_ADC_INJ_SetTriggerSource(ADCx, LL_ADC_INJ_TRIG_SOFTWARE); /* Stop potential ADC conversion on going on ADC group injected. */ if(LL_ADC_INJ_IsConversionOngoing(ADCx) != 0UL) { if(LL_ADC_INJ_IsStopConversionOngoing(ADCx) == 0UL) { LL_ADC_INJ_StopConversion(ADCx); } } /* Wait for ADC conversions are effectively stopped */ timeout_cpu_cycles = ADC_TIMEOUT_STOP_CONVERSION_CPU_CYCLES; while (( LL_ADC_REG_IsStopConversionOngoing(ADCx) | LL_ADC_INJ_IsStopConversionOngoing(ADCx)) == 1UL) { timeout_cpu_cycles--; if(timeout_cpu_cycles == 0UL) { /* Time-out error */ status = ERROR; break; } } /* Flush group injected contexts queue (register JSQR): */ /* Note: Bit JQM must be set to empty the contexts queue (otherwise */ /* contexts queue is maintained with the last active context). */ LL_ADC_INJ_SetQueueMode(ADCx, LL_ADC_INJ_QUEUE_2CONTEXTS_END_EMPTY); /* Disable the ADC instance */ LL_ADC_Disable(ADCx); /* Wait for ADC instance is effectively disabled */ timeout_cpu_cycles = ADC_TIMEOUT_DISABLE_CPU_CYCLES; while (LL_ADC_IsDisableOngoing(ADCx) == 1UL) { timeout_cpu_cycles--; if(timeout_cpu_cycles == 0UL) { /* Time-out error */ status = ERROR; break; } } } /* Check whether ADC state is compliant with expected state */ if(READ_BIT(ADCx->CR, ( ADC_CR_JADSTP | ADC_CR_ADSTP | ADC_CR_JADSTART | ADC_CR_ADSTART | ADC_CR_ADDIS | ADC_CR_ADEN ) ) == 0UL) { /* ========== Reset ADC registers ========== */ /* Reset register IER */ CLEAR_BIT(ADCx->IER, ( LL_ADC_IT_ADRDY | LL_ADC_IT_EOC | LL_ADC_IT_EOS | LL_ADC_IT_OVR | LL_ADC_IT_EOSMP | LL_ADC_IT_JEOC | LL_ADC_IT_JEOS | LL_ADC_IT_JQOVF | LL_ADC_IT_AWD1 | LL_ADC_IT_AWD2 | LL_ADC_IT_AWD3 ) ); /* Reset register ISR */ SET_BIT(ADCx->ISR, ( LL_ADC_FLAG_ADRDY | LL_ADC_FLAG_EOC | LL_ADC_FLAG_EOS | LL_ADC_FLAG_OVR | LL_ADC_FLAG_EOSMP | LL_ADC_FLAG_JEOC | LL_ADC_FLAG_JEOS | LL_ADC_FLAG_JQOVF | LL_ADC_FLAG_AWD1 | LL_ADC_FLAG_AWD2 | LL_ADC_FLAG_AWD3 ) ); /* Reset register CR */ /* - Bits ADC_CR_JADSTP, ADC_CR_ADSTP, ADC_CR_JADSTART, ADC_CR_ADSTART, */ /* ADC_CR_ADCAL, ADC_CR_ADDIS, ADC_CR_ADEN are in */ /* access mode "read-set": no direct reset applicable. */ /* - Reset Calibration mode to default setting (single ended). */ /* - Disable ADC internal voltage regulator. */ /* - Enable ADC deep power down. */ /* Note: ADC internal voltage regulator disable and ADC deep power */ /* down enable are conditioned to ADC state disabled: */ /* already done above. */ CLEAR_BIT(ADCx->CR, ADC_CR_ADVREGEN | ADC_CR_ADCALDIF); SET_BIT(ADCx->CR, ADC_CR_DEEPPWD); /* Reset register CFGR */ CLEAR_BIT(ADCx->CFGR, ( ADC_CFGR_AWD1CH | ADC_CFGR_JAUTO | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL | ADC_CFGR_JQM | ADC_CFGR_JDISCEN | ADC_CFGR_DISCNUM | ADC_CFGR_DISCEN | ADC_CFGR_AUTDLY | ADC_CFGR_CONT | ADC_CFGR_OVRMOD | ADC_CFGR_EXTEN | ADC_CFGR_EXTSEL | ADC_CFGR_RES | ADC_CFGR_DMNGT ) ); SET_BIT(ADCx->CFGR, ADC_CFGR_JQDIS); /* Reset register CFGR2 */ CLEAR_BIT(ADCx->CFGR2, ( ADC_CFGR2_LSHIFT | ADC_CFGR2_OVSR | ADC_CFGR2_RSHIFT1 | ADC_CFGR2_RSHIFT4 | ADC_CFGR2_RSHIFT3 | ADC_CFGR2_RSHIFT2 | ADC_CFGR2_RSHIFT1 | ADC_CFGR2_ROVSM | ADC_CFGR2_TROVS | ADC_CFGR2_OVSS | ADC_CFGR2_JOVSE | ADC_CFGR2_ROVSE) ); /* Reset register SMPR1 */ CLEAR_BIT(ADCx->SMPR1, ( ADC_SMPR1_SMP9 | ADC_SMPR1_SMP8 | ADC_SMPR1_SMP7 | ADC_SMPR1_SMP6 | ADC_SMPR1_SMP5 | ADC_SMPR1_SMP4 | ADC_SMPR1_SMP3 | ADC_SMPR1_SMP2 | ADC_SMPR1_SMP1) ); /* Reset register SMPR2 */ CLEAR_BIT(ADCx->SMPR2, ( ADC_SMPR2_SMP19 | ADC_SMPR2_SMP18 | ADC_SMPR2_SMP17 | ADC_SMPR2_SMP16 | ADC_SMPR2_SMP15 | ADC_SMPR2_SMP14 | ADC_SMPR2_SMP13 | ADC_SMPR2_SMP12 | ADC_SMPR2_SMP11 | ADC_SMPR2_SMP10) ); /* Reset register TR1 */ CLEAR_BIT(ADCx->LTR1, ADC_LTR_LT); SET_BIT(ADCx->HTR1, ADC_HTR_HT); CLEAR_BIT(ADCx->LTR2, ADC_LTR_LT); SET_BIT(ADCx->HTR2, ADC_HTR_HT); CLEAR_BIT(ADCx->LTR3, ADC_LTR_LT); SET_BIT(ADCx->HTR3, ADC_HTR_HT); /* Reset register SQR1 */ CLEAR_BIT(ADCx->SQR1, ( ADC_SQR1_SQ4 | ADC_SQR1_SQ3 | ADC_SQR1_SQ2 | ADC_SQR1_SQ1 | ADC_SQR1_L) ); /* Reset register SQR2 */ CLEAR_BIT(ADCx->SQR2, ( ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7 | ADC_SQR2_SQ6 | ADC_SQR2_SQ5) ); /* Reset register SQR3 */ CLEAR_BIT(ADCx->SQR3, ( ADC_SQR3_SQ14 | ADC_SQR3_SQ13 | ADC_SQR3_SQ12 | ADC_SQR3_SQ11 | ADC_SQR3_SQ10) ); /* Reset register SQR4 */ CLEAR_BIT(ADCx->SQR4, ADC_SQR4_SQ16 | ADC_SQR4_SQ15); /* Reset register JSQR */ CLEAR_BIT(ADCx->JSQR, ( ADC_JSQR_JL | ADC_JSQR_JEXTSEL | ADC_JSQR_JEXTEN | ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3 | ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1 ) ); /* Reset register DR */ /* Note: bits in access mode read only, no direct reset applicable */ /* Reset register OFR1 */ CLEAR_BIT(ADCx->OFR1, ADC_OFR1_OFFSET1 | ADC_OFR1_OFFSET1_CH | ADC_OFR1_SSATE); /* Reset register OFR2 */ CLEAR_BIT(ADCx->OFR2, ADC_OFR2_OFFSET2 | ADC_OFR2_OFFSET2_CH | ADC_OFR2_SSATE); /* Reset register OFR3 */ CLEAR_BIT(ADCx->OFR3, ADC_OFR3_OFFSET3 | ADC_OFR3_OFFSET3_CH | ADC_OFR3_SSATE); /* Reset register OFR4 */ CLEAR_BIT(ADCx->OFR4, ADC_OFR4_OFFSET4 | ADC_OFR4_OFFSET4_CH | ADC_OFR4_SSATE); /* Reset registers JDR1, JDR2, JDR3, JDR4 */ /* Note: bits in access mode read only, no direct reset applicable */ /* Reset register AWD2CR */ CLEAR_BIT(ADCx->AWD2CR, ADC_AWD2CR_AWD2CH); /* Reset register AWD3CR */ CLEAR_BIT(ADCx->AWD3CR, ADC_AWD3CR_AWD3CH); /* Reset register DIFSEL */ CLEAR_BIT(ADCx->DIFSEL, ADC_DIFSEL_DIFSEL); /* Reset register CALFACT */ CLEAR_BIT(ADCx->CALFACT, ADC_CALFACT_CALFACT_D | ADC_CALFACT_CALFACT_S); /* Reset register CALFACT2 */ CLEAR_BIT(ADCx->CALFACT2, ADC_CALFACT2_LINCALFACT); } else { /* ADC instance is in an unknown state */ /* Need to performing a hard reset of ADC instance, using high level */ /* clock source RCC ADC reset. */ /* Caution: On this STM32 serie, if several ADC instances are available */ /* on the selected device, RCC ADC reset will reset */ /* all ADC instances belonging to the common ADC instance. */ /* Caution: On this STM32 serie, if several ADC instances are available */ /* on the selected device, RCC ADC reset will reset */ /* all ADC instances belonging to the common ADC instance. */ status = ERROR; } return status; }
/** * @brief Initialize some features of ADC group injected. * @note These parameters have an impact on ADC scope: ADC group injected. * Refer to corresponding unitary functions into * @ref ADC_LL_EF_Configuration_ADC_Group_Regular * (functions with prefix "INJ"). * @note The setting of these parameters by function @ref LL_ADC_Init() * is conditioned to ADC state: * ADC instance must be disabled. * This condition is applied to all ADC features, for efficiency * and compatibility over all STM32 families. However, the different * features can be set under different ADC state conditions * (setting possible with ADC enabled without conversion on going, * ADC enabled with conversion on going, ...) * Each feature can be updated afterwards with a unitary function * and potentially with ADC in a different state than disabled, * refer to description of each function for setting * conditioned to ADC state. * @note After using this function, other features must be configured * using LL unitary functions. * The minimum configuration remaining to be done is: * - Set ADC group injected sequencer: * map channel on the selected sequencer rank. * Refer to function @ref LL_ADC_INJ_SetSequencerRanks(). * - Set ADC channel sampling time * Refer to function LL_ADC_SetChannelSamplingTime(); * @param ADCx ADC instance * @param ADC_INJ_InitStruct Pointer to a @ref LL_ADC_INJ_InitTypeDef structure * @retval An ErrorStatus enumeration value: * - SUCCESS: ADC registers are initialized * - ERROR: ADC registers are not initialized */ ErrorStatus LL_ADC_INJ_Init(ADC_TypeDef *ADCx, LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct) { ErrorStatus status = SUCCESS; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(ADCx)); #if defined(ADC3) assert_param(IS_LL_ADC_INJ_TRIG_SOURCE(ADCx, ADC_INJ_InitStruct->TriggerSource)); #else assert_param(IS_LL_ADC_INJ_TRIG_SOURCE(ADC_INJ_InitStruct->TriggerSource)); #endif assert_param(IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(ADC_INJ_InitStruct->SequencerLength)); if(ADC_INJ_InitStruct->SequencerLength != LL_ADC_INJ_SEQ_SCAN_DISABLE) { assert_param(IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(ADC_INJ_InitStruct->SequencerDiscont)); } assert_param(IS_LL_ADC_INJ_TRIG_AUTO(ADC_INJ_InitStruct->TrigAuto)); /* Note: Hardware constraint (refer to description of this function): */ /* ADC instance must be disabled. */ if(LL_ADC_IsEnabled(ADCx) == 0U) { /* Configuration of ADC hierarchical scope: */ /* - ADC group injected */ /* - Set ADC group injected trigger source */ /* - Set ADC group injected sequencer length */ /* - Set ADC group injected sequencer discontinuous mode */ /* - Set ADC group injected conversion trigger: independent or */ /* from ADC group regular */ /* Note: On this STM32 serie, ADC trigger edge is set when starting */ /* ADC conversion. */ /* Refer to function @ref LL_ADC_INJ_StartConversionExtTrig(). */ if(ADC_INJ_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE) { MODIFY_REG(ADCx->CR1, ADC_CR1_JDISCEN | ADC_CR1_JAUTO , ADC_INJ_InitStruct->SequencerDiscont | ADC_INJ_InitStruct->TrigAuto ); } else { MODIFY_REG(ADCx->CR1, ADC_CR1_JDISCEN | ADC_CR1_JAUTO , LL_ADC_REG_SEQ_DISCONT_DISABLE | ADC_INJ_InitStruct->TrigAuto ); } MODIFY_REG(ADCx->CR2, ADC_CR2_JEXTSEL , ADC_INJ_InitStruct->TriggerSource ); /* Note: Hardware constraint (refer to description of this function): */ /* Note: If ADC instance feature scan mode is disabled */ /* (refer to ADC instance initialization structure */ /* parameter @ref SequencersScanMode */ /* or function @ref LL_ADC_SetSequencersScanMode() ), */ /* this parameter is discarded. */ LL_ADC_INJ_SetSequencerLength(ADCx, ADC_INJ_InitStruct->SequencerLength); } else { /* Initialization error: ADC instance is not disabled. */ status = ERROR; } return status; }
/** * @brief Wait for injected group conversion to be completed. * @param hadc: ADC handle * @param Timeout: Timeout value in millisecond. * @retval HAL status */ HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout) { uint32_t tickstart; /* Variables for polling in case of scan mode enabled and polling for each */ /* conversion. */ /* Note: Variable "conversion_timeout_cpu_cycles" set to offset 28 CPU */ /* cycles to compensate number of CPU cycles for processing of variable */ /* "conversion_timeout_cpu_cycles_max" */ uint32_t conversion_timeout_cpu_cycles = 28; uint32_t conversion_timeout_cpu_cycles_max = 0; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Get timeout */ tickstart = HAL_GetTick(); /* Polling for end of conversion: differentiation if single/sequence */ /* conversion. */ /* For injected group, flag JEOC is set only at the end of the sequence, */ /* not for each conversion within the sequence. */ /* If setting "EOCSelection" is set to poll for each single conversion, */ /* management of polling depends on setting of injected group sequencer: */ /* - If single conversion for injected group (scan mode disabled or */ /* InjectedNbrOfConversion ==1), flag JEOC is used to determine the */ /* conversion completion. */ /* - If sequence conversion for injected group (scan mode enabled and */ /* InjectedNbrOfConversion >=2), flag JEOC is set only at the end of the */ /* sequence. */ /* To poll for each conversion, the maximum conversion time is computed */ /* from ADC conversion time (selected sampling time + conversion time of */ /* 12 ADC clock cycles) and APB2/ADC clock prescalers (depending on */ /* settings, conversion time range can vary from 8 to several thousands */ /* of CPU cycles). */ /* Note: On STM32L1, setting "EOCSelection" is related to regular group */ /* only, by hardware. For compatibility with other STM32 devices, */ /* this setting is related also to injected group by software. */ if (((hadc->Instance->JSQR & ADC_JSQR_JL) == RESET) || (hadc->Init.EOCSelection != EOC_SINGLE_CONV) ) { /* Wait until End of Conversion flag is raised */ while(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_JEOC)) { /* Check if timeout is disabled (set to infinite wait) */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) { /* Update ADC state machine to timeout */ hadc->State = HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } } } } else { /* Computation of CPU cycles corresponding to ADC conversion cycles. */ /* Retrieve ADC clock prescaler and ADC maximum conversion cycles on all */ /* channels. */ conversion_timeout_cpu_cycles_max = __ADC_GET_CLOCK_PRESCALER_DECIMAL(hadc); conversion_timeout_cpu_cycles_max *= __ADC_CONVCYCLES_MAX_RANGE(hadc); /* Poll with maximum conversion time */ while(conversion_timeout_cpu_cycles < conversion_timeout_cpu_cycles_max) { /* Check if timeout is disabled (set to infinite wait) */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) { /* Update ADC state machine to timeout */ hadc->State = HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } } conversion_timeout_cpu_cycles ++; } } /* Clear end of conversion flag of injected group if low power feature */ /* "Auto Wait" is disabled, to not interfere with this feature until data */ /* register is read using function HAL_ADCEx_InjectedGetValue(). */ if (hadc->Init.LowPowerAutoWait == DISABLE) { /* Clear injected group conversion flag */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JSTRT | ADC_FLAG_JEOC); } /* Update state machine on conversion status if not in error state */ if(hadc->State != HAL_ADC_STATE_ERROR) { /* Update ADC state machine */ if(hadc->State != HAL_ADC_STATE_EOC_INJ_REG) { if(hadc->State == HAL_ADC_STATE_EOC_REG) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ_REG; } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ; } } } /* Return ADC state */ return HAL_OK; }
/** * @brief Initialize some features of ADC group injected. * @note These parameters have an impact on ADC scope: ADC group injected. * Refer to corresponding unitary functions into * @ref ADC_LL_EF_Configuration_ADC_Group_Regular * (functions with prefix "INJ"). * @note The setting of these parameters by function @ref LL_ADC_Init() * is conditioned to ADC state: * ADC instance must be disabled. * This condition is applied to all ADC features, for efficiency * and compatibility over all STM32 families. However, the different * features can be set under different ADC state conditions * (setting possible with ADC enabled without conversion on going, * ADC enabled with conversion on going, ...) * Each feature can be updated afterwards with a unitary function * and potentially with ADC in a different state than disabled, * refer to description of each function for setting * conditioned to ADC state. * @note After using this function, other features must be configured * using LL unitary functions. * The minimum configuration remaining to be done is: * - Set ADC group injected sequencer: * map channel on the selected sequencer rank. * Refer to function @ref LL_ADC_INJ_SetSequencerRanks(). * - Set ADC channel sampling time * Refer to function LL_ADC_SetChannelSamplingTime(); * @param ADCx ADC instance * @param ADC_INJ_InitStruct Pointer to a @ref LL_ADC_INJ_InitTypeDef structure * @retval An ErrorStatus enumeration value: * - SUCCESS: ADC registers are initialized * - ERROR: ADC registers are not initialized */ ErrorStatus LL_ADC_INJ_Init(ADC_TypeDef *ADCx, LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct) { ErrorStatus status = SUCCESS; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(ADCx)); assert_param(IS_LL_ADC_INJ_TRIG_SOURCE(ADC_INJ_InitStruct->TriggerSource)); assert_param(IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(ADC_INJ_InitStruct->SequencerLength)); if(ADC_INJ_InitStruct->SequencerLength != LL_ADC_INJ_SEQ_SCAN_DISABLE) { assert_param(IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(ADC_INJ_InitStruct->SequencerDiscont)); } assert_param(IS_LL_ADC_INJ_TRIG_AUTO(ADC_INJ_InitStruct->TrigAuto)); /* Note: Hardware constraint (refer to description of this function): */ /* ADC instance must be disabled. */ if(LL_ADC_IsEnabled(ADCx) == 0UL) { /* Configuration of ADC hierarchical scope: */ /* - ADC group injected */ /* - Set ADC group injected trigger source */ /* - Set ADC group injected sequencer length */ /* - Set ADC group injected sequencer discontinuous mode */ /* - Set ADC group injected conversion trigger: independent or */ /* from ADC group regular */ /* Note: On this STM32 serie, ADC trigger edge is set to value 0x0 by */ /* setting of trigger source to SW start. */ if(ADC_INJ_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE) { MODIFY_REG(ADCx->CFGR, ADC_CFGR_JDISCEN | ADC_CFGR_JAUTO , ADC_INJ_InitStruct->SequencerDiscont | ADC_INJ_InitStruct->TrigAuto ); } else { MODIFY_REG(ADCx->CFGR, ADC_CFGR_JDISCEN | ADC_CFGR_JAUTO , LL_ADC_REG_SEQ_DISCONT_DISABLE | ADC_INJ_InitStruct->TrigAuto ); } MODIFY_REG(ADCx->JSQR, ADC_JSQR_JEXTSEL | ADC_JSQR_JEXTEN | ADC_JSQR_JL , ADC_INJ_InitStruct->TriggerSource | ADC_INJ_InitStruct->SequencerLength ); } else { /* Initialization error: ADC instance is not disabled. */ status = ERROR; } return status; }
/** * @brief De-initialize registers of the selected ADC instance * to their default reset values. * @note To reset all ADC instances quickly (perform a hard reset), * use function @ref LL_ADC_CommonDeInit(). * @note If this functions returns error status, it means that ADC instance * is in an unknown state. * In this case, perform a hard reset using high level * clock source RCC ADC reset. * Refer to function @ref LL_ADC_CommonDeInit(). * @param ADCx ADC instance * @retval An ErrorStatus enumeration value: * - SUCCESS: ADC registers are de-initialized * - ERROR: ADC registers are not de-initialized */ ErrorStatus LL_ADC_DeInit(ADC_TypeDef *ADCx) { ErrorStatus status = SUCCESS; __IO uint32_t timeout_cpu_cycles = 0U; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(ADCx)); /* Disable ADC instance if not already disabled. */ if(LL_ADC_IsEnabled(ADCx) == 1U) { /* Set ADC group regular trigger source to SW start to ensure to not */ /* have an external trigger event occurring during the conversion stop */ /* ADC disable process. */ LL_ADC_REG_SetTriggerSource(ADCx, LL_ADC_REG_TRIG_SOFTWARE); /* Stop potential ADC conversion on going on ADC group regular. */ if(LL_ADC_REG_IsConversionOngoing(ADCx) != 0U) { if(LL_ADC_REG_IsStopConversionOngoing(ADCx) == 0U) { LL_ADC_REG_StopConversion(ADCx); } } /* Wait for ADC conversions are effectively stopped */ timeout_cpu_cycles = ADC_TIMEOUT_STOP_CONVERSION_CPU_CYCLES; while (LL_ADC_REG_IsStopConversionOngoing(ADCx) == 1U) { if(timeout_cpu_cycles-- == 0U) { /* Time-out error */ status = ERROR; } } /* Disable the ADC instance */ LL_ADC_Disable(ADCx); /* Wait for ADC instance is effectively disabled */ timeout_cpu_cycles = ADC_TIMEOUT_DISABLE_CPU_CYCLES; while (LL_ADC_IsDisableOngoing(ADCx) == 1U) { if(timeout_cpu_cycles-- == 0U) { /* Time-out error */ status = ERROR; } } } /* Check whether ADC state is compliant with expected state */ if(READ_BIT(ADCx->CR, ( ADC_CR_ADSTP | ADC_CR_ADSTART | ADC_CR_ADDIS | ADC_CR_ADEN ) ) == 0U) { /* ========== Reset ADC registers ========== */ /* Reset register IER */ CLEAR_BIT(ADCx->IER, ( LL_ADC_IT_ADRDY | LL_ADC_IT_EOC | LL_ADC_IT_EOS | LL_ADC_IT_OVR | LL_ADC_IT_EOSMP | LL_ADC_IT_AWD1 ) ); /* Reset register ISR */ SET_BIT(ADCx->ISR, ( LL_ADC_FLAG_ADRDY | LL_ADC_FLAG_EOC | LL_ADC_FLAG_EOS | LL_ADC_FLAG_OVR | LL_ADC_FLAG_EOSMP | LL_ADC_FLAG_AWD1 ) ); /* Reset register CR */ /* Bits ADC_CR_ADCAL, ADC_CR_ADSTP, ADC_CR_ADSTART are in access mode */ /* "read-set": no direct reset applicable. */ /* No action on register CR */ /* Reset register CFGR1 */ CLEAR_BIT(ADCx->CFGR1, ( ADC_CFGR1_AWDCH | ADC_CFGR1_AWDEN | ADC_CFGR1_AWDSGL | ADC_CFGR1_DISCEN | ADC_CFGR1_AUTOFF | ADC_CFGR1_WAIT | ADC_CFGR1_CONT | ADC_CFGR1_OVRMOD | ADC_CFGR1_EXTEN | ADC_CFGR1_EXTSEL | ADC_CFGR1_ALIGN | ADC_CFGR1_RES | ADC_CFGR1_SCANDIR | ADC_CFGR1_DMACFG | ADC_CFGR1_DMAEN ) ); /* Reset register CFGR2 */ /* Note: Update of ADC clock mode is conditioned to ADC state disabled: */ /* already done above. */ CLEAR_BIT(ADCx->CFGR2, ADC_CFGR2_CKMODE); /* Reset register SMPR */ CLEAR_BIT(ADCx->SMPR, ADC_SMPR_SMP); /* Reset register TR */ MODIFY_REG(ADCx->TR, ADC_TR_HT | ADC_TR_LT, ADC_TR_HT); /* Reset register CHSELR */ #if defined(ADC_CCR_VBATEN) CLEAR_BIT(ADCx->CHSELR, ( ADC_CHSELR_CHSEL18 | ADC_CHSELR_CHSEL17 | ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL15 | ADC_CHSELR_CHSEL14 | ADC_CHSELR_CHSEL13 | ADC_CHSELR_CHSEL12 | ADC_CHSELR_CHSEL11 | ADC_CHSELR_CHSEL10 | ADC_CHSELR_CHSEL9 | ADC_CHSELR_CHSEL8 | ADC_CHSELR_CHSEL7 | ADC_CHSELR_CHSEL6 | ADC_CHSELR_CHSEL5 | ADC_CHSELR_CHSEL4 | ADC_CHSELR_CHSEL3 | ADC_CHSELR_CHSEL2 | ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL0 ) ); #else CLEAR_BIT(ADCx->CHSELR, ( ADC_CHSELR_CHSEL17 | ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL15 | ADC_CHSELR_CHSEL14 | ADC_CHSELR_CHSEL13 | ADC_CHSELR_CHSEL12 | ADC_CHSELR_CHSEL11 | ADC_CHSELR_CHSEL10 | ADC_CHSELR_CHSEL9 | ADC_CHSELR_CHSEL8 | ADC_CHSELR_CHSEL7 | ADC_CHSELR_CHSEL6 | ADC_CHSELR_CHSEL5 | ADC_CHSELR_CHSEL4 | ADC_CHSELR_CHSEL3 | ADC_CHSELR_CHSEL2 | ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL0 ) ); #endif /* Reset register DR */ /* bits in access mode read only, no direct reset applicable */ } else { /* ADC instance is in an unknown state */ /* Need to performing a hard reset of ADC instance, using high level */ /* clock source RCC ADC reset. */ /* Caution: On this STM32 serie, if several ADC instances are available */ /* on the selected device, RCC ADC reset will reset */ /* all ADC instances belonging to the common ADC instance. */ status = ERROR; } return status; }