diff options
author | Steven Gotthardt <gotthardt@gmail.com> | 2022-12-18 15:05:51 -0700 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2023-02-13 12:12:27 -0500 |
commit | 94cbf5ff48199f4652450fbb8de682f662a2cc5a (patch) | |
tree | 1080fbd36d8e41549906404fea3c9d26c2d5ef6b /lib/hc32f460/driver/src/hc32f460_adc.c | |
parent | 1e7057e917c0a663a508ac9b616d77ae53d78297 (diff) | |
download | kutter-94cbf5ff48199f4652450fbb8de682f662a2cc5a.tar.gz kutter-94cbf5ff48199f4652450fbb8de682f662a2cc5a.tar.xz kutter-94cbf5ff48199f4652450fbb8de682f662a2cc5a.zip |
lib: Add hc32f460 definitions
Signed-off-by: Steven Gotthardt <gotthardt@gmail.com>
Diffstat (limited to 'lib/hc32f460/driver/src/hc32f460_adc.c')
-rw-r--r-- | lib/hc32f460/driver/src/hc32f460_adc.c | 1742 |
1 files changed, 1742 insertions, 0 deletions
diff --git a/lib/hc32f460/driver/src/hc32f460_adc.c b/lib/hc32f460/driver/src/hc32f460_adc.c new file mode 100644 index 00000000..08f406bb --- /dev/null +++ b/lib/hc32f460/driver/src/hc32f460_adc.c @@ -0,0 +1,1742 @@ +/*******************************************************************************
+ * Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
+ *
+ * This software component is licensed by HDSC under BSD 3-Clause license
+ * (the "License"); You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ */
+/******************************************************************************/
+/** \file hc32f460_adc.c
+ **
+ ** A detailed description is available at
+ ** @link AdcGroup Adc description @endlink
+ **
+ ** - 2018-11-30 CDT First version for Device Driver Library of Adc.
+ **
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Include files
+ ******************************************************************************/
+#include "hc32f460_adc.h"
+#include "hc32f460_utility.h"
+
+/**
+ *******************************************************************************
+ ** \addtogroup AdcGroup
+ ******************************************************************************/
+//@{
+
+/*******************************************************************************
+ * Local type definitions ('typedef')
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Local pre-processor symbols/macros ('#define')
+ ******************************************************************************/
+/*! Parameter validity check for ADC peripherals. */
+#define IS_ADC_PERIPH(ADCx) \
+( ((ADCx) == M4_ADC1) || \
+ ((ADCx) == M4_ADC2))
+
+/*! Parameter validity check for ADC1 channel index. */
+#define IS_ADC1_CH_INDEX(x) \
+( ((x) < ADC1_CH_COUNT))
+
+/*! Parameter validity check for ADC2 channel index. */
+#define IS_ADC2_CH_INDEX(x) \
+( ((x) < ADC2_CH_COUNT))
+
+/*! Parameter validity check for ADC average count. */
+#define IS_ADC_AVCNT(AVCNT) \
+( ((AVCNT) == AdcAvcnt_2) || \
+ (((AVCNT) >= AdcAvcnt_4) && ((AVCNT) <= AdcAvcnt_256)))
+
+/*! Parameter validity check for ADC data alignment. */
+#define IS_ADC_DATA_ALIGN(ALIGN) \
+( ((ALIGN) == AdcDataAlign_Right) || \
+ ((ALIGN) == AdcDataAlign_Left))
+
+/*! Parameter validity check for ADC auto clear DR. */
+#define IS_ADC_CLREN(EN) \
+( ((EN) == AdcClren_Enable) || \
+ ((EN) == AdcClren_Disable))
+
+/*! Parameter validity check for ADC resolution. */
+#define IS_ADC_RESOLUTION(RESOLUTION) \
+( ((RESOLUTION) == AdcResolution_8Bit) || \
+ ((RESOLUTION) == AdcResolution_10Bit) || \
+ ((RESOLUTION) == AdcResolution_12Bit))
+
+/*! Parameter validity check for ADC scan convert mode. */
+#define IS_ADC_SCAN_MODE(MODE) \
+( ((MODE) == AdcMode_SAOnce) || \
+ ((MODE) == AdcMode_SAContinuous) || \
+ ((MODE) == AdcMode_SAOnceSBOnce) || \
+ ((MODE) == AdcMode_SAContinuousSBOnce))
+
+/*! Parameter validity check for ADC RSCHSEL. */
+#define IS_ADC_RSCHSEL(SEL) \
+( ((SEL) == AdcRschsel_Continue) || \
+ ((SEL) == AdcRschsel_Restart))
+
+/*! Parameter validity check for ADC SA trigger source. */
+#define IS_ADC_TRGEN(EN) \
+( ((EN) == AdcTrgen_Enable) || \
+ ((EN) == AdcTrgen_Disable))
+
+/*! Parameter validity check for ADC SA trigger source. */
+#define IS_ADC_TRGSEL(SEL) \
+( ((SEL) == AdcTrgsel_ADTRGX) || \
+ ((SEL) == AdcTrgsel_TRGX0) || \
+ ((SEL) == AdcTrgsel_TRGX1) || \
+ ((SEL) == AdcTrgsel_TRGX0_TRGX1))
+
+/*! Parameter validity check for ADC common trigger. */
+#define IS_ADC_COM_TRIGGER(x) \
+( ((x) == AdcComTrigger_1) || \
+ ((x) == AdcComTrigger_2) || \
+ ((x) == AdcComTrigger_1_2))
+
+/*! Parameter validity check for ADC EOCAIEN/ENCBIEN. */
+#define IS_ADC_EOCIEN(EN) \
+( ((EN) == AdcEocien_Disable) || \
+ ((EN) == AdcEocien_Enable))
+
+/*! Parameter validity check for ADC sampling time. */
+#define IS_ADC_SAMPLE_TIME(TIME) \
+( ((TIME) == 255u) || \
+ (((TIME) >= 5u) && ((TIME) <= 254u)))
+
+/*! Parameter validity check for ADC sync trigger mode. */
+#define IS_ADC_SYNC_MODE(MODE) \
+( ((MODE) == AdcSync_SingleSerial) || \
+ ((MODE) == AdcSync_SingleParallel) || \
+ ((MODE) == AdcSync_ContinuousSerial) || \
+ ((MODE) == AdcSync_ContinuousParallel))
+
+/*! Parameter validity check for ADC sync able. */
+#define IS_ADC_SYNC_ENABLE(EN) \
+( ((EN) == AdcSync_Disable) || \
+ ((EN) == AdcSync_Enable))
+
+/*! Parameter validity check for ADC ADWIEN */
+#define IS_ADC_AWDIEN(EN) \
+( ((EN) == AdcAwdInt_Disable) || \
+ ((EN) == AdcAwdInt_Enable))
+
+/*! Parameter validity check for ADC AWDSS */
+#define IS_ADC_AWDSS(SS) \
+( ((SS) == AdcAwdSel_SA_SB) || \
+ ((SS) == AdcAwdSel_SA) || \
+ ((SS) == AdcAwdSel_SB) || \
+ ((SS) == AdcAwdSel_SB_SA))
+
+/*! Parameter validity check for ADC AWDMD */
+#define IS_ADC_AWDMD(MD) \
+( ((MD) == AdcAwdCmpMode_0) || \
+ ((MD) == AdcAwdCmpMode_1))
+
+/*! Parameter validity check for ADC AWDEN */
+#define IS_ADC_AWDEN(EN) \
+( ((EN) == AdcAwd_Disable) || \
+ ((EN) == AdcAwd_Enable))
+
+/*! Parameter validity check for ADC PGA control */
+#define IS_ADC_PGA_CTL(CTL) \
+( ((CTL) == AdcPgaCtl_Invalid) || \
+ ((CTL) == AdcPgaCtl_Amplify))
+
+/*! Parameter validity check for ADC gain factor. */
+#define IS_ADC_PGA_FACTOR(FACTOR) \
+( ((FACTOR) == AdcPgaFactor_2) || \
+ (((FACTOR) >= AdcPgaFactor_2P133) && ((FACTOR) <= AdcPgaFactor_32)))
+
+/*! Parameter validity check for ADC PGA negative. */
+#define IS_ADC_PGA_NEGATIVE(N) \
+( ((N) == AdcPgaNegative_VSSA) || \
+ ((N) == AdcPgaNegative_PGAVSS))
+
+/*! Parameter validity check for ADC PGA channel. */
+#define IS_ADC_PGA_CH(ch) \
+( ((ch) == PGA_CH_NONE) || \
+ ((ch) == PGA_CH0) || \
+ ((ch) == PGA_CH1) || \
+ ((ch) == PGA_CH2) || \
+ ((ch) == PGA_CH3) || \
+ ((ch) == PGA_CH4) || \
+ ((ch) == PGA_CH5) || \
+ ((ch) == PGA_CH6) || \
+ ((ch) == PGA_CH7) || \
+ ((ch) == PGA_CH8))
+
+/*! Parameter validity check for ADC trigger source event . */
+#define IS_ADC_TRIG_SRC_EVENT(x) \
+( ((x) == EVT_PORT_EIRQ0) || \
+ (((x) > EVT_PORT_EIRQ0) && ((x) <= EVT_PORT_EIRQ15)) || \
+ (((x) >= EVT_DMA1_TC0) && ((x) <= EVT_DMA2_BTC3)) || \
+ (((x) >= EVT_EFM_OPTEND) && ((x) <= EVT_USBFS_SOF)) || \
+ (((x) >= EVT_DCU1) && ((x) <= EVT_DCU4)) || \
+ (((x) >= EVT_TMR01_GCMA) && ((x) <= EVT_TMR02_GCMB)) || \
+ (((x) >= EVT_RTC_ALM) && ((x) <= EVT_RTC_PRD)) || \
+ (((x) >= EVT_TMR61_GCMA) && ((x) <= EVT_TMR61_GUDF)) || \
+ (((x) >= EVT_TMR61_SCMA) && ((x) <= EVT_TMR61_SCMB)) || \
+ (((x) >= EVT_TMR62_GCMA) && ((x) <= EVT_TMR62_GUDF)) || \
+ (((x) >= EVT_TMR62_SCMA) && ((x) <= EVT_TMR62_SCMB)) || \
+ (((x) >= EVT_TMR63_GCMA) && ((x) <= EVT_TMR63_GUDF)) || \
+ (((x) >= EVT_TMR63_SCMA) && ((x) <= EVT_TMR63_SCMB)) || \
+ (((x) >= EVT_TMRA1_OVF) && ((x) <= EVT_TMRA5_CMP)) || \
+ (((x) >= EVT_TMRA6_OVF) && ((x) <= EVT_TMRA6_CMP)) || \
+ (((x) >= EVT_USART1_EI) && ((x) <= EVT_USART4_RTO)) || \
+ (((x) >= EVT_SPI1_SPRI) && ((x) <= EVT_AOS_STRG)) || \
+ (((x) >= EVT_TMR41_SCMUH) && ((x) <= EVT_TMR42_SCMWL)) || \
+ (((x) >= EVT_TMR43_SCMUH) && ((x) <= EVT_TMR43_SCMWL)) || \
+ (((x) >= EVT_EVENT_PORT1) && ((x) <= EVT_EVENT_PORT4)) || \
+ (((x) >= EVT_I2S1_TXIRQOUT) && ((x) <= EVT_I2S1_RXIRQOUT)) || \
+ (((x) >= EVT_I2S2_TXIRQOUT) && ((x) <= EVT_I2S2_RXIRQOUT)) || \
+ (((x) >= EVT_I2S3_TXIRQOUT) && ((x) <= EVT_I2S3_RXIRQOUT)) || \
+ (((x) >= EVT_I2S4_TXIRQOUT) && ((x) <= EVT_I2S4_RXIRQOUT)) || \
+ (((x) >= EVT_ACMP1) && ((x) <= EVT_ACMP3)) || \
+ (((x) >= EVT_I2C1_RXI) && ((x) <= EVT_I2C3_EEI)) || \
+ (((x) >= EVT_PVD_PVD1) && ((x) <= EVT_OTS)) || \
+ ((x) == EVT_WDT_REFUDF) || \
+ (((x) >= EVT_ADC1_EOCA) && ((x) <= EVT_TRNG_END)) || \
+ (((x) >= EVT_SDIOC1_DMAR) && ((x) <= EVT_SDIOC1_DMAW)) || \
+ (((x) >= EVT_SDIOC2_DMAR) && ((x) <= EVT_SDIOC2_DMAW)) || \
+ ((x) == EVT_MAX))
+
+/*******************************************************************************
+ * Global variable definitions (declared in header file with 'extern')
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Local function prototypes ('static')
+ ******************************************************************************/
+static void ADC_ReadAllData(const M4_ADC_TypeDef *ADCx, uint16_t *pu16AdcData, uint8_t u8Length);
+
+/*******************************************************************************
+ * Local variable definitions ('static')
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Function implementation - global ('extern')
+ ******************************************************************************/
+/**
+ *******************************************************************************
+ ** \brief Initializes an ADC instance.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] pstcInit Pointer to ADC initialization structure.
+ ** See @ref stc_adc_init_t for details.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_Init(M4_ADC_TypeDef *ADCx, const stc_adc_init_t *pstcInit)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+
+ if ((NULL != ADCx) && (NULL != pstcInit))
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ DDL_ASSERT(IS_ADC_RESOLUTION(pstcInit->enResolution));
+ DDL_ASSERT(IS_ADC_DATA_ALIGN(pstcInit->enDataAlign));
+ DDL_ASSERT(IS_ADC_CLREN(pstcInit->enAutoClear));
+ DDL_ASSERT(IS_ADC_SCAN_MODE(pstcInit->enScanMode));
+ DDL_ASSERT(IS_ADC_RSCHSEL(pstcInit->enRschsel));
+
+ /* Stop ADC conversion. */
+ ADCx->STR = 0u;
+
+ ADCx->CR0_f.ACCSEL = pstcInit->enResolution;
+ ADCx->CR0_f.DFMT = pstcInit->enDataAlign;
+ ADCx->CR0_f.CLREN = pstcInit->enAutoClear;
+ ADCx->CR0_f.MS = pstcInit->enScanMode;
+ ADCx->CR1_f.RSCHSEL = pstcInit->enRschsel;
+
+ /* Disable EOC(End Of Conversion) interrupts default. */
+ ADCx->ICR = (uint8_t)0x0;
+
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Deinitializes an ADC instance.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_DeInit(M4_ADC_TypeDef *ADCx)
+{
+ uint8_t i;
+ uint8_t u8SstrNum;
+ uint32_t u32SSTRAddr;
+ en_result_t enRet = ErrorInvalidParameter;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ /* Set the value of all registers to the reset value. */
+ /* Stop ADC conversion. */
+ ADCx->STR = 0u;
+ ADCx->CR0 = 0u;
+ ADCx->CR1 = 0u;
+ ADCx->TRGSR = 0u;
+ ADCx->CHSELRA0 = 0u;
+ ADCx->CHSELRB0 = 0u;
+ ADCx->AVCHSELR0 = 0u;
+ ADCx->CHMUXR0 = (uint16_t)0x3210;
+ ADCx->CHMUXR1 = (uint16_t)0x7654;
+ ADCx->ISR = 0u;
+ ADCx->ICR = (uint8_t)0x03;
+ ADCx->AWDCR = 0u;
+ ADCx->AWDDR0 = 0u;
+ ADCx->AWDDR1 = 0u;
+ ADCx->AWDCHSR0 = 0u;
+ ADCx->AWDSR0 = 0u;
+
+ u32SSTRAddr = (uint32_t)&ADCx->SSTR0;
+ if (M4_ADC1 == ADCx)
+ {
+ ADCx->CHSELRA1 = 0u;
+ ADCx->CHSELRB1 = 0u;
+ ADCx->AVCHSELR1 = 0u;
+ ADCx->CHMUXR2 = (uint16_t)0xBA98;
+ ADCx->CHMUXR3 = (uint16_t)0xFEDC;
+ ADCx->SYNCCR = (uint16_t)0x0C00;
+ ADCx->AWDCHSR1 = 0u;
+ ADCx->AWDSR1 = 0u;
+ ADCx->PGACR = 0u;
+ ADCx->PGAGSR = 0u;
+ ADCx->PGAINSR0 = 0u;
+ ADCx->PGAINSR1 = 0u;
+ ADCx->SSTRL = 0x0Bu;
+ u8SstrNum = 16u;
+ }
+ else
+ {
+ u8SstrNum = 9u;
+ }
+
+ for (i=0u; i<u8SstrNum; i++)
+ {
+ *(__IO uint8_t *)u32SSTRAddr = 0x0Bu;
+ u32SSTRAddr++;
+ }
+
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Set scan mode.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param[in] enMode See @ref en_adc_scan_mode_t for details.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_SetScanMode(M4_ADC_TypeDef *ADCx, en_adc_scan_mode_t enMode)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ DDL_ASSERT(IS_ADC_SCAN_MODE(enMode));
+
+ ADCx->CR0_f.MS = enMode;
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Set trigger source.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] pstcTrgCfg Pointer to ADC trigger source configuration structure.
+ ** \arg u8Sequence The sequence which you want to set it's trigger source.
+ ** \arg enTrgEnable Enable or disable trigger source.
+ ** \arg enTrgSel The type of trigger source.
+ ** \arg enInTrg0 Event number @ref en_event_src_t.
+ ** \arg enInTrg1 Event number @ref en_event_src_t.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ ** \note Sequence A and Sequence B CAN NOT set the same trigger source.
+ **
+ ******************************************************************************/
+en_result_t ADC_ConfigTriggerSrc(M4_ADC_TypeDef *ADCx,
+ const stc_adc_trg_cfg_t *pstcTrgCfg)
+{
+ uint32_t u32TrgSelR;
+ __IO uint32_t *io32AdcxTrgSelR0;
+ __IO uint32_t *io32AdcxTrgSelR1;
+ en_result_t enRet = ErrorInvalidParameter;
+
+ if ((NULL != ADCx) &&
+ (NULL != pstcTrgCfg) &&
+ (pstcTrgCfg->u8Sequence <= ADC_SEQ_B))
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ DDL_ASSERT(IS_ADC_TRGSEL(pstcTrgCfg->enTrgSel));
+
+ if (ADC_SEQ_A == pstcTrgCfg->u8Sequence)
+ {
+ ADCx->TRGSR_f.TRGSELA = pstcTrgCfg->enTrgSel;
+ }
+ else
+ {
+ ADCx->TRGSR_f.TRGSELB = pstcTrgCfg->enTrgSel;
+ }
+
+ if (AdcTrgsel_ADTRGX != pstcTrgCfg->enTrgSel)
+ {
+ if (M4_ADC1 == ADCx)
+ {
+ io32AdcxTrgSelR0 = &(M4_AOS->ADC1_ITRGSELR0);
+ io32AdcxTrgSelR1 = &(M4_AOS->ADC1_ITRGSELR1);
+ }
+ else
+ {
+ io32AdcxTrgSelR0 = &(M4_AOS->ADC2_ITRGSELR0);
+ io32AdcxTrgSelR1 = &(M4_AOS->ADC2_ITRGSELR1);
+ }
+
+ if ((pstcTrgCfg->enTrgSel & AdcTrgsel_TRGX0) == AdcTrgsel_TRGX0)
+ {
+ DDL_ASSERT(IS_ADC_TRIG_SRC_EVENT(pstcTrgCfg->enInTrg0));
+
+ u32TrgSelR = *io32AdcxTrgSelR0;
+ u32TrgSelR &= ~0x1FFul;
+ u32TrgSelR |= pstcTrgCfg->enInTrg0;
+ *io32AdcxTrgSelR0 = u32TrgSelR;
+ }
+ if ((pstcTrgCfg->enTrgSel & AdcTrgsel_TRGX1) == AdcTrgsel_TRGX1)
+ {
+ DDL_ASSERT(IS_ADC_TRIG_SRC_EVENT(pstcTrgCfg->enInTrg1));
+
+ u32TrgSelR = *io32AdcxTrgSelR1;
+ u32TrgSelR &= ~0x1FFul;
+ u32TrgSelR |= pstcTrgCfg->enInTrg1;
+ *io32AdcxTrgSelR1 = u32TrgSelR;
+ }
+ }
+
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Set trigger source.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u8Seq The sequence which you want to set it's trigger source.
+ **
+ ** \param [in] enState Enable or disable trigger source.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_TriggerSrcCmd(M4_ADC_TypeDef *ADCx,
+ uint8_t u8Seq,
+ en_functional_state_t enState)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+
+ if ((NULL != ADCx) && (u8Seq <= ADC_SEQ_B))
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enState));
+
+ if (ADC_SEQ_A == u8Seq)
+ {
+ ADCx->TRGSR_f.TRGENA = enState;
+ }
+ else
+ {
+ ADCx->TRGSR_f.TRGENB = enState;
+ }
+
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Enable or disable ADC common trigger.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] enTrgSel ADC trigger source type. See @ref en_adc_trgsel_t for details.
+ **
+ ** \param [in] enComTrigger ADC common trigger selection. See @ref en_adc_com_trigger_t for details.
+ **
+ ** \param [in] enState Enable or disable the specified common trigger.
+ **
+ ** \retval None.
+ **
+ ******************************************************************************/
+void ADC_ComTriggerCmd(M4_ADC_TypeDef *ADCx, en_adc_trgsel_t enTrgSel, \
+ en_adc_com_trigger_t enComTrigger, en_functional_state_t enState)
+{
+ uint32_t u32ComTrig = enComTrigger;
+ uint32_t u32ITRGSELRAddr;
+
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ DDL_ASSERT(IS_ADC_TRGSEL(enTrgSel) && (enTrgSel != AdcTrgsel_ADTRGX));
+ DDL_ASSERT(IS_ADC_COM_TRIGGER(enComTrigger));
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enState));
+
+ if (M4_ADC1 == ADCx)
+ {
+ u32ITRGSELRAddr = (uint32_t)&M4_AOS->ADC1_ITRGSELR0;
+ }
+ else
+ {
+ u32ITRGSELRAddr = (uint32_t)&M4_AOS->ADC2_ITRGSELR0;
+ }
+
+ u32ComTrig <<= 30u;
+
+ if ((enTrgSel & AdcTrgsel_TRGX0) == AdcTrgsel_TRGX0)
+ {
+ if (enState == Enable)
+ {
+ *(__IO uint32_t *)u32ITRGSELRAddr |= u32ComTrig;
+ }
+ else
+ {
+ *(__IO uint32_t *)u32ITRGSELRAddr &= ~u32ComTrig;
+ }
+ }
+
+ if ((enTrgSel & AdcTrgsel_TRGX1) == AdcTrgsel_TRGX1)
+ {
+ u32ITRGSELRAddr += 4ul;
+ if (enState == Enable)
+ {
+ *(__IO uint32_t *)u32ITRGSELRAddr |= u32ComTrig;
+ }
+ else
+ {
+ *(__IO uint32_t *)u32ITRGSELRAddr &= ~u32ComTrig;
+ }
+ }
+}
+
+/**
+ *******************************************************************************
+ ** \brief Add ADC channel.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] pstcChCfg Pointer to ADC channel configuration structure.
+ ** \arg u32Channel The channel(s) you want to configure.
+ ** \arg u8Sequence The sequence which the channel(s) belong(s) to.
+ ** \arg pu8SampTime Pointer to sampling time.
+ ** eg. u32Channel = 1001b
+ ** pu8SampTime[0] = channel 0's time
+ ** pu8SampTime[1] = channel 3's time
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ ** \note Sequence A and Sequence B CAN NOT set the same channel!!!
+ **
+ ******************************************************************************/
+en_result_t ADC_AddAdcChannel(M4_ADC_TypeDef *ADCx, const stc_adc_ch_cfg_t *pstcChCfg)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ uint8_t i;
+ uint8_t j;
+ uint32_t u32ChannelSel;
+ __IO uint8_t *io8Sstr;
+
+ if ((NULL != ADCx) &&
+ (NULL != pstcChCfg) &&
+ (pstcChCfg->u8Sequence <= ADC_SEQ_B))
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ if (M4_ADC1 == ADCx)
+ {
+ u32ChannelSel = pstcChCfg->u32Channel & ADC1_CH_ALL;
+ if (ADC_SEQ_A == pstcChCfg->u8Sequence)
+ {
+ ADCx->CHSELRA0 |= (uint16_t)u32ChannelSel;
+ ADCx->CHSELRA1 |= (uint16_t)(u32ChannelSel >> 16u);
+ }
+ else
+ {
+ ADCx->CHSELRB0 |= (uint16_t)u32ChannelSel;
+ ADCx->CHSELRB1 |= (uint16_t)(u32ChannelSel >> 16u);
+ }
+ }
+ else
+ {
+ u32ChannelSel = pstcChCfg->u32Channel & ADC2_CH_ALL;
+ if (ADC_SEQ_A == pstcChCfg->u8Sequence)
+ {
+ ADCx->CHSELRA0 |= (uint16_t)u32ChannelSel;
+ }
+ else
+ {
+ ADCx->CHSELRB0 |= (uint16_t)u32ChannelSel;
+ }
+ }
+
+ /* Set sampling time */
+ i = 0u;
+ j = 0u;
+ io8Sstr = &(ADCx->SSTR0);
+ while (0u != u32ChannelSel)
+ {
+ if (u32ChannelSel & 0x1ul)
+ {
+ io8Sstr[i] = pstcChCfg->pu8SampTime[j++];
+ }
+ u32ChannelSel >>= 1u;
+ i++;
+ }
+
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Delete ADC channel(s).
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u32Channel The channel(s) you want to delete.
+ ** \arg ADC1_CH0 ~ ADC1_CH16 Channels of ADC unit 1.
+ ** \arg ADC2_CH0 ~ ADC2_CH8 Channels of ADC unit 2.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ** \note You can use this function to delete ADC channel(s)
+ ** and then set the corresponding pin(s) of the channel(s)
+ ** to the other mode you need in your application.
+ **
+ ******************************************************************************/
+en_result_t ADC_DelAdcChannel(M4_ADC_TypeDef *ADCx, uint32_t u32Channel)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ uint16_t u16ChSelR0;
+ uint16_t u16ChSelR1;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ u16ChSelR0 = (uint16_t)u32Channel;
+ u16ChSelR1 = (uint16_t)(u32Channel >> 16u);
+
+ ADCx->CHSELRA0 &= (uint16_t)(~u16ChSelR0);
+ ADCx->CHSELRB0 &= (uint16_t)(~u16ChSelR0);
+
+ if (M4_ADC1 == ADCx)
+ {
+ ADCx->CHSELRA1 &= (uint16_t)(~u16ChSelR1);
+ ADCx->CHSELRB1 &= (uint16_t)(~u16ChSelR1);
+ }
+
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief ADC interrupt configuration.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u8Seq The sequence to be configured.
+ **
+ ** \param [in] enState Enable or Disable sequence conversion done interrupt.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_SeqITCmd(M4_ADC_TypeDef *ADCx,
+ uint8_t u8Seq,
+ en_functional_state_t enState)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ uint8_t u8Msk = 0u;
+
+ if ((NULL != ADCx) && (u8Seq <= ADC_SEQ_B))
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enState));
+
+ u8Msk = (uint8_t)(0x1ul << u8Seq);
+ ADCx->ISR &= (uint8_t)(~u8Msk);
+
+ if (Enable == enState)
+ {
+ ADCx->ICR |= u8Msk;
+ }
+ else
+ {
+ ADCx->ICR &= (uint8_t)(~u8Msk);
+ }
+
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief ADC average conversion configuration.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] enAvgCnt Average after enAvgCnt conversions.
+ ** See @ref en_adc_avcnt_t for details.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_ConfigAvg(M4_ADC_TypeDef *ADCx, en_adc_avcnt_t enAvgCnt)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ DDL_ASSERT(IS_ADC_AVCNT(enAvgCnt));
+
+ ADCx->CR0_f.AVCNT = enAvgCnt;
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Add average channel(s).
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u32Channel The channel(s), which will be set as average channel(s).
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ** \note The channel must first be configured as an analog channel
+ ** by function ADC_AddAdcChannel.
+ **
+ ******************************************************************************/
+en_result_t ADC_AddAvgChannel(M4_ADC_TypeDef *ADCx, uint32_t u32Channel)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ uint16_t u16AvgChR0;
+ uint16_t u16AvgChR1;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ if (M4_ADC1 == ADCx)
+ {
+ u32Channel &= ADC1_CH_ALL;
+ }
+ else
+ {
+ u32Channel &= ADC2_CH_ALL;
+ }
+
+ u16AvgChR0 = (uint16_t)u32Channel;
+ u16AvgChR1 = (uint16_t)(u32Channel >> 16u);
+
+ ADCx->AVCHSELR0 |= u16AvgChR0;
+ if (M4_ADC1 == ADCx)
+ {
+ ADCx->AVCHSELR1 |= u16AvgChR1;
+ }
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Delete average channel(s).
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u32Channel The average channel(s) which you want to delete.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_DelAvgChannel(M4_ADC_TypeDef *ADCx, uint32_t u32Channel)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ uint16_t u16AvgChR0;
+ uint16_t u16AvgChR1;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ u16AvgChR0 = (uint16_t)u32Channel;
+ u16AvgChR1 = (uint16_t)(u32Channel >> 16u);
+
+ ADCx->AVCHSELR0 &= (uint16_t)(~u16AvgChR0);
+ if (M4_ADC1 == ADCx)
+ {
+ ADCx->AVCHSELR1 &= (uint16_t)(~u16AvgChR1);
+ }
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief ADC AWD(analog watch dog) configuration.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] pstcAwdCfg Pointer to the configuration structure.
+ ** See @ref stc_adc_awd_cfg_t for details.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_ConfigAwd(M4_ADC_TypeDef *ADCx, const stc_adc_awd_cfg_t *pstcAwdCfg)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+
+ if ((NULL != ADCx) && (NULL != pstcAwdCfg))
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ DDL_ASSERT(IS_ADC_AWDMD(pstcAwdCfg->enAwdmd));
+ DDL_ASSERT(IS_ADC_AWDSS(pstcAwdCfg->enAwdss));
+
+ ADCx->AWDCR_f.AWDEN = AdcAwd_Disable;
+ ADCx->AWDCR_f.AWDIEN = AdcAwdInt_Disable;
+ ADCx->AWDCR_f.AWDMD = pstcAwdCfg->enAwdmd;
+ ADCx->AWDCR_f.AWDSS = pstcAwdCfg->enAwdss;
+
+ ADCx->AWDDR0 = pstcAwdCfg->u16AwdDr0;
+ ADCx->AWDDR1 = pstcAwdCfg->u16AwdDr1;
+
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Enable or disable ADC AWD(analog watch dog).
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] enState Enable or disable AWD.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_AwdCmd(M4_ADC_TypeDef *ADCx, en_functional_state_t enState)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enState));
+
+ ADCx->AWDCR_f.AWDEN = enState;
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Enable or disable ADC AWD(analog watch dog) interrupt.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] enState Enable or disable AWD interrupt.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_AwdITCmd(M4_ADC_TypeDef *ADCx, en_functional_state_t enState)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enState));
+
+ ADCx->AWDCR_f.AWDIEN = enState;
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Add AWD channel(s).
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u32Channel The channel(s), which will be set as AWD channel(s).
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ** \note The channel must first be configured as an analog channel
+ ** by function ADC_AddAdcChannel.
+ **
+ ******************************************************************************/
+en_result_t ADC_AddAwdChannel(M4_ADC_TypeDef *ADCx, uint32_t u32Channel)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ uint16_t u16ChSelR0;
+ uint16_t u16ChSelR1;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ if (M4_ADC1 == ADCx)
+ {
+ u32Channel &= ADC1_CH_ALL;
+ }
+ else
+ {
+ u32Channel &= ADC2_CH_ALL;
+ }
+
+ u16ChSelR0 = (uint16_t)u32Channel;
+ u16ChSelR1 = (uint16_t)(u32Channel >> 16u);
+
+ ADCx->AWDCHSR0 |= u16ChSelR0;
+ if (M4_ADC1 == ADCx)
+ {
+ ADCx->AWDCHSR1 |= u16ChSelR1;
+ }
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Delete AWD channel(s).
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u32Channel The AWD channel(s) which you are going to delete.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_DelAwdChannel(M4_ADC_TypeDef *ADCx, uint32_t u32Channel)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ uint16_t u16ChSelR0;
+ uint16_t u16ChSelR1;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ u16ChSelR0 = (uint16_t)u32Channel;
+ u16ChSelR1 = (uint16_t)(u32Channel >> 16u);
+
+ ADCx->AWDCHSR0 &= (uint16_t)(~u16ChSelR0);
+ if (M4_ADC1 == ADCx)
+ {
+ ADCx->AWDCHSR1 &= (uint16_t)(~u16ChSelR1);
+ }
+
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief ADC programmable gain amplifier(PGA) configuration.
+ **
+ ** \param [in] enFactor PGA gain factor.
+ ** \param [in] enNegativeIn PGA negative input select.
+ **
+ ** \retval None.
+ **
+ ** \note Only ADC1 has PGA.
+ **
+ ******************************************************************************/
+void ADC_ConfigPga(en_adc_pga_factor_t enFactor, en_adc_pga_negative_t enNegativeIn)
+{
+ DDL_ASSERT(IS_ADC_PGA_FACTOR(enFactor));
+ DDL_ASSERT(IS_ADC_PGA_NEGATIVE(enNegativeIn));
+
+ M4_ADC1->PGAGSR_f.GAIN = enFactor;
+ M4_ADC1->PGAINSR1_f.PGAVSSEN = enNegativeIn;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Enable or disable PGA.
+ **
+ ** \param [in] enState Enable or disable PGA.
+ **
+ ** \retval None.
+ **
+ ******************************************************************************/
+void ADC_PgaCmd(en_functional_state_t enState)
+{
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enState));
+
+ if (Enable == enState)
+ {
+ M4_ADC1->PGACR_f.PGACTL = AdcPgaCtl_Amplify;
+ }
+ else
+ {
+ M4_ADC1->PGACR_f.PGACTL = AdcPgaCtl_Invalid;
+ }
+}
+
+/**
+ *******************************************************************************
+ ** \brief Select PGA channel.
+ **
+ ** \param[in] u16Channel The channel, which you want to gain.
+ **
+ ** \retval None.
+ **
+ ** \note Only ADC1 has PGA. The channel must first
+ ** be configured as an analog channel
+ ** by function ADC_AddAdcChannel
+ **
+ ******************************************************************************/
+void ADC_PgaSelChannel(uint16_t u16Channel)
+{
+ DDL_ASSERT(IS_ADC_PGA_CH(u16Channel));
+ M4_ADC1->PGAINSR0 = u16Channel;
+}
+
+/**
+ *******************************************************************************
+ ** \brief ADC sync mode configuration.
+ **
+ ** \param [in] enMode Synchronous mode types.
+ ** \param [in] u8TrgDelay ADC2 trigger delay time.
+ **
+ ** \retval None.
+ **
+ ******************************************************************************/
+void ADC_ConfigSync(en_adc_sync_mode_t enMode, uint8_t u8TrgDelay)
+{
+ DDL_ASSERT(IS_ADC_SYNC_MODE(enMode));
+
+ /* Disable synchronous mode first. */
+ M4_ADC1->SYNCCR_f.SYNCEN = AdcSync_Disable;
+
+ M4_ADC1->SYNCCR_f.SYNCMD = enMode;
+ M4_ADC1->SYNCCR_f.SYNCDLY = u8TrgDelay;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Enable or disable sync mode.
+ **
+ ** \param [in] enState Enable or disable sync mode.
+ **
+ ** \retval None.
+ **
+ ******************************************************************************/
+void ADC_SyncCmd(en_functional_state_t enState)
+{
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enState));
+
+ M4_ADC1->SYNCCR_f.SYNCEN = enState;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Start an ADC conversion.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ** \note Software startup only support sequence A.
+ **
+ ******************************************************************************/
+en_result_t ADC_StartConvert(M4_ADC_TypeDef *ADCx)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ ADCx->STR = 1u;
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Stop an ADC conversion and clear flags.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval ErrorTimeout Timeout.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_StopConvert(M4_ADC_TypeDef *ADCx)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ __IO uint32_t u32TimeCount = 0u;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ enRet = Ok;
+ /* Make sure the ADC is really stopped. */
+ while (ADCx->STR == 1u)
+ {
+ /* Stop ADC conversion. */
+ ADCx->STR = 0u;
+ if (++u32TimeCount > 10000u)
+ {
+ enRet = ErrorTimeout;
+ break;
+ }
+ }
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Get the conversion status flag.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u8Seq The sequence which you want to get
+ ** it's conversion status flag.
+ **
+ ** \retval Set ADC converted done.
+ ** \retval Reset ADC is converting or parameter error.
+ **
+ ******************************************************************************/
+en_flag_status_t ADC_GetEocFlag(const M4_ADC_TypeDef *ADCx, uint8_t u8Seq)
+{
+ en_flag_status_t enFlag = Reset;
+
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ if (ADCx->ISR & ((uint8_t)(0x1ul << u8Seq)))
+ {
+ enFlag = Set;
+ }
+
+ return enFlag;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Clear conversion status flag of sequence A or sequence B.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u8Seq The sequence which you want to clear
+ ** it's conversion status flag.
+ **
+ ** \retval None.
+ **
+ ******************************************************************************/
+void ADC_ClrEocFlag(M4_ADC_TypeDef *ADCx, uint8_t u8Seq)
+{
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ ADCx->ISR &= (uint8_t)(~(0x1ul << u8Seq));
+ }
+}
+
+/**
+ *******************************************************************************
+ ** \brief ADC start sequence A, check it's EOC status and get the data.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [out] pu16AdcData The address to store ADC value.
+ ** The location of the data store depends on
+ ** the parameter u8Length.
+ ** u8Length >= ADCx_CH_COUNT(ADC1_CH_COUNT or ADC2_CH_COUNT),
+ ** all of the ADC data regs will be read:
+ ** pu16AdcData[0] = data of Channel 0,
+ ** pu16AdcData[1] = data of Channel 1,
+ ** pu16AdcData[2] = data of Channel 2,
+ ** ...
+ ** u8Length < ADCx_CH_COUNT(ADC1_CH_COUNT or ADC2_CH_COUNT),
+ ** only the data of the enabled channles will be read:
+ ** pu16AdcData[0] = data of the 1st enabled channel,
+ ** pu16AdcData[1] = data of the 2nd enabled channel,
+ ** pu16AdcData[2] = data of the 3rd enabled channel,
+ ** ...
+ **
+ ** \param [in] u8Length The length of the ADC data to be read.
+ **
+ ** \param [in] u32Timeout Timeout value.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval ErrorTimeout Timeout.
+ ** \retval OperationInProgress ADC is converting.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_PollingSa(M4_ADC_TypeDef *ADCx,
+ uint16_t *pu16AdcData,
+ uint8_t u8Length,
+ uint32_t u32Timeout)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ uint8_t u8AllDataLength = 0u;
+ uint32_t u32Channel = 0u;
+ uint32_t u32AdcTimeout = 0u;
+ __IO uint32_t u32TimeCount = 0u;
+
+ if ((NULL != ADCx) && (NULL != pu16AdcData) && (0u != u8Length))
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ if (M4_ADC1 == ADCx)
+ {
+ if (u8Length >= ADC1_CH_COUNT)
+ {
+ u8AllDataLength = ADC1_CH_COUNT;
+ }
+ else
+ {
+ u32Channel = (uint32_t)ADCx->CHSELRA1;
+ u32Channel <<= 16u;
+ u32Channel |= (uint32_t)ADCx->CHSELRA0;
+ }
+ }
+ else
+ {
+ if (u8Length >= ADC2_CH_COUNT)
+ {
+ u8AllDataLength = ADC2_CH_COUNT;
+ }
+ else
+ {
+ u32Channel = (uint32_t)M4_ADC2->CHSELRA0;
+ }
+ }
+
+ /* Start ADC conversion. */
+ ADCx->STR = (uint8_t)0x01;
+
+ /* 10 is the number of required instructions cycles for the below loop statement. */
+ u32AdcTimeout = u32Timeout * (SystemCoreClock / 10u / 1000u);
+ u32TimeCount = 0u;
+ enRet = ErrorTimeout;
+ while (u32TimeCount < u32AdcTimeout)
+ {
+ if (ADCx->ISR_f.EOCAF)
+ {
+ /* Get ADC data. */
+ if (u8AllDataLength)
+ {
+ ADC_ReadAllData(ADCx, pu16AdcData, u8AllDataLength);
+ }
+ else
+ {
+ ADC_GetChData(ADCx, u32Channel, pu16AdcData, u8Length);
+ }
+
+ /* Clear sequence A flag. */
+ ADCx->ISR_f.EOCAF = 0u;
+ enRet = Ok;
+ break;
+ }
+ u32TimeCount++;
+ }
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Reading all data regs of an ADC.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [out] pu16AdcData The address where the data will be stored.
+ ** pu16AdcData[0] = data of Channel 0,
+ ** pu16AdcData[1] = data of Channel 1,
+ ** pu16AdcData[2] = data of Channel 2,
+ ** ...
+ **
+ ** \param [in] u8Length The length of the ADC data to be read.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_GetAllData(const M4_ADC_TypeDef *ADCx, uint16_t *pu16AdcData, uint8_t u8Length)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ if (((M4_ADC1 == ADCx) && (u8Length >= ADC1_CH_COUNT)) ||
+ ((M4_ADC2 == ADCx) && (u8Length >= ADC2_CH_COUNT)))
+ {
+ ADC_ReadAllData(ADCx, pu16AdcData, u8Length);
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Reading the data of the specified channel(s).
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base
+ ** \arg M4_ADC1 ADC unit 1 instance register base
+ ** \arg M4_ADC2 ADC unit 2 instance register base
+ **
+ ** \param [in] u32TargetCh The specified channel(s)
+ **
+ ** \param [out] pu16AdcData The address where the data will be stored.
+ ** pu16AdcData[0] = data of the 1st enabled channel,
+ ** pu16AdcData[1] = data of the 2nd enabled channel,
+ ** pu16AdcData[2] = data of the 3rd enabled channel,
+ ** eg. u32TargetCh = 1001b
+ ** pu16AdcData[0] = Channel 0's data,
+ ** pu16AdcData[1] = Channel 3's data,
+ **
+ ** \param [in] u8Length The length of the ADC data to be read.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_GetChData(const M4_ADC_TypeDef *ADCx,
+ uint32_t u32TargetCh,
+ uint16_t *pu16AdcData,
+ uint8_t u8Length)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ uint8_t i;
+ uint8_t j;
+ uint32_t u32Channel;
+ __IO const uint16_t *pu16DataReg = &(ADCx->DR0);
+
+ if ((NULL != ADCx) && (NULL != pu16AdcData) && (0u != u8Length))
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ if (M4_ADC1 == ADCx)
+ {
+ u32Channel = u32TargetCh & ADC1_CH_ALL;
+ }
+ else
+ {
+ u32Channel = u32TargetCh & ADC2_CH_ALL;
+ }
+
+ i = 0u;
+ j = 0u;
+ while ((0u != u32Channel) && (0u != u8Length))
+ {
+ if (0u != (u32Channel & 0x1ul))
+ {
+ pu16AdcData[j] = pu16DataReg[i];
+ j++;
+ u8Length--;
+ }
+
+ u32Channel >>= 1u;
+ i++;
+ }
+
+ enRet = Ok;
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Get the value of a specified channel via channel index.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base
+ ** \arg M4_ADC1 ADC unit 1 instance register base
+ ** \arg M4_ADC2 ADC unit 2 instance register base
+ **
+ ** \param [in] u8ChIndex The index of the specified channel.
+ ** u8ChIndex < ADC1_CH_COUNT while ADCx == M4_ADC1;
+ ** u8ChIndex < ADC2_CH_COUNT while ADCx == M4_ADC2.
+ **
+ ** \retval An uint16_t value -- the ADC value of the specified channel.
+ **
+ ******************************************************************************/
+uint16_t ADC_GetValue(const M4_ADC_TypeDef *ADCx, uint8_t u8ChIndex)
+{
+ __IO const uint16_t *pu16DataReg = &(ADCx->DR0);
+
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ return pu16DataReg[u8ChIndex];
+}
+
+/**
+ *******************************************************************************
+ ** \brief Get all AWD channels status flags.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \retval u32AwdFlag 0 -- No ADC channel meets AWD comparison conditions.
+ ** !0 -- The bit value of the channel that satisfies the
+ ** AWD condition is 1.
+ **
+ ******************************************************************************/
+uint32_t ADC_GetAwdFlag(const M4_ADC_TypeDef *ADCx)
+{
+ uint32_t u32AwdFlag;
+
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ if (M4_ADC1 == ADCx)
+ {
+ u32AwdFlag = ADCx->AWDSR1;
+ u32AwdFlag <<= 16u;
+ u32AwdFlag |= ADCx->AWDSR0;
+ }
+ else
+ {
+ u32AwdFlag = ADCx->AWDSR0;
+ }
+
+ return u32AwdFlag;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Clear all AWD channels status flags
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \retval None.
+ **
+ ******************************************************************************/
+void ADC_ClrAwdFlag(M4_ADC_TypeDef *ADCx)
+{
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ ADCx->AWDSR0 = 0u;
+ if (M4_ADC1 == ADCx)
+ {
+ ADCx->AWDSR0 = 0u;
+ ADCx->AWDSR1 = 0u;
+ }
+ }
+}
+
+/**
+ *******************************************************************************
+ ** \brief Clear AWD specified channels status flags.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u32AwdCh The channel(s) which you want to clear it's flag(s).
+ **
+ ** \retval None.
+ **
+ ******************************************************************************/
+void ADC_ClrAwdChFlag(M4_ADC_TypeDef *ADCx, uint32_t u32AwdCh)
+{
+ uint16_t u16ChR0;
+ uint16_t u16ChR1;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ u16ChR0 = (uint16_t)u32AwdCh;
+ u16ChR1 = (uint16_t)(u32AwdCh >> 16u);
+
+ ADCx->AWDSR0 &= (uint16_t)(~u16ChR0);
+ if (M4_ADC1 == ADCx)
+ {
+ ADCx->AWDSR1 &= (uint16_t)(~u16ChR1);
+ }
+ }
+}
+
+/**
+ *******************************************************************************
+ ** \brief Remap an ADC pin to channel(s).
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u32DestChannel Destination channel(s).
+ **
+ ** \param [in] u8AdcPin ADC pin number.
+ **
+ ** \retval ErrorInvalidParameter Parameter error.
+ ** \retval Ok No error occurred.
+ **
+ ******************************************************************************/
+en_result_t ADC_ChannelRemap(M4_ADC_TypeDef *ADCx,
+ uint32_t u32DestChannel,
+ uint8_t u8AdcPin)
+{
+ en_result_t enRet = ErrorInvalidParameter;
+ uint8_t i;
+ uint8_t u8OffsetReg;
+ uint8_t u8ChPos;
+ uint16_t u16AdcPin = u8AdcPin;
+ __IO uint16_t *io16Chmuxr = NULL;
+
+ if (NULL != ADCx)
+ {
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+ enRet = Ok;
+ if (M4_ADC1 == ADCx)
+ {
+ if (u16AdcPin <= ADC1_IN15)
+ {
+ u32DestChannel &= ADC1_PIN_MASK_ALL;
+ }
+ else
+ {
+ enRet = ErrorInvalidParameter;
+ }
+ }
+ else
+ {
+ if ((u16AdcPin >= ADC12_IN4) && (u16AdcPin <= ADC12_IN11))
+ {
+ u16AdcPin -= 4u;
+ u32DestChannel &= ADC2_PIN_MASK_ALL;
+ }
+ else
+ {
+ enRet = ErrorInvalidParameter;
+ }
+ }
+
+ if (Ok == enRet)
+ {
+ i = 0u;
+ while (0u != u32DestChannel)
+ {
+ if (u32DestChannel & 0x1ul)
+ {
+ u8OffsetReg = i / 4u;
+ u8ChPos = (i % 4u) * 4u;
+ io16Chmuxr = &(ADCx->CHMUXR0) + u8OffsetReg;
+ *io16Chmuxr &= (uint16_t)(~(0xFul << u8ChPos));
+ *io16Chmuxr |= (uint16_t)(u16AdcPin << u8ChPos);
+ }
+
+ u32DestChannel >>= 1u;
+ i++;
+ }
+ }
+ }
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Get the number of the pin corresponding to the specified channel.
+ **
+ ** \param [in] ADCx Pointer to ADC instance register base.
+ ** \arg M4_ADC1 ADC unit 1 instance register base.
+ ** \arg M4_ADC2 ADC unit 2 instance register base.
+ **
+ ** \param [in] u8ChIndex This channel that you want to get its pin number.
+ **
+ ** \retval [0, 15] The correct ADC pin number.
+ ** \retval [0xFF] The invalid ADC pin number.
+ **
+ ******************************************************************************/
+uint8_t ADC_GetChannelPinNum(const M4_ADC_TypeDef *ADCx, uint8_t u8ChIndex)
+{
+ uint8_t u8OffsetPin;
+ uint8_t u8OffsetReg;
+ uint8_t u8ChPos;
+ uint8_t u8AdcPin = ADC_PIN_INVALID;
+ __IO const uint16_t *io16Chmuxr = NULL;
+
+ DDL_ASSERT(IS_ADC_PERIPH(ADCx));
+
+ if (M4_ADC1 == ADCx)
+ {
+ DDL_ASSERT(IS_ADC1_CH_INDEX(u8ChIndex));
+ u8OffsetPin = 0u;
+ }
+ else
+ {
+ DDL_ASSERT(IS_ADC2_CH_INDEX(u8ChIndex));
+ u8OffsetPin = 4u;
+ }
+
+ u8OffsetReg = u8ChIndex / 4u;
+ u8ChPos = (u8ChIndex % 4u) * 4u;
+ io16Chmuxr = &(ADCx->CHMUXR0) + u8OffsetReg;
+ u8AdcPin = (uint8_t)((*io16Chmuxr >> u8ChPos) & ((uint16_t)0xF));
+ u8AdcPin += u8OffsetPin;
+
+ return u8AdcPin;
+}
+
+/*******************************************************************************
+ * Function implementation - local ('static')
+ ******************************************************************************/
+/**
+ *******************************************************************************
+ ** \brief Read all data of an ADC. pu16AdcData[0] = DR0, pu16AdcData[1] = DR1, ...
+ **
+ ******************************************************************************/
+static void ADC_ReadAllData(const M4_ADC_TypeDef *ADCx, uint16_t *pu16AdcData, uint8_t u8Length)
+{
+ uint8_t i;
+ __IO const uint16_t *pu16DataReg = &(ADCx->DR0);
+
+ for (i = 0u; i < u8Length; i++)
+ {
+ pu16AdcData[i] = pu16DataReg[i];
+ }
+}
+
+//@} // AdcGroup
+
+/*******************************************************************************
+ * EOF (not truncated)
+ ******************************************************************************/
|