Professional Documents
Culture Documents
******************************************************************************
* @file stm32f4xx_hal_adc.c
* @author MCD Application Team
* @brief This file provides firmware functions to manage the following
* functionalities of the Analog to Digital Convertor (ADC) peripheral:
* + Initialization and de-initialization functions
* + IO operation functions
* + State and errors functions
*
@verbatim
==============================================================================
##### ADC Peripheral features #####
==============================================================================
[..]
(#) 12-bit, 10-bit, 8-bit or 6-bit configurable resolution.
(#) Interrupt generation at the end of conversion, end of injected conversion,
and in case of analog watchdog or overrun events
(#) Single and continuous conversion modes.
(#) Scan mode for automatic conversion of channel 0 to channel x.
(#) Data alignment with in-built data coherency.
(#) Channel-wise programmable sampling time.
(#) External trigger option with configurable polarity for both regular and
injected conversion.
(#) Dual/Triple mode (on devices with 2 ADCs or more).
(#) Configurable DMA data storage in Dual/Triple ADC mode.
(#) Configurable delay between conversions in Dual/Triple interleaved mode.
(#) ADC conversion type (refer to the datasheets).
(#) ADC supply requirements: 2.4 V to 3.6 V at full speed and down to 1.8 V at
slower speed.
(#) ADC input range: VREF(minus) = VIN = VREF(plus).
(#) DMA request generation during regular channel conversion.
(#) Configure the channels for regular group parameters (channel number,
channel rank into sequencer, ..., into regular group)
using function HAL_ADC_ConfigChannel().
(#) Optionally, for devices with several ADC instances: configure the
multimode parameters using function HAL_ADCEx_MultiModeConfigChannel().
(+) To read the ADC converted values, use the HAL_ADC_GetValue() function.
(+) Stop the ADC peripheral using HAL_ADC_Stop()
[..]
(@) You can refer to the ADC HAL driver header file for more useful macros
@endverbatim
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without
modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#ifdef HAL_ADC_MODULE_ENABLED
@endverbatim
* @{
*/
/**
* @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)
{
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
if(hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
{
assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
}
if(hadc->State == HAL_ADC_STATE_RESET)
{
/* Initialize ADC error code */
ADC_CLEAR_ERRORCODE(hadc);
/* Release Lock */
__HAL_UNLOCK(hadc);
/**
* @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)
{
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
/* Process unlocked */
__HAL_UNLOCK(hadc);
/**
* @brief Initializes the ADC MSP.
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval None
*/
__weak void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hadc);
/* NOTE : This function Should not be modified, when the callback is needed,
the HAL_ADC_MspInit could be implemented in the user file
*/
}
/**
* @brief DeInitializes the ADC MSP.
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval None
*/
__weak void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hadc);
/* NOTE : This function Should not be modified, when the callback is needed,
the HAL_ADC_MspDeInit could be implemented in the user file
*/
}
/**
* @}
*/
@endverbatim
* @{
*/
/**
* @brief Enables ADC and starts conversion of the regular channels.
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc)
{
__IO uint32_t counter = 0U;
ADC_Common_TypeDef *tmpADC_Common;
/* Process locked */
__HAL_LOCK(hadc);
/* Enable the ADC peripheral */
/* Check if ADC peripheral is disabled in order to enable it and wait during
Tstab time the ADC's stabilization */
if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON)
{
/* Enable the Peripheral */
__HAL_ADC_ENABLE(hadc);
/* Process unlocked */
/* Unlock before starting ADC conversions: in case of potential */
/* interruption, to let the process to ADC IRQ Handler. */
__HAL_UNLOCK(hadc);
/**
* @brief Disables ADC and stop conversion of regular channels.
*
* @note Caution: This function will stop also injected channels.
*
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
*
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
/* Process locked */
__HAL_LOCK(hadc);
/* Process unlocked */
__HAL_UNLOCK(hadc);
/**
* @brief Poll for regular conversion complete
* @note ADC conversion flags EOS (end of sequence) and EOC (end of
* conversion) are cleared by this function.
* @note This function cannot be used in a particular setup: ADC configured
* in DMA mode and polling for end of each conversion (ADC init
* parameter "EOCSelection" set to ADC_EOC_SINGLE_CONV).
* In this case, DMA resets the flag EOC and polling cannot be
* performed on each conversion. Nevertheless, polling can still
* be performed on the complete sequence.
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @param Timeout Timeout value in millisecond.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t
Timeout)
{
uint32_t tickstart = 0U;
/* Process unlocked */
__HAL_UNLOCK(hadc);
return HAL_ERROR;
}
/* Get tick */
tickstart = HAL_GetTick();
/* Process unlocked */
__HAL_UNLOCK(hadc);
return HAL_TIMEOUT;
}
}
}
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
{
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
}
}
/**
* @brief Poll for conversion event
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @param EventType the ADC event type.
* This parameter can be one of the following values:
* @arg ADC_AWD_EVENT: ADC Analog watch Dog event.
* @arg ADC_OVR_EVENT: ADC Overrun event.
* @param Timeout Timeout value in millisecond.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType,
uint32_t Timeout)
{
uint32_t tickstart = 0U;
/* Get tick */
tickstart = HAL_GetTick();
/* Process unlocked */
__HAL_UNLOCK(hadc);
return HAL_TIMEOUT;
}
}
}
/**
* @brief Enables the interrupt and starts ADC conversion of regular channels.
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc)
{
__IO uint32_t counter = 0U;
ADC_Common_TypeDef *tmpADC_Common;
/* Process locked */
__HAL_LOCK(hadc);
/* Process unlocked */
/* Unlock before starting ADC conversions: in case of potential */
/* interruption, to let the process to ADC IRQ Handler. */
__HAL_UNLOCK(hadc);
/**
* @brief Disables the interrupt and stop ADC conversion of regular channels.
*
* @note Caution: This function will stop also injected channels.
*
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc)
{
/* 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);
/* Process unlocked */
__HAL_UNLOCK(hadc);
/**
* @brief Handles ADC interrupt request
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval None
*/
void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc)
{
uint32_t tmp1 = 0U, tmp2 = 0U;
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
{
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
}
}
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
{
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
}
}
/* Conversion complete callback */
HAL_ADCEx_InjectedConvCpltCallback(hadc);
/* Error callback */
HAL_ADC_ErrorCallback(hadc);
/**
* @brief Enables ADC DMA request after last transfer (Single-ADC mode) and
enables ADC peripheral
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @param pData The destination Buffer address.
* @param Length The length of data to be transferred from ADC peripheral to
memory.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData,
uint32_t Length)
{
__IO uint32_t counter = 0U;
ADC_Common_TypeDef *tmpADC_Common;
/* Process locked */
__HAL_LOCK(hadc);
/* Process unlocked */
/* Unlock before starting ADC conversions: in case of potential */
/* interruption, to let the process to ADC IRQ Handler. */
__HAL_UNLOCK(hadc);
/* Manage ADC and DMA start: ADC overrun interruption, DMA start, ADC */
/* start (in case of SW start): */
/**
* @brief Disables ADC DMA (Single-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_ADC_Stop_DMA(ADC_HandleTypeDef* hadc)
{
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
/* Process locked */
__HAL_LOCK(hadc);
/* 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);
/* Process unlocked */
__HAL_UNLOCK(hadc);
/**
* @brief Gets the converted value from data register of regular channel.
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval Converted value
*/
uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc)
{
/* Return the selected ADC converted value */
return hadc->Instance->DR;
}
/**
* @brief Regular conversion complete callback in non blocking mode
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval None
*/
__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hadc);
/* NOTE : This function Should not be modified, when the callback is needed,
the HAL_ADC_ConvCpltCallback could be implemented in the user file
*/
}
/**
* @brief Regular conversion half DMA transfer callback in non blocking mode
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval None
*/
__weak void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hadc);
/* NOTE : This function Should not be modified, when the callback is needed,
the HAL_ADC_ConvHalfCpltCallback could be implemented in the user file
*/
}
/**
* @brief Analog watchdog callback in non blocking mode
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval None
*/
__weak void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hadc);
/* NOTE : This function Should not be modified, when the callback is needed,
the HAL_ADC_LevelOoutOfWindowCallback could be implemented in the user
file
*/
}
/**
* @brief Error ADC callback.
* @note In case of error due to overrun when using ADC with DMA transfer
* (HAL ADC handle paramater "ErrorCode" to state "HAL_ADC_ERROR_OVR"):
* - Reinitialize the DMA using function "HAL_ADC_Stop_DMA()".
* - If needed, restart a new ADC conversion using function
* "HAL_ADC_Start_DMA()"
* (this function is also clearing overrun flag)
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval None
*/
__weak void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hadc);
/* NOTE : This function Should not be modified, when the callback is needed,
the HAL_ADC_ErrorCallback could be implemented in the user file
*/
}
/**
* @}
*/
@endverbatim
* @{
*/
/**
* @brief Configures for the selected ADC regular channel its corresponding
* rank in the sequencer and its sample time.
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @param sConfig ADC configuration structure.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc,
ADC_ChannelConfTypeDef* sConfig)
{
__IO uint32_t counter = 0U;
ADC_Common_TypeDef *tmpADC_Common;
/* Process locked */
__HAL_LOCK(hadc);
/* For Rank 1 to 6 */
if (sConfig->Rank < 7U)
{
/* Clear the old SQx bits for the selected rank */
hadc->Instance->SQR3 &= ~ADC_SQR3_RK(ADC_SQR3_SQ1, sConfig->Rank);
if((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR))
{
/* Delay for temperature sensor stabilization time */
/* Compute number of CPU cycles to wait for */
counter = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000U));
while(counter != 0U)
{
counter--;
}
}
}
/* Process unlocked */
__HAL_UNLOCK(hadc);
/**
* @brief Configures the analog watchdog.
* @note Analog watchdog thresholds can be modified while ADC conversion
* is on going.
* In this case, some constraints must be taken into account:
* The programmed threshold values are effective from the next
* ADC EOC (end of unitary conversion).
* Considering that registers write delay may happen due to
* bus activity, this might cause an uncertainty on the
* effective timing of the new programmed threshold values.
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @param AnalogWDGConfig pointer to an ADC_AnalogWDGConfTypeDef structure
* that contains the configuration information of ADC analog watchdog.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_ADC_AnalogWDGConfig(ADC_HandleTypeDef* hadc,
ADC_AnalogWDGConfTypeDef* AnalogWDGConfig)
{
#ifdef USE_FULL_ASSERT
uint32_t tmp = 0U;
#endif /* USE_FULL_ASSERT */
#ifdef USE_FULL_ASSERT
tmp = ADC_GET_RESOLUTION(hadc);
assert_param(IS_ADC_RANGE(tmp, AnalogWDGConfig->HighThreshold));
assert_param(IS_ADC_RANGE(tmp, AnalogWDGConfig->LowThreshold));
#endif /* USE_FULL_ASSERT */
/* Process locked */
__HAL_LOCK(hadc);
if(AnalogWDGConfig->ITMode == ENABLE)
{
/* Enable the ADC Analog watchdog interrupt */
__HAL_ADC_ENABLE_IT(hadc, ADC_IT_AWD);
}
else
{
/* Disable the ADC Analog watchdog interrupt */
__HAL_ADC_DISABLE_IT(hadc, ADC_IT_AWD);
}
/* Process unlocked */
__HAL_UNLOCK(hadc);
/**
* @}
*/
@endverbatim
* @{
*/
/**
* @brief return the ADC state
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval HAL state
*/
uint32_t HAL_ADC_GetState(ADC_HandleTypeDef* hadc)
{
/* Return ADC state */
return hadc->State;
}
/**
* @brief Return the ADC error code
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval ADC Error Code
*/
uint32_t HAL_ADC_GetError(ADC_HandleTypeDef *hadc)
{
return hadc->ErrorCode;
}
/**
* @}
*/
/**
* @brief Initializes the ADCx peripheral according to the specified parameters
* in the ADC_InitStruct without initializing the ADC MSP.
* @param hadc pointer to a ADC_HandleTypeDef structure that contains
* the configuration information for the specified ADC.
* @retval None
*/
static void ADC_Init(ADC_HandleTypeDef* hadc)
{
ADC_Common_TypeDef *tmpADC_Common;
if(hadc->Init.DiscontinuousConvMode != DISABLE)
{
assert_param(IS_ADC_REGULAR_DISC_NUMBER(hadc->Init.NbrOfDiscConversion));
/**
* @brief DMA transfer complete callback.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma)
{
/* Retrieve ADC handle corresponding to current DMA handle */
ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)-
>Parent;
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
{
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
}
}
/**
* @brief DMA half transfer complete callback.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma)
{
ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)-
>Parent;
/* Conversion complete callback */
HAL_ADC_ConvHalfCpltCallback(hadc);
}
/**
* @brief DMA error callback
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void ADC_DMAError(DMA_HandleTypeDef *hdma)
{
ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)-
>Parent;
hadc->State= HAL_ADC_STATE_ERROR_DMA;
/* Set ADC error code to DMA error */
hadc->ErrorCode |= HAL_ADC_ERROR_DMA;
HAL_ADC_ErrorCallback(hadc);
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_ADC_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/