K74B/app_Indie/drivers/hal/src/adc_device.c
2024-01-18 17:01:45 +08:00

202 lines
7.4 KiB
C

/**
* @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 <adc_device.h>
#include <isrfuncs.h>
#include <appConfig.h>
#include <motorControlTask.h>
#include <pwm_aux_device.h>
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;
}