/* ****************************************************************************** * * @file adc.c * @brief adc module * @ic sy8835 * * @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 \******************************************************************************/ idata int8_t ADC_Offset_Error = 0; //ADC Offset Error 校准值寄存器 idata int8_t Bat_ADC_Offset_Error = 0; idata uint8_t Vor_Isense_Gain_Error = 0; idata uint8_t Vol_Isense_Gain_Error = 0; idata int8_t Vor_Isense_Offset_Error = 0; idata int8_t Vol_Isense_Offset_Error = 0; xdata uint8_t ADC_Chn_Num = 0; idata uint16_t g_Value_Adc = 0; xdata uint16_t g_Value_Adc_Avg = 0; #if 0 xdata uint16_t g_Value_Adc0 = 0; xdata uint16_t g_Value_Adc1 = 0; xdata uint16_t g_Vref_Adc = 0; #endif xdata int16_t g_Vntc_Adc = 0; xdata int16_t g_pmu_Adc_Ivol = 0; xdata int16_t g_pmu_Adc_Ivor = 0; xdata int16_t g_Vbat_Adc = 0; xdata int16_t g_pmu_Adc_Vout = 0; xdata uint8_t g_ADC_Chn = 0; xdata uint8_t Adc_Index = 0; bit ADC_Cal_Over_Flag = 0; /******************************************************************************\ 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; #if 1 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; //Vol_Isense_Offset_Error = 10; //Vor_Isense_Offset_Error = 10; #endif EX6 = 1; //ADC IRQ Enable } /* ******************************************************************************* * void PMU_ADC_Chn_Data(PMU_ADC_CHANNELS_E pmu_Adc_Chn) * * Description : 设置相应通道的使能。在主循环中按通道设置各个通道的使能,连续模式,进中断8次后,取值,切通道。 在中断中获取对应的ADC值,减少主函数的阻塞,提升系统性能。 * * Arguments : NONE * 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。 #ifdef _DEBUG_ADC // printf("Vol:Adc_Avg:%d,Ivol:%d,Offset_Error:%d,Gain_Error:%d,temp:%d\r\n",(u16)g_Value_Adc_Avg,(u16)g_pmu_Adc_Ivol,(u16)Vol_Isense_Offset_Error,(u16)Vol_Isense_Gain_Error,(u16)( ( g_Value_Adc_Avg - Vol_Isense_Offset_Error ) )); #endif 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。 #ifdef _DEBUG_ADC // printf("Vor:Adc_Avg:%d,Ivor:%d,Offset_Error:%d,Gain_Error:%d,temp:%d\r\n",(u16)g_Value_Adc_Avg,(u16)g_pmu_Adc_Ivor,(u16)Vor_Isense_Offset_Error,(u16)Vor_Isense_Gain_Error,(u16)( ( g_Value_Adc_Avg - Vor_Isense_Offset_Error ) )); #endif 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; } //g_Value_Adc_Avg = 0; ADC_Cal_Over_Flag = 0; #ifdef _DEBUG_ADC printf("adc chn:%d,adc_value:%d,Ivol:%d,Vbat:%d,Vout:%d,Ivor:%d,Vntc:%d.\r\n",(uint16_t)ADC_Chn_Num,(uint16_t)g_Value_Adc_Avg,(uint16_t)g_pmu_Adc_Ivol,(uint16_t)g_Vbat_Adc,(uint16_t)g_pmu_Adc_Vout,(uint16_t)g_pmu_Adc_Ivor,(uint16_t)g_Vntc_Adc); #endif } 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 = 1; ADC_CTL1 &= ~0x01; //Disable ADC. } } IRQ_FLAG10 = ADC_Data_Ready; } #endif