/* ****************************************************************************** * * @file adc.c * @brief adc module * @ic sy8837/8 * * @version 1.0 * @date 2024/11/01 15:00:40 * @author Alex Xu * * Copyright (c) 2013-2099,Tkplusemi Technology Co.,Ltd. * All Rights Reserved * * History: * Revision Date Author Desc * 1.0.0 2024/11/01 Alex build this file ******************************************************************************/ /*_____ I N C L U D E S ____________________________________________________*/ #include "adc.h" #include "system.h" #include "sys_tim.h" #if ADC_ENABLE /******************************************************************************\ Macro definitions \******************************************************************************/ #define ADC_AVERAGE_CNT 8 /******************************************************************************\ Variables definitions \******************************************************************************/ static int8_t ADC_Offset_Error; //ADC Offset Error 校准值,有符号数 static int8_t Bat_ADC_Offset_Error;//电池 ADC Offset Error 校准值,有符号数 static uint8_t Vor_Isense_Gain_Error;//Vor 电流ADC GAIN Error 校准值,无符号数 static uint8_t Vol_Isense_Gain_Error;//Vol 电流ADC GAIN Error 校准值,无符号数 static int8_t Vor_Isense_Offset_Error;//Vor 电流ADC Offset Error 校准值,无符号数 static int8_t Vol_Isense_Offset_Error;//Vol 电流ADC Offset Error 校准值,无符号数 static uint8_t g_ADC_Chn;//ADC采样通道 static uint8_t Adc_Index;//ADC采样次数计数器 static bit ADC_Cal_Over_Flag;//ADC采样完成标志位 static uint16_t g_Value_Adc;//ADC采样码值 static uint16_t g_Value_Adc_Avg;//ADC多次采样值和 uint8_t ADC_Chn_Num; //ADC采样通道计数器 int16_t g_Vntc_Adc;//NTC通道ADC采样码值 int16_t g_pmu_Adc_Ivol;//Vol通道电流ADC采样码值 int16_t g_pmu_Adc_Ivor;//Vor通道电流ADC采样码值 int16_t g_Vbat_Adc;//Bat通道ADC采样码值 int16_t g_pmu_Adc_Vout;//Vout通道ADC采样码值 /******************************************************************************\ Functions definitions \******************************************************************************/ /* ******************************************************************************* * void Adc_Init(void) * * Description : ADC Initialization. --- 系统初始化调用。( ADC采样转换一次需要19个CLK,一个CLK 4us,转换一次需要76us。) ADC采用连续模式,在中断中采样8次后,等待下一个通道使能。在切换通道前取前一个通道的采样值,进行8次平均。 * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void Adc_Init(void) { SFRADDR = MFP_CTL1; //Set P07 As NTC SFRDATA |= 0x80; SFRADDR = ADC_CTL0; //0B10111101,<0x29>--ADC EN;ADC 2.5V Enable b[4];ADC1 Pullup 100K Enable b[5]; continue mode; ADC CLK divided by 48=230k SFRDATA = 0xB5; ADC_CTL1 = ( ADC_NTC << 4 ) | 0x01; //Start ADC , Enable ntc Chn. SFRADDR = IRQ_EN10; //Enable ADC Interrupt(INT6). SFRDATA |= 0x01; ADC_Offset_Error = (int8_t)( ( ADC_OFFSET & 0x0F ) - 8 ); //获取ADC Offset Error校准值。 Bat_ADC_Offset_Error = (int8_t)( ADC_OFFSET >> 4 ); /* 获取Ivox对应的Offset Error 和Gain Error */ Vol_Isense_Offset_Error = (int8_t)( ( IVOX_OFFSET & 0x0F ) - 8 ) * 10; //VOX 电流采样 offset 修调。每一个位为 10mV,1000 对应 offset 误差为 0mV,1001 对应 offset误差为 10mV,0111 对应 offset 误差为-10mV Vol_Isense_Gain_Error = IVOL_GAIN; Vor_Isense_Offset_Error = (int8_t)( ( IVOX_OFFSET >> 4 ) - 8 ) * 10; Vor_Isense_Gain_Error = IVOR_GAIN; EX6 = 1; //ADC IRQ Enable } /* ******************************************************************************* * void PMU_ADC_Chn_Data(PMU_ADC_CHANNELS_E pmu_Adc_Chn) * * Description : 设置相应通道的使能。在主循环中按通道设置各个通道的使能,连续模式,进中断取值8次叠加后,切通道。 在中断中获取对应的ADC值,减少主函数的阻塞,提升系统性能。 * * Arguments : PMU_ADC_CHANNELS_E pmu_Adc_Chn * Returns : NONE * Notes : NONE * ******************************************************************************* */ void PMU_ADC_Chn_Data( PMU_ADC_CHANNELS_E pmu_Adc_Chn ) { if( ADC_Cal_Over_Flag ) { g_Value_Adc_Avg = g_Value_Adc_Avg >> 3; /*获取xSen对应的ADC值*/ switch (g_ADC_Chn) { case ADC_NTC: g_Vntc_Adc = g_Value_Adc_Avg - ADC_Offset_Error; //NTC取码值是否需要处理Offset Error。 if( g_Vntc_Adc < 0 ) { g_Vntc_Adc = 0; } break; case ADC_IVOL: g_Value_Adc_Avg = ( (uint32_t)g_Value_Adc_Avg * 2500 ) >> 10 ; //ADC的LSB = 2500mV / 1024 = 2.44mV g_pmu_Adc_Ivol = (int32)( (int16)( g_Value_Adc_Avg - Vol_Isense_Offset_Error ) ) * 100 / (int16)( 500 + 2 * Vol_Isense_Gain_Error ) ; //IVOL电压位VOL的电流放大5倍送给ADC,例如:100mA电流,ADC采样电压为500mV。 if( g_pmu_Adc_Ivol < 0 ) //只处理正电流 { g_pmu_Adc_Ivol = 0; } break; case ADC_IVOR: g_Value_Adc_Avg = ( (uint32_t)g_Value_Adc_Avg * 2500 ) >> 10 ; //ADC的LSB = 2500mV / 1024 = 2.44mV g_pmu_Adc_Ivor = (int32)( (int16)( g_Value_Adc_Avg - Vor_Isense_Offset_Error ) ) * 100 / (int16)( 500 + 2 * Vor_Isense_Gain_Error ) ; //IVOR电压位VOR的电流放大5倍送给ADC,例如:100mA电流,ADC采样电压为500mV。 if( g_pmu_Adc_Ivor < 0 ) //只处理正电流 { g_pmu_Adc_Ivor = 0; } break; case ADC_BAT: g_Value_Adc_Avg = ((uint32_t)( g_Value_Adc_Avg ) * 2500) >> 10 ; //ADC的LSB = 2500mV / 1024 = 2.44mV g_Vbat_Adc = g_Value_Adc_Avg << 1; //VBAT的2分压。 g_Vbat_Adc += (int32)( ( g_Vbat_Adc * 4 * ( Bat_ADC_Offset_Error - 8 ) ) / 1000 ); if( g_Vbat_Adc < 0 ) { g_Vbat_Adc = 0; } break; case ADC_VOUT: g_Value_Adc_Avg = ( (int32_t)( g_Value_Adc_Avg - ADC_Offset_Error ) * 2500 ) >> 10 ; //ADC的LSB = 2500mV / 1024 = 2.44mV g_pmu_Adc_Vout = g_Value_Adc_Avg << 1; //VOUT的2分压。 if( g_pmu_Adc_Vout <0 ) { g_pmu_Adc_Vout = 0; } break; default: break; } ADC_Cal_Over_Flag = FALSE; } else { g_ADC_Chn = pmu_Adc_Chn; ADC_CTL1 = ( pmu_Adc_Chn << 4 ) | 0x01; //ADC Start Enable,Set Channel N Enabel. g_Value_Adc_Avg = 0; Adc_Index = 0; } } /* ******************************************************************************* * void EX6_ADC_isr(void ) interrupt Interrupt_Vector_IE6 * * Description : System External Intterupt 6 adc Interrupt. * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void EX6_ADC_isr(void) interrupt Interrupt_Vector_IE6 { if(IRQ_FLAG10 & ADC_Data_Ready) { g_Value_Adc = ADC_DATL; //先取低8位数据,锁定当前ADC采样值。 g_Value_Adc |= (uint16_t)( ( ADC_DATH & 0x03 ) << 8 ); if( Adc_Index < ADC_AVERAGE_CNT ) //求均值 { g_Value_Adc_Avg += g_Value_Adc; Adc_Index++; } else { ADC_Cal_Over_Flag = TRUE; ADC_CTL1 &= ~0x01; //Disable ADC. } } IRQ_FLAG10 = ADC_Data_Ready; } #endif