828eco基于GD32H7mcu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1749 lines
69 KiB

/*!
\file gd32h75e_adc.c
\brief ADC driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
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 the copyright holder 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.
*/
#include "gd32h75e_adc.h"
/* discontinuous mode macro */
#define ADC_CHANNEL_LENGTH_SUBTRACT_ONE ((uint8_t)1U)
/* ADC routine channel macro */
#define ADC_ROUTINE_CHANNEL_RANK_ONE ((uint8_t)1U)
#define ADC_ROUTINE_CHANNEL_RANK_THREE ((uint8_t)3U)
#define ADC_ROUTINE_CHANNEL_RANK_FIVE ((uint8_t)5U)
#define ADC_ROUTINE_CHANNEL_RANK_SEVEN ((uint8_t)7U)
#define ADC_ROUTINE_CHANNEL_RANK_NINE ((uint8_t)9U)
#define ADC_ROUTINE_CHANNEL_RANK_ELEVEN ((uint8_t)11U)
#define ADC_ROUTINE_CHANNEL_RANK_THIRTEEN ((uint8_t)13U)
#define ADC_ROUTINE_CHANNEL_RANK_FIFTEEN ((uint8_t)15U)
#define ADC_ROUTINE_CHANNEL_RANK_SIXTEEN ((uint8_t)16U)
#define ADC_ROUTINE_CHANNEL_SHIFT_LENGTH ((uint8_t)16U)
/* ADC inserted channel macro */
#define ADC_INSERTED_CHANNEL_RANK_ONE ((uint8_t)1U)
#define ADC_INSERTED_CHANNEL_RANK_THREE ((uint8_t)3U)
#define ADC_INSERTED_CHANNEL_RANK_FOUR ((uint8_t)4U)
#define ADC_INSERTED_CHANNEL_SHIFT_LENGTH ((uint8_t)16U)
/* ADC inserted channel offset macro */
#define ADC_OFFSET_LENGTH ((uint8_t)3U)
#define ADC_OFFSET_SHIFT_LENGTH ((uint8_t)4U)
/* ADC IOFF0 reg offset address macro */
#define ADC_IOFF0_OFFSET ((uint32_t)0x0000000CU)
/* external trigger mode macro */
#define ROUTINE_TRIGGER_MODE ((uint8_t)28U)
#define INSERTED_TRIGGER_MODE ((uint8_t)20U)
/*!
\brief reset ADC
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_deinit(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
switch(adc_periph) {
case ADC0:
rcu_periph_reset_enable(RCU_ADC0RST);
rcu_periph_reset_disable(RCU_ADC0RST);
break;
case ADC1:
rcu_periph_reset_enable(RCU_ADC1RST);
rcu_periph_reset_disable(RCU_ADC1RST);
break;
case ADC2:
rcu_periph_reset_enable(RCU_ADC2RST);
rcu_periph_reset_disable(RCU_ADC2RST);
break;
default:
break;
}
}
}
/*!
\brief configure the ADC clock
\param[in] adc_periph: ADCx, x=0,2
\param[in] prescaler: configure ADCs prescaler ratio
only one parameter can be selected which is shown as below:
\arg ADC_CLK_SYNC_HCLK_DIV2: ADC sync clock mode HCLK div2
\arg ADC_CLK_SYNC_HCLK_DIV4: ADC sync clock mode HCLK div4
\arg ADC_CLK_SYNC_HCLK_DIV6: ADC sync clock mode HCLK div6
\arg ADC_CLK_SYNC_HCLK_DIV8: ADC sync clock mode HCLK div8
\arg ADC_CLK_SYNC_HCLK_DIV10: ADC sync clock mode HCLK div10
\arg ADC_CLK_SYNC_HCLK_DIV12: ADC sync clock mode HCLK div12
\arg ADC_CLK_SYNC_HCLK_DIV14: ADC sync clock mode HCLK div14
\arg ADC_CLK_SYNC_HCLK_DIV16: ADC sync clock mode HCLK div16
\arg ADC_CLK_ASYNC_DIV1: ADC async clock mode div1
\arg ADC_CLK_ASYNC_DIV2: ADC async clock mode div2
\arg ADC_CLK_ASYNC_DIV4: ADC async clock mode div4
\arg ADC_CLK_ASYNC_DIV6: ADC async clock mode div6
\arg ADC_CLK_ASYNC_DIV8: ADC async clock mode div8
\arg ADC_CLK_ASYNC_DIV10: ADC async clock mode div10
\arg ADC_CLK_ASYNC_DIV12: ADC async clock mode div12
\arg ADC_CLK_ASYNC_DIV16: ADC async clock mode div16
\arg ADC_CLK_ASYNC_DIV32: ADC async clock mode div32
\arg ADC_CLK_ASYNC_DIV64: ADC async clock mode div64
\arg ADC_CLK_ASYNC_DIV128: ADC async clock mode div128
\arg ADC_CLK_ASYNC_DIV256: ADC async clock mode div256
\param[out] none
\retval none
*/
void adc_clock_config(uint32_t adc_periph, uint32_t prescaler)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0002U), ERR_PERIPH);
} else if(NOT_ADC_CLK_MODE(prescaler)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ADC2 == adc_periph) {
ADC_SYNCCTL(ADC2) &= ~((uint32_t)(ADC_SYNCCTL_ADCCK | ADC_SYNCCTL_ADCSCK));
ADC_SYNCCTL(ADC2) |= (uint32_t)prescaler;
} else {
ADC_SYNCCTL(ADC0) &= ~((uint32_t)(ADC_SYNCCTL_ADCCK | ADC_SYNCCTL_ADCSCK));
ADC_SYNCCTL(ADC0) |= (uint32_t)prescaler;
}
}
}
/*!
\brief enable or disable ADC special function
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] function: the function to config
only one or more parameter can be selected which is shown as below:
\arg ADC_SCAN_MODE: scan mode select
\arg ADC_INSERTED_CHANNEL_AUTO: inserted sequence convert automatically
\arg ADC_CONTINUOUS_MODE: continuous mode select
\param[in] newvalue: ENABLE or DISABLE
\param[out] none
\retval none
*/
void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus newvalue)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0003U), ERR_PERIPH);
} else if(NOT_ADC_SPECIAL_FUNCTION_VALUE(function)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_ADC_ENABLE_DISABLE(newvalue)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0003U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ENABLE == newvalue) {
if(RESET != (function & ADC_SCAN_MODE)) {
/* enable scan mode */
ADC_CTL0(adc_periph) |= (uint32_t)ADC_SCAN_MODE;
}
if(RESET != (function & ADC_INSERTED_CHANNEL_AUTO)) {
/* enable inserted sequence convert automatically */
ADC_CTL0(adc_periph) |= (uint32_t)ADC_INSERTED_CHANNEL_AUTO;
}
if(RESET != (function & ADC_CONTINUOUS_MODE)) {
/* enable continuous mode */
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CONTINUOUS_MODE;
}
} else {
if(RESET != (function & ADC_SCAN_MODE)) {
/* disable scan mode */
ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_SCAN_MODE);
}
if(RESET != (function & ADC_INSERTED_CHANNEL_AUTO)) {
/* disable inserted sequence convert automatically */
ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_INSERTED_CHANNEL_AUTO);
}
if(RESET != (function & ADC_CONTINUOUS_MODE)) {
/* disable continuous mode */
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CONTINUOUS_MODE);
}
}
}
}
/*!
\brief configure ADC data alignment
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] data_alignment: data alignment select
only one parameter can be selected which is shown as below:
\arg ADC_DATAALIGN_RIGHT: LSB alignment
\arg ADC_DATAALIGN_LEFT: MSB alignment
\param[out] none
\retval none
*/
void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0004U), ERR_PERIPH);
} else if(NOT_ADC_DATA_ALIGNMENT(data_alignment)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0004U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ADC_DATAALIGN_RIGHT == data_alignment) {
/* LSB alignment */
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL);
} else if(ADC_DATAALIGN_LEFT == data_alignment) {
/* MSB alignment */
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_DAL;
} else {
/* illegal parameters */
}
}
}
/*!
\brief enable ADC interface
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_enable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0005U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)) {
/* enable ADC */
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON;
}
}
}
/*!
\brief disable ADC interface
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_disable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0006U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* disable ADC */
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON);
}
}
/*!
\brief configure ADC calibration mode
\param[in] adc_periph: ADCx, x=0,1
\param[in] clb_mode: calibration mode
only one parameter can be selected which is shown as below:
\arg ADC_CALIBRATION_OFFSET_MISMATCH: ADC calibration offset and mismatch mode
\arg ADC_CALIBRATION_OFFSET: ADC calibration offset mode
\param[out] none
\retval none
*/
void adc_calibration_mode_config(uint32_t adc_periph, uint32_t clb_mode)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0007U), ERR_PERIPH);
} else if(NOT_CALIBRATION_MODE(clb_mode)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0007U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ADC_CALIBRATION_OFFSET_MISMATCH == clb_mode) {
/* offset and mismatch mode */
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_CALMOD);
} else if(ADC_CALIBRATION_OFFSET == clb_mode) {
/* offset mode */
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_CALMOD;
} else {
/* illegal parameters */
}
}
}
/*!
\brief configure ADC calibration number
\param[in] adc_periph: ADCx, x=0,1
\param[in] clb_num: calibration number
only one parameter can be selected which is shown as below:
\arg ADC_CALIBRATION_NUM1: calibrate once
\arg ADC_CALIBRATION_NUM2: calibrate twice
\arg ADC_CALIBRATION_NUM4: calibrate 4 times
\arg ADC_CALIBRATION_NUM8: calibrate 8 times
\arg ADC_CALIBRATION_NUM16: calibrate 16 times
\arg ADC_CALIBRATION_NUM32: calibrate 32 times
\param[out] none
\retval none
*/
void adc_calibration_number(uint32_t adc_periph, uint32_t clb_num)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0008U), ERR_PERIPH);
} else if(NOT_ADC_CALIBRATION_NUMBER(clb_num)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0008U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_CALNUM);
ADC_CTL1(adc_periph) |= (uint32_t)clb_num;
}
}
/*!
\brief ADC calibration and reset calibration
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_calibration_enable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0009U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* reset the selected ADC calibration registers */
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_RSTCLB;
/* check the RSTCLB bit state */
while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)) {
}
/* enable ADC calibration process */
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_CLB;
/* check the CLB bit state */
while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)) {
}
}
}
/*!
\brief configure ADC resolution
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] resolution: ADC resolution
only one parameter can be selected which is shown as below:
\arg ADC_RESOLUTION_14B: 14-bit ADC resolution, for ADC0/ADC1
\arg ADC_RESOLUTION_12B: 12-bit ADC resolution, for all ADCs
\arg ADC_RESOLUTION_10B: 10-bit ADC resolution, for all ADCs
\arg ADC_RESOLUTION_8B: 8-bit ADC resolution, for all ADCs
\arg ADC_RESOLUTION_6B: 6-bit ADC resolution, only for ADC2
\param[out] none
\retval none
*/
void adc_resolution_config(uint32_t adc_periph, uint32_t resolution)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x000AU), ERR_PERIPH);
} else if(NOT_ADC_RESOLUTION(resolution)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x000AU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DRES);
if(ADC2 == adc_periph) {
if(ADC_RESOLUTION_14B == resolution) {
/* illegal parameters */
} else {
ADC_CTL0(adc_periph) |= (uint32_t)CTL0_DRES(resolution - 1U);
}
} else {
if(ADC_RESOLUTION_6B == resolution) {
/* illegal parameters */
} else {
ADC_CTL0(adc_periph) |= (uint32_t)CTL0_DRES(resolution);
}
}
}
}
/*!
\brief enable or disable ADC internal channels
\param[in] internal_channel: the internal channels
only one parameter can be selected which is shown as below:
\arg ADC_CHANNEL_INTERNAL_TEMPSENSOR: temperature sensor channel
\arg ADC_CHANNEL_INTERNAL_VREFINT: vrefint channel
\arg ADC_CHANNEL_INTERNAL_VBAT: vbat channel
\arg ADC_CHANNEL_INTERNAL_HP_TEMPSENSOR: high-precision temperature sensor channel
\param[in] newvalue: ENABLE or DISABLE
\param[out] none
\retval none
*/
void adc_internal_channel_config(uint32_t internal_channel, ControlStatus newvalue)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_CHANNEL_INTERNAL(internal_channel)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x000BU), ERR_PARAM_INVALID);
} else if(NOT_ADC_ENABLE_DISABLE(newvalue)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x000BU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ENABLE == newvalue) {
ADC_CTL1(ADC2) |= (uint32_t)internal_channel;
} else {
ADC_CTL1(ADC2) &= ~((uint32_t)internal_channel);
}
}
}
/*!
\brief enable DMA request
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_dma_mode_enable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x000CU), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* enable DMA request */
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_DMA;
}
}
/*!
\brief disable DMA request
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_dma_mode_disable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x000DU), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* disable DMA request */
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA);
}
}
/*!
\brief when DMA=1, the DMA engine issues a request at end of each routine conversion
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_dma_request_after_last_enable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x000EU), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_DDM;
}
}
/*!
\brief the DMA engine is disabled after the end of transfer signal from DMA controller is detected
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_dma_request_after_last_disable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x000FU), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DDM);
}
}
/*!
\brief enable hpdf mode
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_hpdf_mode_enable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0010U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* enable hpdf mode */
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_HPDFCFG;
}
}
/*!
\brief disable hpdf mode
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_hpdf_mode_disable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0011U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* disable hpdf mode */
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_HPDFCFG);
}
}
/*!
\brief configure ADC discontinuous mode
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] adc_sequence: select the sequence
only one parameter can be selected which is shown as below:
\arg ADC_ROUTINE_CHANNEL: routine sequence
\arg ADC_INSERTED_CHANNEL: inserted sequence
\arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of routine & inserted channel
\param[in] length: number of conversions in discontinuous mode, the number can be 1..8
for routine channel, the number has no effect for inserted channel
\param[out] none
\retval none
*/
void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_sequence, uint32_t length)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0012U), ERR_PERIPH);
} else if(NOT_ADC_SEQUENCE_EXD(adc_sequence)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
} else if(NOT_ADC_DISCONTINUOUS_MODE_LENGTH(length)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* disable discontinuous mode of routine & inserted channel */
ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_DISRC | ADC_CTL0_DISIC));
switch(adc_sequence) {
case ADC_ROUTINE_CHANNEL:
/* config the number of conversions in discontinuous mode */
ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM);
if((length <= 8U) && (length >= 1U)) {
ADC_CTL0(adc_periph) |= CTL0_DISNUM((uint32_t)(length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
}
/* enable routine sequence discontinuous mode */
ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC;
break;
case ADC_INSERTED_CHANNEL:
/* enable inserted sequence discontinuous mode */
ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC;
break;
case ADC_CHANNEL_DISCON_DISABLE:
/* disable discontinuous mode of routine & inserted channel */
default:
break;
}
}
}
/*!
\brief configure the length of routine sequence or inserted sequence
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] adc_sequence: select the sequence
only one parameter can be selected which is shown as below:
\arg ADC_ROUTINE_CHANNEL: routine sequence
\arg ADC_INSERTED_CHANNEL: inserted sequence
\param[in] length: the length of the channel
routine channel 1-16
inserted channel 1-4
\param[out] none
\retval none
*/
void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_sequence, uint32_t length)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0013U), ERR_PERIPH);
} else if(NOT_ADC_SEQUENCE(adc_sequence)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
} else if(NOT_ADC_CHANNEL_LENGTH(length)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0013U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
switch(adc_sequence) {
case ADC_ROUTINE_CHANNEL:
if((length >= 1U) && (length <= 16U)) {
ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL);
ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
}
break;
case ADC_INSERTED_CHANNEL:
if((length >= 1U) && (length <= 4U)) {
ADC_ISQ0(adc_periph) &= ~((uint32_t)ADC_ISQ0_IL);
ADC_ISQ0(adc_periph) |= ISQ0_IL((uint32_t)(length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
}
break;
default:
break;
}
}
}
/*!
\brief configure ADC routine channel
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] rank: the routine sequence rank,this parameter must be between 0 to 15
\param[in] adc_channel: the selected ADC channel
only one parameter can be selected which is shown as below:
\arg ADC_CHANNEL_x(x=0..20): ADC Channelx
\param[in] sample_time: the sample time value, 0..809 for ADC0/ADC1, 0..638 for ADC2
\param[out] none
\retval none
*/
void adc_routine_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0014U), ERR_PERIPH);
} else if(NOT_ADC_ROUTINE_SEQUENCE_RANK_VALUE(rank)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0014U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_ADC_CHANNEL(adc_channel)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0014U), ERR_PARAM_INVALID);
} else if(NOT_ADC_SAMPLE_TIME(sample_time)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0014U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t rsq;
/* configure ADC routine sequence */
if(rank < ADC_ROUTINE_CHANNEL_RANK_ONE) {
/* the routine sequence rank is smaller than one */
rsq = ADC_RSQ8(adc_periph);
rsq &= ~((uint32_t)((ADC_RSQX_RSMPN | ADC_RSQX_RSQN) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH * rank)));
rsq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
rank));
ADC_RSQ8(adc_periph) = rsq;
} else if(rank < ADC_ROUTINE_CHANNEL_RANK_THREE) {
/* the routine sequence rank is smaller than three */
rsq = ADC_RSQ7(adc_periph);
rsq &= ~((uint32_t)((ADC_RSQX_RSMPN | ADC_RSQX_RSQN) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_ONE))));
rsq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_ONE)));
ADC_RSQ7(adc_periph) = rsq;
} else if(rank < ADC_ROUTINE_CHANNEL_RANK_FIVE) {
/* the routine sequence rank is smaller than five */
rsq = ADC_RSQ6(adc_periph);
rsq &= ~((uint32_t)((ADC_RSQX_RSMPN | ADC_RSQX_RSQN) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_THREE))));
rsq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_THREE)));
ADC_RSQ6(adc_periph) = rsq;
} else if(rank < ADC_ROUTINE_CHANNEL_RANK_SEVEN) {
/* the routine sequence rank is smaller than seven */
rsq = ADC_RSQ5(adc_periph);
rsq &= ~((uint32_t)((ADC_RSQX_RSMPN | ADC_RSQX_RSQN) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_FIVE))));
rsq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_FIVE)));
ADC_RSQ5(adc_periph) = rsq;
} else if(rank < ADC_ROUTINE_CHANNEL_RANK_NINE) {
/* the routine sequence rank is smaller than nine */
rsq = ADC_RSQ4(adc_periph);
rsq &= ~((uint32_t)((ADC_RSQX_RSMPN | ADC_RSQX_RSQN) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_SEVEN))));
rsq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_SEVEN)));
ADC_RSQ4(adc_periph) = rsq;
} else if(rank < ADC_ROUTINE_CHANNEL_RANK_ELEVEN) {
/* the routine sequence rank is smaller than eleven */
rsq = ADC_RSQ3(adc_periph);
rsq &= ~((uint32_t)((ADC_RSQX_RSMPN | ADC_RSQX_RSQN) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_NINE))));
rsq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_NINE)));
ADC_RSQ3(adc_periph) = rsq;
} else if(rank < ADC_ROUTINE_CHANNEL_RANK_THIRTEEN) {
/* the routine sequence rank is smaller than thirteen */
rsq = ADC_RSQ2(adc_periph);
rsq &= ~((uint32_t)((ADC_RSQX_RSMPN | ADC_RSQX_RSQN) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_ELEVEN))));
rsq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_ELEVEN)));
ADC_RSQ2(adc_periph) = rsq;
} else if(rank < ADC_ROUTINE_CHANNEL_RANK_FIFTEEN) {
/* the routine sequence rank is smaller than fifteen */
rsq = ADC_RSQ1(adc_periph);
rsq &= ~((uint32_t)((ADC_RSQX_RSMPN | ADC_RSQX_RSQN) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_THIRTEEN))));
rsq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_THIRTEEN)));
ADC_RSQ1(adc_periph) = rsq;
} else if(rank < ADC_ROUTINE_CHANNEL_RANK_SIXTEEN) {
/* the routine sequence rank is smaller than sixteen */
rsq = ADC_RSQ0(adc_periph);
rsq &= ~((uint32_t)((ADC_RSQX_RSMPN | ADC_RSQX_RSQN) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_FIFTEEN))));
rsq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_ROUTINE_CHANNEL_SHIFT_LENGTH *
(rank - ADC_ROUTINE_CHANNEL_RANK_FIFTEEN)));
ADC_RSQ0(adc_periph) = rsq;
} else {
/* illegal parameters */
}
}
}
/*!
\brief configure ADC inserted channel
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] rank: the inserted sequencer rank,this parameter must be between 0 to 3
\param[in] adc_channel: the selected ADC channel
only one parameter can be selected which is shown as below:
\arg ADC_CHANNEL_x(x=0..20): ADC Channelx
\param[in] sample_time: The sample time value, 0..809 for ADC0/ADC1, 0..638 for ADC2
\param[out] none
\retval none
*/
void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0015U), ERR_PERIPH);
} else if(NOT_ADC_INSERTED_SEQUENCE_RANK_VALUE(rank)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0015U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_ADC_CHANNEL(adc_channel)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0015U), ERR_PARAM_INVALID);
} else if(NOT_ADC_SAMPLE_TIME(sample_time)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0015U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint8_t inserted_length, rankx;
uint32_t isq;
/* get inserted sequence length */
inserted_length = (uint8_t)GET_BITS(ADC_ISQ0(adc_periph), 20U, 21U);
rankx = ADC_OFFSET_LENGTH - inserted_length + rank;
/* configure ADC inserted sequence */
if(rankx < ADC_INSERTED_CHANNEL_RANK_ONE) {
/* the inserted sequence rank is smaller than one */
isq = ADC_ISQ2(adc_periph);
isq &= ~((uint32_t)((ADC_ISQX_ISMPN | ADC_ISQX_ISQN) << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH * rankx)));
isq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH * rankx));
ADC_ISQ2(adc_periph) = isq;
} else if(rankx < ADC_INSERTED_CHANNEL_RANK_THREE) {
/* the inserted sequence rank is smaller than three */
isq = ADC_ISQ1(adc_periph);
isq &= ~((uint32_t)((ADC_ISQX_ISMPN | ADC_ISQX_ISQN) << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH *
(rankx - ADC_INSERTED_CHANNEL_RANK_ONE))));
isq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH *
(rankx - ADC_INSERTED_CHANNEL_RANK_ONE)));
ADC_ISQ1(adc_periph) = isq;
} else if(rankx < ADC_INSERTED_CHANNEL_RANK_FOUR) {
/* the inserted sequence rank is smaller than four */
isq = ADC_ISQ0(adc_periph);
isq &= ~((uint32_t)((ADC_ISQX_ISMPN | ADC_ISQX_ISQN) << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH *
(rankx - ADC_INSERTED_CHANNEL_RANK_THREE))));
isq |= ((uint32_t)(SQX_SMP(sample_time) | adc_channel) << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH *
(rankx - ADC_INSERTED_CHANNEL_RANK_THREE)));
ADC_ISQ0(adc_periph) = isq;
} else {
/* illegal parameters */
}
}
}
/*!
\brief configure ADC inserted channel offset
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] inserted_channel : insert channel select
only one parameter can be selected which is shown as below:
\arg ADC_INSERTED_CHANNEL_0: inserted channel0
\arg ADC_INSERTED_CHANNEL_1: inserted channel1
\arg ADC_INSERTED_CHANNEL_2: inserted channel2
\arg ADC_INSERTED_CHANNEL_3: inserted channel3
\param[in] offset : the offset data
\param[out] none
\retval none
*/
void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint32_t offset)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0016U), ERR_PERIPH);
} else if(NOT_INSERTED_CHANNEL(inserted_channel)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0017U), ERR_PARAM_INVALID);
} else if(NOT_ADC_INSERTED_OFFSET_VALUE(offset)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0017U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint8_t inserted_length;
uint32_t num = 0U;
inserted_length = (uint8_t)GET_BITS(ADC_ISQ0(adc_periph), 20U, 21U);
num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel));
if(num <= ADC_OFFSET_LENGTH) {
/* calculate the offset of the register */
num = num * ADC_OFFSET_SHIFT_LENGTH;
/* config the offset of the selected channels */
REG32((adc_periph) + ADC_IOFF0_OFFSET + num) = IOFFX_IOFF((uint32_t)offset);
}
}
}
/*!
\brief configure differential mode for ADC channel
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] adc_channel: the channel use differential mode
one or more parameters can be selected which is shown as below:
\arg ADC_DIFFERENTIAL_MODE_CHANNEL_x(x=0..21), ADC_DIFFERENTIAL_MODE_CHANNEL_ALL: ADC channel for differential mode
\param[in] newvalue: ENABLE or DISABLE
\param[out] none
\retval none
*/
void adc_channel_differential_mode_config(uint32_t adc_periph, uint32_t adc_channel, ControlStatus newvalue)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0017U), ERR_PERIPH);
} else if(NOT_ADC_DIFFERENTIAL_MODE_CHANNEL(adc_channel)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0017U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_ADC_ENABLE_DISABLE(newvalue)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0017U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ENABLE == newvalue) {
ADC_DIFCTL(adc_periph) |= (uint32_t)adc_channel;
} else {
ADC_DIFCTL(adc_periph) &= ~((uint32_t)adc_channel);
}
}
}
/*!
\brief enable ADC external trigger
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] adc_sequence: select the sequence
only one parameter can be selected which is shown as below:
\arg ADC_ROUTINE_CHANNEL: routine sequence
\arg ADC_INSERTED_CHANNEL: inserted sequence
\param[in] trigger_mode: external trigger mode
only one parameter can be selected which is shown as below:
\arg EXTERNAL_TRIGGER_DISABLE: external trigger disable
\arg EXTERNAL_TRIGGER_RISING: rising edge of external trigger
\arg EXTERNAL_TRIGGER_FALLING: falling edge of external trigger
\arg EXTERNAL_TRIGGER_RISING_FALLING: rising and falling edge of external trigger
\param[out] none
\retval none
*/
void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_sequence, uint32_t trigger_mode)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0018U), ERR_PERIPH);
} else if(NOT_ADC_SEQUENCE(adc_sequence)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0018U), ERR_PARAM_INVALID);
} else if(NOT_ADC_TRIGGER_MODE(trigger_mode)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0018U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
switch(adc_sequence) {
case ADC_ROUTINE_CHANNEL:
/* configure ADC routine sequence external trigger mode */
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETMRC);
ADC_CTL1(adc_periph) |= (uint32_t)(trigger_mode << ROUTINE_TRIGGER_MODE);
break;
case ADC_INSERTED_CHANNEL:
/* configure ADC inserted sequence external trigger mode */
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETMIC);
ADC_CTL1(adc_periph) |= (uint32_t)(trigger_mode << INSERTED_TRIGGER_MODE);
break;
default:
break;
}
}
}
/*!
\brief enable ADC software trigger
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] adc_sequence: select the sequence
only one parameter can be selected which is shown as below:
\arg ADC_ROUTINE_CHANNEL: routine sequence
\arg ADC_INSERTED_CHANNEL: inserted sequence
\param[out] none
\retval none
*/
void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_sequence)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0019U), ERR_PERIPH);
} else if(NOT_ADC_SEQUENCE(adc_sequence)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0019U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* enable routine channel software trigger */
if(RESET != (adc_sequence & ADC_ROUTINE_CHANNEL)) {
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_SWRCST;
}
/* enable inserted sequence software trigger */
if(RESET != (adc_sequence & ADC_INSERTED_CHANNEL)) {
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_SWICST;
}
}
}
/*!
\brief configure end of conversion mode
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] end_selection: end of conversion mode
only one parameter can be selected which is shown as below:
\arg ADC_EOC_SET_SEQUENCE: only at the end of a sequence of routine conversions, the EOC bit is set. Overflow detection is disabled unless DMA=1.
\arg ADC_EOC_SET_CONVERSION: at the end of each routine conversion, the EOC bit is set. Overflow is detected automatically.
\param[out] none
\retval none
*/
void adc_end_of_conversion_config(uint32_t adc_periph, uint32_t end_selection)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x001AU), ERR_PERIPH);
} else if(NOT_ADC_END_OF_CONVERSION_MODE(end_selection)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x001AU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ADC_EOC_SET_SEQUENCE == end_selection) {
/* only at the end of a sequence of routine conversions, the EOC bit is set */
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_EOCM);
} else if(ADC_EOC_SET_CONVERSION == end_selection) {
/* at the end of each routine conversion, the EOC bit is set. Overflow is detected automatically */
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_EOCM;
} else {
/* illegal parameters */
}
}
}
/*!
\brief read ADC routine data register
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] none
\param[out] none
\retval the conversion value
*/
uint32_t adc_routine_data_read(uint32_t adc_periph)
{
uint32_t rdata;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x001BU), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
rdata = (ADC_RDATA(adc_periph));
}
return (uint32_t)rdata;
}
/*!
\brief read ADC inserted sequence data register
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] inserted_channel : insert channel select
only one parameter can be selected which is shown as below:
\arg ADC_INSERTED_CHANNEL_0: inserted Channel0
\arg ADC_INSERTED_CHANNEL_1: inserted channel1
\arg ADC_INSERTED_CHANNEL_2: inserted Channel2
\arg ADC_INSERTED_CHANNEL_3: inserted Channel3
\param[out] none
\retval the conversion value
*/
uint32_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel)
{
uint32_t idata;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x001CU), ERR_PERIPH);
} else if(NOT_INSERTED_CHANNEL(inserted_channel)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x001CU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* read the data of the selected channel */
switch(inserted_channel) {
case ADC_INSERTED_CHANNEL_0:
/* read the data of channel 0 */
idata = ADC_IDATA0(adc_periph);
break;
case ADC_INSERTED_CHANNEL_1:
/* read the data of channel 1 */
idata = ADC_IDATA1(adc_periph);
break;
case ADC_INSERTED_CHANNEL_2:
/* read the data of channel 2 */
idata = ADC_IDATA2(adc_periph);
break;
case ADC_INSERTED_CHANNEL_3:
/* read the data of channel 3 */
idata = ADC_IDATA3(adc_periph);
break;
default:
idata = 0U;
break;
}
}
return (uint32_t)idata;
}
/*!
\brief configure ADC analog watchdog 0 single channel
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] adc_channel: the selected ADC channel
only one parameter can be selected which is shown as below:
\arg ADC_CHANNEL_x: ADC Channelx(x=0..20)
\param[out] none
\retval none
*/
void adc_watchdog0_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x001DU), ERR_PERIPH);
} else if(NOT_ADC_CHANNEL(adc_channel)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x001DU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC |
ADC_CTL0_WD0CHSEL));
ADC_CTL0(adc_periph) |= (uint32_t)adc_channel;
ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC);
}
}
/*!
\brief configure ADC analog watchdog 0 group channel
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] adc_sequence: the sequence use analog watchdog 0
only one parameter can be selected which is shown as below:
\arg ADC_ROUTINE_CHANNEL: routine sequence
\arg ADC_INSERTED_CHANNEL: inserted sequence
\arg ADC_ROUTINE_INSERTED_CHANNEL: both routine and inserted sequence
\param[out] none
\retval none
*/
void adc_watchdog0_group_channel_enable(uint32_t adc_periph, uint8_t adc_sequence)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x001EU), ERR_PERIPH);
} else if(NOT_ADC_SEQUENC_BOTH(adc_sequence)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x001EU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC));
/* select the sequence */
switch(adc_sequence) {
case ADC_ROUTINE_CHANNEL:
ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_RWD0EN;
break;
case ADC_INSERTED_CHANNEL:
ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_IWD0EN;
break;
case ADC_ROUTINE_INSERTED_CHANNEL:
ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN);
break;
default:
break;
}
}
}
/*!
\brief disable ADC analog watchdog 0
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_watchdog0_disable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x001FU), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC |
ADC_CTL0_WD0CHSEL));
}
}
/*!
\brief configure ADC analog watchdog 1 channel
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] selection_channel: the channel use analog watchdog 1
one or more parameters can be selected which is shown as below:
\arg ADC_AWD1_2_SELECTION_CHANNEL_x, ADC_AWD1_2_SELECTION_CHANNEL_ALL: ADC channel analog watchdog 1/2 selection
\param[in] newvalue: ENABLE or DISABLE
\param[out] none
\retval none
*/
void adc_watchdog1_channel_config(uint32_t adc_periph, uint32_t selection_channel, ControlStatus newvalue)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0020U), ERR_PERIPH);
} else if(NOT_ADC_ANALOG_WATCHDOG_SEL(selection_channel)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0020U), ERR_PARAM_INVALID);
} else if(NOT_ADC_ENABLE_DISABLE(newvalue)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0020U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ENABLE == newvalue) {
ADC_WD1SR(adc_periph) |= (uint32_t)selection_channel;
} else {
ADC_WD1SR(adc_periph) &= ~((uint32_t)selection_channel);
}
}
}
/*!
\brief configure ADC analog watchdog 2 channel
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] selection_channel: the channel use analog watchdog 2
one or more parameters can be selected which is shown as below:
\arg ADC_AWD1_2_SELECTION_CHANNEL_x, ADC_AWD1_2_SELECTION_CHANNEL_ALL: ADC channel analog watchdog 1/2 selection
\param[in] newvalue: ENABLE or DISABLE
\param[out] none
\retval none
*/
void adc_watchdog2_channel_config(uint32_t adc_periph, uint32_t selection_channel, ControlStatus newvalue)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0021U), ERR_PERIPH);
} else if(NOT_ADC_ANALOG_WATCHDOG_SEL(selection_channel)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0021U), ERR_PARAM_INVALID);
} else if(NOT_ADC_ENABLE_DISABLE(newvalue)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0021U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ENABLE == newvalue) {
ADC_WD2SR(adc_periph) |= (uint32_t)selection_channel;
} else {
ADC_WD2SR(adc_periph) &= ~((uint32_t)selection_channel);
}
}
}
/*!
\brief disable ADC analog watchdog 1
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_watchdog1_disable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0022U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_WD1SR(adc_periph) &= ~((uint32_t)ADC_WD1SR_AWD1CS);
}
}
/*!
\brief disable ADC analog watchdog 2
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_watchdog2_disable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0023U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_WD2SR(adc_periph) &= ~((uint32_t)ADC_WD2SR_AWD2CS);
}
}
/*!
\brief configure ADC analog watchdog 0 threshold
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] low_threshold: analog watchdog 0 low threshold, 0..0xFFFFFF for ADC0/ADC1, 0..0xFFF for ADC2
\param[in] high_threshold: analog watchdog 0 high threshold, 0..0xFFFFFF for ADC0/ADC1, 0..0xFFF for ADC2
\param[out] none
\retval none
*/
void adc_watchdog0_threshold_config(uint32_t adc_periph, uint32_t low_threshold, uint32_t high_threshold)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0024U), ERR_PERIPH);
} else if(NOT_ADC_ANALOG_WATCHDOG_THRESHOLD(low_threshold)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0024U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_ADC_ANALOG_WATCHDOG_THRESHOLD(high_threshold)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0024U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_WDLT0(adc_periph) = (uint32_t)WDLT0_WDLT0(low_threshold);
ADC_WDHT0(adc_periph) = (uint32_t)WDHT0_WDHT0(high_threshold);
}
}
/*!
\brief configure ADC analog watchdog 1 threshold
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] low_threshold: analog watchdog 1 low threshold, 0..0xFFFFFF for ADC0/ADC1, 0..0xFF for ADC2
\param[in] high_threshold: analog watchdog 1 high threshold, 0..0xFFFFFF for ADC0/ADC1, 0..0xFF for ADC2
\param[out] none
\retval none
*/
void adc_watchdog1_threshold_config(uint32_t adc_periph, uint32_t low_threshold, uint32_t high_threshold)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0025U), ERR_PERIPH);
} else if(NOT_ADC_ANALOG_WATCHDOG_THRESHOLD(low_threshold)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0025U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_ADC_ANALOG_WATCHDOG_THRESHOLD(high_threshold)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0025U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_WDLT1(adc_periph) = (uint32_t)WDLT1_WDLT1(low_threshold);
ADC_WDHT1(adc_periph) = (uint32_t)WDHT1_WDHT1(high_threshold);
}
}
/*!
\brief configure ADC analog watchdog 2 threshold
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] low_threshold: analog watchdog 2 low threshold, 0..0xFFFFFF for ADC0/ADC1, 0..0xFF for ADC2
\param[in] high_threshold: analog watchdog 2 high threshold, 0..0xFFFFFF for ADC0/ADC1, 0..0xFF for ADC2
\param[out] none
\retval none
*/
void adc_watchdog2_threshold_config(uint32_t adc_periph, uint32_t low_threshold, uint32_t high_threshold)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0026U), ERR_PERIPH);
} else if(NOT_ADC_ANALOG_WATCHDOG_THRESHOLD(low_threshold)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0026U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_ADC_ANALOG_WATCHDOG_THRESHOLD(high_threshold)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0026U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_WDLT2(adc_periph) = (uint32_t)WDLT2_WDLT2(low_threshold);
ADC_WDHT2(adc_periph) = (uint32_t)WDHT2_WDHT2(high_threshold);
}
}
/*!
\brief configure ADC oversample mode
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] mode: ADC oversampling mode
only one parameter can be selected which is shown as below:
\arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger
\arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger
\param[in] shift: ADC oversampling shift
only one parameter can be selected which is shown as below:
\arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift
\arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift
\arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift
\arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift
\arg ADC_OVERSAMPLING_SHIFT_4B: 4-bit oversampling shift
\arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift
\arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift
\arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift
\arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift
\arg ADC_OVERSAMPLING_SHIFT_9B: 9-bit oversampling shift, available for ADC0/ADC1
\arg ADC_OVERSAMPLING_SHIFT_10B: 10-bit oversampling shift, available for ADC0/ADC1
\arg ADC_OVERSAMPLING_SHIFT_11B: 11-bit oversampling shift, available for ADC0/ADC1
\param[in] ratio: ADC oversampling ratio, 0..1023 for ADC0/ADC1, 0..255 for ADC2
\param[out] none
\retval none
*/
void adc_oversample_mode_config(uint32_t adc_periph, uint32_t mode, uint16_t shift, uint16_t ratio)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0027U), ERR_PERIPH);
} else if(NOT_ADC_OVERSAMPLING_MODE(mode)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0027U), ERR_PARAM_INVALID);
} else if(NOT_ADC_OVERSAMPLING_SHIFT(shift)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0027U), ERR_PARAM_INVALID);
} else if(NOT_ADC_OVERSAMPLING_RATIO(ratio)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0027U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ADC_OVERSAMPLING_ALL_CONVERT == mode) {
/* all oversampled conversions for a channel are done consecutively after a trigger */
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS);
} else if(ADC_OVERSAMPLING_ONE_CONVERT == mode) {
/* each oversampled conversion for a channel needs a trigger */
ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS;
} else {
/* illegal parameters */
}
/* config the shift and ratio */
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS));
ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)OVSCR_OVSR(ratio));
}
}
/*!
\brief enable ADC oversample mode
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_oversample_mode_enable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0028U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_OVSEN;
}
}
/*!
\brief disable ADC oversample mode
\param[in] adc_periph: ADCx, x=0,1,2
\param[out] none
\retval none
*/
void adc_oversample_mode_disable(uint32_t adc_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0029U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN);
}
}
/*!
\brief get the ADC flag bits
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] flag: the adc flag
only one parameter can be selected which is shown as below:
\arg ADC_FLAG_WDE0: analog watchdog 0 event flag
\arg ADC_FLAG_EOC: end of sequence conversion flag
\arg ADC_FLAG_EOIC: end of inserted sequence conversion flag
\arg ADC_FLAG_STIC: start flag of inserted sequence
\arg ADC_FLAG_STRC: start flag of routine sequence
\arg ADC_FLAG_ROVF: routine data register overflow flag
\arg ADC_FLAG_WDE1: analog watchdog 1 event flag
\arg ADC_FLAG_WDE2: analog watchdog 2 event flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t flag)
{
FlagStatus reval = RESET;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002AU), ERR_PERIPH);
} else if(NOT_ADC_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002AU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(ADC_STAT(adc_periph) & flag) {
reval = SET;
}
}
return reval;
}
/*!
\brief clear the ADC flag bits
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] flag: the adc flag
only one parameter can be selected which is shown as below:
\arg ADC_FLAG_WDE0: analog watchdog 0 event flag
\arg ADC_FLAG_EOC: end of sequence conversion flag
\arg ADC_FLAG_EOIC: end of inserted sequence conversion flag
\arg ADC_FLAG_STIC: start flag of inserted sequence
\arg ADC_FLAG_STRC: start flag of routine sequence
\arg ADC_FLAG_ROVF: routine data register overflow flag
\arg ADC_FLAG_WDE1: analog watchdog 1 event flag
\arg ADC_FLAG_WDE2: analog watchdog 2 event flag
\param[out] none
\retval none
*/
void adc_flag_clear(uint32_t adc_periph, uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002BU), ERR_PERIPH);
} else if(NOT_ADC_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002BU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_STAT(adc_periph) = ~((uint32_t)flag);
}
}
/*!
\brief enable ADC interrupt
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] adc_interrupt: the adc interrupt
only one parameter can be selected which is shown as below:
\arg ADC_INT_WDE0: analog watchdog 0 interrupt
\arg ADC_INT_EOC: end of sequence conversion interrupt
\arg ADC_INT_EOIC: end of inserted sequence conversion interrupt
\arg ADC_INT_ROVF: routine data register overflow interrupt
\arg ADC_INT_WDE1: analog watchdog 1 interrupt
\arg ADC_INT_WDE2: analog watchdog 2 interrupt
\param[out] none
\retval none
*/
void adc_interrupt_enable(uint32_t adc_periph, uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002CU), ERR_PERIPH);
} else if(NOT_ADC_INTERRUPT(interrupt)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002CU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_CTL0(adc_periph) |= (uint32_t)interrupt;
}
}
/*!
\brief disable ADC interrupt
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] adc_interrupt: the adc interrupt
only one parameter can be selected which is shown as below:
\arg ADC_INT_WDE0: analog watchdog 0 interrupt
\arg ADC_INT_EOC: end of sequence conversion interrupt
\arg ADC_INT_EOIC: end of inserted sequence conversion interrupt
\arg ADC_INT_ROVF: routine data register overflow interrupt
\arg ADC_INT_WDE1: analog watchdog 1 interrupt
\arg ADC_INT_WDE2: analog watchdog 2 interrupt
\param[out] none
\retval none
*/
void adc_interrupt_disable(uint32_t adc_periph, uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002DU), ERR_PERIPH);
} else if(NOT_ADC_INTERRUPT(interrupt)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002DU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_CTL0(adc_periph) &= ~(uint32_t)interrupt;
}
}
/*!
\brief get the ADC interrupt bits
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] int_flag: the adc interrupt flag
only one parameter can be selected which is shown as below:
\arg ADC_INT_FLAG_WDE0: analog watchdog 0 interrupt
\arg ADC_INT_FLAG_EOC: end of sequence conversion interrupt
\arg ADC_INT_FLAG_EOIC: end of inserted sequence conversion interrupt
\arg ADC_INT_FLAG_ROVF: routine data register overflow interrupt
\arg ADC_INT_FLAG_WDE1: analog watchdog 1 interrupt
\arg ADC_INT_FLAG_WDE2: analog watchdog 2 interrupt
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t int_flag)
{
FlagStatus reval = RESET;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002EU), ERR_PERIPH);
} else if(NOT_ADC_INTERRUPT_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002EU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t state;
/* check the interrupt bits */
switch(int_flag) {
case ADC_INT_FLAG_WDE0:
/* get the ADC analog watchdog 0 interrupt bits */
state = ADC_STAT(adc_periph) & ADC_STAT_WDE0;
if((ADC_CTL0(adc_periph) & ADC_CTL0_WDE0IE) && state) {
reval = SET;
}
break;
case ADC_INT_FLAG_EOC:
/* get the ADC end of sequence conversion interrupt bits */
state = ADC_STAT(adc_periph) & ADC_STAT_EOC;
if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state) {
reval = SET;
}
break;
case ADC_INT_FLAG_EOIC:
/* get the ADC end of inserted sequence conversion interrupt bits */
state = ADC_STAT(adc_periph) & ADC_STAT_EOIC;
if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state) {
reval = SET;
}
break;
case ADC_INT_FLAG_ROVF:
/* get the ADC routine data register overflow interrupt bits */
state = ADC_STAT(adc_periph) & ADC_STAT_ROVF;
if((ADC_CTL0(adc_periph) & ADC_CTL0_ROVFIE) && state) {
reval = SET;
}
break;
case ADC_INT_FLAG_WDE1:
/* get the ADC analog watchdog 1 interrupt bits */
state = ADC_STAT(adc_periph) & ADC_STAT_WDE1;
if((ADC_CTL0(adc_periph) & ADC_CTL0_WDE1IE) && state) {
reval = SET;
}
break;
case ADC_INT_FLAG_WDE2:
/* get the ADC analog watchdog 2 interrupt bits */
state = ADC_STAT(adc_periph) & ADC_STAT_WDE2;
if((ADC_CTL0(adc_periph) & ADC_CTL0_WDE2IE) && state) {
reval = SET;
}
break;
default:
break;
}
}
return reval;
}
/*!
\brief clear the ADC flag
\param[in] adc_periph: ADCx, x=0,1,2
\param[in] int_flag: the adc interrupt flag
only one parameter can be selected which is shown as below:
\arg ADC_INT_FLAG_WDE0: analog watchdog 0 interrupt flag
\arg ADC_INT_FLAG_EOC: end of sequence conversion interrupt flag
\arg ADC_INT_FLAG_EOIC: end of inserted sequence conversion interrupt flag
\arg ADC_INT_FLAG_ROVF: routine data register overflow interrupt flag
\arg ADC_INT_FLAG_WDE1: analog watchdog 1 interrupt flag
\arg ADC_INT_FLAG_WDE2: analog watchdog 2 interrupt flag
\param[out] none
\retval none
*/
void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t int_flag)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_PERIPH(adc_periph)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002FU), ERR_PERIPH);
} else if(NOT_ADC_INTERRUPT_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x002FU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_STAT(adc_periph) = ~((uint32_t)int_flag);
}
}
/*!
\brief configure the ADC sync mode
\param[in] sync_mode: ADC sync mode
only one parameter can be selected which is shown as below:
\arg ADC_SYNC_MODE_INDEPENDENT: all the ADCs work independently
\arg ADC_DAUL_ROUTINE_PARALLEL_INSERTED_PARALLEL: combined routine parallel & inserted parallel mode
\arg ADC_DAUL_ROUTINE_PARALLEL_INSERTED_ROTATION: combined routine parallel & trigger rotation mode
\arg ADC_DAUL_INSERTED_PARALLEL: inserted parallel mode
\arg ADC_DAUL_ROUTINE_PARALLEL: routine parallel mode
\arg ADC_DAUL_ROUTINE_FOLLOW_UP: follow-up mode
\arg ADC_DAUL_INSERTED_TRIGGER_ROTATION: trigger rotation mode
\param[out] none
\retval none
*/
void adc_sync_mode_config(uint32_t sync_mode)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_SYNC_mode(sync_mode)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0030U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_SYNCCTL(ADC0) &= ~((uint32_t)ADC_SYNCCTL_SYNCM);
ADC_SYNCCTL(ADC0) |= (uint32_t)sync_mode;
}
}
/*!
\brief configure the delay between 2 sampling phases in ADC sync modes
\param[in] sample_delay: the delay between 2 sampling phases in ADC sync modes
only one parameter can be selected which is shown as below:
\arg ADC_SYNC_DELAY_xCYCLE: x=5..20,the delay between 2 sampling phases in ADC sync modes is x ADC clock cycles
\param[out] none
\retval none
*/
void adc_sync_delay_config(uint32_t sample_delay)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_SYNC_DELAY_SAMPLE(sample_delay)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0031U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_SYNCCTL(ADC0) &= ~((uint32_t)ADC_SYNCCTL_SYNCDLY);
ADC_SYNCCTL(ADC0) |= (uint32_t)sample_delay;
}
}
/*!
\brief configure ADC sync DMA mode selection
\param[in] dma_mode: ADC sync DMA mode
only one parameter can be selected which is shown as below:
\arg ADC_SYNC_DMA_DISABLE: ADC sync DMA disabled
\arg ADC_SYNC_DMA_MODE0: ADC sync DMA mode 0
\arg ADC_SYNC_DMA_MODE1: ADC sync DMA mode 1
\param[out] none
\retval none
*/
void adc_sync_dma_config(uint32_t dma_mode)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_ADC_SYNC_DMA_mode(dma_mode)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0032U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
ADC_SYNCCTL(ADC0) &= ~((uint32_t)ADC_SYNCCTL_SYNCDMA);
ADC_SYNCCTL(ADC0) |= (uint32_t)dma_mode;
}
}
/*!
\brief configure ADC sync DMA engine issues requests according to the SYNCDMA bits
\param[in] none
\param[out] none
\retval none
*/
void adc_sync_dma_request_after_last_enable(void)
{
ADC_SYNCCTL(ADC0) |= (uint32_t)ADC_SYNCCTL_SYNCDDM;
}
/*!
\brief configure ADC sync DMA engine is disabled after the end of transfer signal from DMA controller is detected
\param[in] none
\param[out] none
\retval none
*/
void adc_sync_dma_request_after_last_disable(void)
{
ADC_SYNCCTL(ADC0) &= ~((uint32_t)ADC_SYNCCTL_SYNCDDM);
}
/*!
\brief read ADC sync master adc routine data register 0
\param[in] none
\param[out] none
\retval sync routine data 0
*/
uint32_t adc_sync_master_adc_routine_data0_read(void)
{
return (uint32_t)(ADC_SYNCDATA0 & ADC_SYNCDATA0_SYNCDATA0);
}
/*!
\brief read ADC sync slave adc routine data register 0
\param[in] none
\param[out] none
\retval sync routine data 0
*/
uint32_t adc_sync_slave_adc_routine_data0_read(void)
{
return (uint32_t)(ADC_SYNCDATA0 & ADC_SYNCDATA0_SYNCDATA1) >> 16;
}
/*!
\brief read ADC sync routine data register 1
\param[in] none
\param[out] none
\retval sync routine data 1
*/
uint32_t adc_sync_routine_data1_read(void)
{
return (uint32_t)ADC_SYNCDATA1;
}