/** * @copyright 2015 Indie Semiconductor. * * This file is proprietary to Indie Semiconductor. * All rights reserved. Reproduction or distribution, in whole * or in part, is forbidden except by express written permission * of Indie Semiconductor. * * @file adc_device.c * @Author: Jack.Pan * @E-mail:jack.pan@indiemicro.com * @Date: 2020/09/10 */ #include #include #include #include #include static ADCMeasureParam_t adcMeasParamm = {ADC_MEASURE_ITEM_NONE, 0}; static adc_cb_func_t adcCallback = NULL; static uint16_t adcResult[10]; void ADC_Handler(void) { if (adcCallback !=NULL){ if(adcMeasParamm.item == ADC_MEASURE_ITEM_VAMP){ adcResult[0] = (uint16_t)(SAR_CTRL_SFRS->DATA[0].DATA & 0x07FFU);//VAMP adcResult[1] = (uint16_t)(SAR_CTRL_SFRS->DATA[1].DATA & 0x0FFFU);//VBAT adcResult[2] = (uint16_t)(SAR_CTRL_SFRS->DATA[2].DATA & 0x0FFFU);//VPB3 adcResult[3] = (uint16_t)(SAR_CTRL_SFRS->DATA[3].DATA & 0x0FFFU);//VPC4 }else{ adcResult[1] = 160;//(uint16_t)(SAR_CTRL_SFRS->DATA[1].DATA & 0x0FFFU);//VBAT adcResult[2] = 150;//(uint16_t)(SAR_CTRL_SFRS->DATA[2].DATA & 0x0FFFU);//VTEMP } adcCallback(adcMeasParamm, adcResult); } SAR_CTRL_SFRS->SARINT.CLEAR.INT_CONV_DONE_CLR = 1U; SAR_CTRL_SFRS->SARCTRL.SARENAREQ = 1U; } void ADC_GeneralInit(void) { #if SYS_MAIN_CLOCK_DIV == CLOCK_DIV_1 SAR_CTRL_SFRS->SARCLKDIV = 4U; #elif SYS_MAIN_CLOCK_DIV == CLOCK_DIV_2 SAR_CTRL_SFRS->SARCLKDIV = 2U; #else SAR_CTRL_SFRS->SARCLKDIV = 1U; #endif for (uint8_t i = 0U; i < 10U; i++){ SAR_CTRL_SFRS->ADCCHCTRL2R.WORD &= ~((uint32_t)0x03UL << (i*2+8U));//clear SAR_CTRL_SFRS->ADCCHCTRL2R.WORD |= ((uint32_t)ADC_REF_VDD_3V3 << (i*2+8U));//set vref 3v3 SAR_CTRL_SFRS->ADCCHCTRL0R.WORD &= ~((uint32_t)0x03UL << (i*2+0U)); SAR_CTRL_SFRS->ADCCHCTRL0R.WORD |= ((uint32_t)ADC_AFE_INPUT_ALL_EXT << (i*2+0U)); SAR_CTRL_SFRS->ADCCHCTRL0R.WORD &= ~((uint32_t)0x01UL << (i*1+20U)); SAR_CTRL_SFRS->ADCCHCTRL0R.WORD |= ((uint32_t)ADC_AFE_GAIN_31_OF_32 << (i*1+20U)); } SAR_CTRL_SFRS->ADCCHCTRL0R.SARINPUTGAINCH4 = ADC_AFE_GAIN_22_OF_32; SAR_CTRL_SFRS->SARINT.ENABLE.INT_CONV_DONE_ENA = 0;//1:Convert Done Interrupt Enable. SAR_CTRL_SFRS->SARINT.ENABLE.INT_TRIG_CLASH_ENA = 0;//1:Trigger Clash Interrupt Enable. SAR_CTRL_SFRS->SARINT.CLEAR.INT_CONV_DONE_CLR = 1; SAR_CTRL_SFRS->SARINT.CLEAR.INT_TRIG_CLASH_CLR = 1; } void ADC_Init(AdcMeasureItem_t item, uint8_t channel) { ADCTriggerParam_t source; adcMeasParamm.item = item; adcMeasParamm.channel = channel; switch(item){ case ADC_MEASURE_ITEM_VAMP:/* 1x */ SAR_CTRL_SFRS->SARCFG.TRIGDLY = 15U; // SAR_CTRL_SFRS->SARCFG.TRIGSEL = 1U;//0x1: Select PWMAUX_TRIGSEL // SAR_CTRL_SFRS->SARCFG.PWMAUXCHSEL = 0U;//0x0: Select PWMAUX Channel 0 // SAR_CTRL_SFRS->SARCFG.PWMAUXTRIGSEL = 4U;// 0x4: Triggered by PWM AUX counter 0 period. 0x8: Triggered by PWM AUX counter 1 period. // SAR_CTRL_SFRS->SARCFG.TRIGSRC = 8U;//Triggered through hardware, either select from TRIGSRC[2:0] or from PWMAUX_TRIGSEL.TRIGSRC[2:0]=0x0: Triggered by the PWM compare trigger0. source.selection = ADC_TRIGGER_SEL_PWM_AUX_TRIGSRC; source.channel = ADC_PWMAUX_CHN0; source.pwmAux = ADC_PWMAUX_TRIG_SRC_PWM_PERIOD0; source.general = ADC_TRIG_SRC_PWM_CMP0; /* SYSCTRLA_SFRS->CSACTRLR.CSAGAINSEL = 0U;//5 gain SYSCTRLA_SFRS->CSACTRLR.CSAZEROEN = 0U; SYSCTRLA_SFRS->CSACTRLR.CSAPOWEN = 1U; */ SAR_CTRL_SFRS->AFECTRL.SARAFEEN = 1;//ADC AFE Enable. adc afe enable. If vinp, vinn and vin vcm all choose external, adc afe should be disabled: adc_adc_en=0, otherwise, adc afe must be enabled: adc_afe_en=1. SAR_CTRL_SFRS->AFECTRL.ADCSELVINVCMEXT = 0;//Select External Inputs to ADC. choose ADC input common voltage. 0: choose internal vin_vcm, equals to (vinp+vinn)/2; 1: choose external vin_vcm, for PN detect. SAR_CTRL_SFRS->AFECTRL.SARPREAMPEN = 1;// adc pre-amp enable. SAR_CTRL_SFRS->ADCCHCONF.CH1SEL = ADC_CH_SEL_TSENSOR_GND;// SAR_CTRL_SFRS->ADCCHCONF.CH2SEL = ADC_CH_SEL_VBAT_GND; SAR_CTRL_SFRS->ADCCHCONF.CH3SEL = ADC_CH_SEL_PB6_GND; SAR_CTRL_SFRS->ADCCHCONF.CH4SEL = ADC_CH_SEL_PB7_GND; SAR_CTRL_SFRS->ADCCHCTRL1R.SAMPCYCCH1 = 15U;//max 15 SAR_CTRL_SFRS->SARCTRL.DIGRESET = 0X1U; SAR_CTRL_SFRS->ADCCHCONF.SEQCNT = ADC_SQ_CH1_2_CH4;//0x3: CH1->CH2->CH3 break; case ADC_MEASURE_ITEM_VBAT_VTEMP:/* 1x */ SAR_CTRL_SFRS->ADCCHCONF.CH2SEL = ADC_CH_SEL_VBAT_GND; SAR_CTRL_SFRS->ADCCHCONF.CH3SEL = ADC_CH_SEL_TSENSOR_GND; SAR_CTRL_SFRS->ADCCHCONF.SEQCNT = (uint8_t)ADC_SQ_CH1_2_CH3; source.selection = ADC_TRIGGER_SEL_GENERAL_TRIGSRC; source.general = ADC_TRIG_SRC_SOFT_INPUT; break; case ADC_MEASURE_ITEM_VBG: /*1x */ SAR_CTRL_SFRS->ADCCHCONF.CH1SEL = ADC_CH_SEL_REF_GND; SAR_CTRL_SFRS->ADCCHCONF.SEQCNT = (uint8_t)ADC_SQ_CH1_2_CH1; source.selection = ADC_TRIGGER_SEL_GENERAL_TRIGSRC; source.general = ADC_TRIG_SRC_SOFT_INPUT; break; case ADC_MEASURE_ITEM_VBAT: /*1/16x */ SAR_CTRL_SFRS->ADCCHCONF.CH1SEL = ADC_CH_SEL_VBAT_GND; SAR_CTRL_SFRS->ADCCHCONF.SEQCNT = (uint8_t)ADC_SQ_CH1_2_CH1; source.selection = ADC_TRIGGER_SEL_GENERAL_TRIGSRC; source.general = ADC_TRIG_SRC_SOFT_INPUT; break; case ADC_MEASURE_ITEM_VDD1V5: SAR_CTRL_SFRS->ADCCHCONF.CH1SEL = ADC_CH_SEL_1V5_GND; SAR_CTRL_SFRS->ADCCHCONF.SEQCNT = (uint8_t)ADC_SQ_CH1_2_CH1; source.selection = ADC_TRIGGER_SEL_GENERAL_TRIGSRC; source.general = ADC_TRIG_SRC_SOFT_INPUT; break; default: break; } SAR_CTRL_SFRS->SARCFG.TRIGSEL = source.selection; if (source.selection == ADC_TRIGGER_SEL_GENERAL_TRIGSRC){ SAR_CTRL_SFRS->SARCFG.TRIGSRC = source.general; }else{ SAR_CTRL_SFRS->SARCFG.PWMAUXCHSEL = source.channel; SAR_CTRL_SFRS->SARCFG.PWMAUXTRIGSEL = source.pwmAux; SAR_CTRL_SFRS->SARCFG.TRIGSRC = source.general; SAR_CTRL_SFRS->SARCFG.ROUND = 1U;//0x1: Negative code+1 } } void ADC_UnInit(AdcMeasureItem_t item) { } /** * @brief Register a callback function to ADC interrupt handler. * * @param dev Pointer to the ADC device. * @param cb The callback function to be registered. * @return 0 for success or error code upon a failure. */ void ADC_RegisterIRQ(adc_cb_func_t callback) { adcCallback = callback; SAR_CTRL_SFRS->SARINT.CLEAR.INT_CONV_DONE_CLR = 1U; SAR_CTRL_SFRS->SARINT.ENABLE.INT_CONV_DONE_ENA = 1U; NVIC_EnableIRQ(ADC_IRQn); } /** * @brief Unregister a callback function to ADC interrupt handler. * * @param dev Pointer to the ADC device. * @param cb The callback function to be unregistered. * @return 0 for success or error code upon a failure. */ void ADC_UnregisterIRQ(void) { adcCallback = NULL; SAR_CTRL_SFRS->SARINT.CLEAR.INT_CONV_DONE_CLR = 1U; SAR_CTRL_SFRS->SARINT.ENABLE.INT_CONV_DONE_ENA = 0U; NVIC_DisableIRQ(ADC_IRQn); } void ADC_Start(void) { SAR_CTRL_SFRS->SARINT.CLEAR.INT_CONV_DONE_CLR = 1U; SAR_CTRL_SFRS->SARCTRL.SARENAREQ = 1U; SAR_CTRL_SFRS->SARCTRL.CONVERT = 1U; } ADCMeasureParam_t ADC_GetadcMeasParamm(void){ return adcMeasParamm; }