Index: sdk/yc_adc.h
===================================================================
--- /YC3121_SDK/fw/sdk/yc_adc.h	(revision 823)
+++ /YC3121_SDK/fw/sdk/yc_adc.h	(working copy)
@@ -100,5 +100,6 @@
  * @retval The filtered result,-1:get result failed
  */
 int ADC_Filt(ADC_ChxTypeDef ADC_Channel);
+int ADC_GetVoltage_Verify(ADC_ChxTypeDef ADC_Channel,int ref_vol_low,int ref_vol_high,int vol_low,int vol_high);
 
 #endif   /* __YC_ADC_H__ */
Index: sdk/yc_adc.c
===================================================================
--- /YC3121_SDK/fw/sdk/yc_adc.c	(revision 823)
+++ /YC3121_SDK/fw/sdk/yc_adc.c	(working copy)
@@ -9,9 +9,61 @@
 
 #define ADC_RESULT (0x7FE&ADC_RDATA)
 
+//#define ADC_CALIBR_OPEN
+#define ADC_1V_DIFF_VALUE       (0x20)
+#define ADC_CALIB_0V_GPIO       (40)
+#define ADC_CALIB_0V_CHANNEL    (ADC_CHANNEL_3)
 extern Boolean ipc_inited;
 static int calculate_voltage(int result, int vol_high_ref, int vol_low_ref, int vol_high, int vol_low);
 uint8_t r_otp_ref_para[16];
+static int io_vol_low_ref = 0;
+static int io_vol_high_ref = 0;
+
+static void ADC_Calibration_Para(void)
+{
+    int adc_0v_value = 0;
+    int adc_1v_value = 0;
+    uint8_t cnt = 5;
+    
+    /*get 0v ad value*/
+    
+    uint8_t gpio_func = GPIO_CONFIG(ADC_CALIB_0V_GPIO);
+    GPIO_CONFIG(ADC_CALIB_0V_GPIO) = OUTPUT_LOW;
+    delay_ms(5);
+    while(cnt -- )
+    {
+        adc_0v_value = ADC_GetResult(ADC_CALIB_0V_CHANNEL);
+        if(adc_0v_value > 0x3e0 && adc_0v_value < 0x420)
+        {
+            break;
+        }
+        delay_us(300);
+    }
+    GPIO_CONFIG(ADC_CALIB_0V_GPIO) = gpio_func;
+    
+    /*Calibration 1v para*/
+    
+    int k = ((((r_otp_ref_para[3] << 8) | r_otp_ref_para[2]) -  adc_0v_value)*1000)/ IO_LOW_VOLTAGE_REF;
+    adc_1v_value =  (IO_LOW_VOLTAGE_REF * k + (((r_otp_ref_para[3] << 8) | r_otp_ref_para[2])*1000))/1000;
+    
+    int diff = adc_1v_value > ((r_otp_ref_para[9] << 8) | r_otp_ref_para[8])? adc_1v_value -  ((r_otp_ref_para[9] << 8) | r_otp_ref_para[8]): ((r_otp_ref_para[9] << 8) | r_otp_ref_para[8]) - adc_1v_value;
+    if(diff > ADC_1V_DIFF_VALUE)
+    {
+        r_otp_ref_para[9] = r_otp_ref_para[3];
+        r_otp_ref_para[8] = r_otp_ref_para[2];
+        r_otp_ref_para[2] = adc_0v_value & 0xff;
+        r_otp_ref_para[3] = adc_0v_value >> 8 & 0xff;
+        io_vol_low_ref = 0;
+        io_vol_high_ref = IO_LOW_VOLTAGE_REF;
+    }
+    else
+    {
+        io_vol_low_ref = IO_LOW_VOLTAGE_REF;
+        io_vol_high_ref = IO_HIHG_VOLTAGE_REF;
+    }
+    
+    return ;
+}
 
 void ADC_Init(ADC_InitTypeDef *ADC_InitStruct)
 {
@@ -35,6 +87,13 @@
     
     //read otp reference
     read_otp(ADC_REF_OTP_ADDR, r_otp_ref_para, 16);
+#ifdef  ADC_CALIBR_OPEN
+    /*adc calibration*/
+    ADC_Calibration_Para();
+#else
+    io_vol_low_ref = IO_LOW_VOLTAGE_REF;
+    io_vol_high_ref = IO_HIHG_VOLTAGE_REF;
+#endif
 }
 
 uint16_t  ADC_GetResult(ADC_ChxTypeDef ADC_Channel)
@@ -103,6 +162,7 @@
 
 int ADC_GetVoltage(ADC_ChxTypeDef ADC_Channel)
 {
+    int v_rang = 0;
     int result = 0;
     int i = 0, j = 0;
     int voltage_low  = 2800;
@@ -120,8 +180,9 @@
     case ADC_GPIO:
         reg_voltage_low  = ((r_otp_ref_para[3] << 8) | r_otp_ref_para[2]) * 1000;
         ref_voltage_high = ((r_otp_ref_para[9] << 8) | r_otp_ref_para[8]) * 1000;
-        voltage_low = IO_LOW_VOLTAGE_REF;
-        voltage_high = IO_HIHG_VOLTAGE_REF;
+        voltage_low = io_vol_low_ref;
+        voltage_high = io_vol_high_ref;
+        v_rang = 1200;
         break;
 
     case ADC_HVIN:
@@ -129,6 +190,7 @@
         ref_voltage_high = ((r_otp_ref_para[11] << 8) | r_otp_ref_para[10]) * 1000; //OTP中5.0V校准值
         voltage_low = HVIN_LOW_VOLTAGE_REF;
         voltage_high = HVIN_HIHG_VOLTAGE_REF;
+        v_rang = 5500;
         break;
 
     case ADC_VINLPM:
@@ -136,6 +198,7 @@
         ref_voltage_high = ((r_otp_ref_para[11] << 8) | r_otp_ref_para[10]) * 1000;
         voltage_low = VINLPM_LOW_VOLTAGE_REF;
         voltage_high = VINLPM_HIHG_VOLTAGE_REF;
+       v_rang = 1200;
         break;
     default:
         return -1;
@@ -171,7 +234,7 @@
     {
         result += adc_result_buf[i];
     }
-    return result / (FILT_NUM - 2 * REMOVE_NUM);
+    return (result / (FILT_NUM - 2 * REMOVE_NUM)) < v_rang ? (result / (FILT_NUM - 2 * REMOVE_NUM)) : v_rang;
 }
 
 /**
@@ -188,6 +251,6 @@
     int rega = result * 1000 - vol_low_ref;
     int regb = vol_high_ref - vol_low_ref;
     int regc = vol_high - vol_low;
-    int temp = (rega * regc) / regb + vol_low;
+    int temp = ((rega * regc) / regb + vol_low) > 0 ? ((rega * regc) / regb + vol_low) : -((rega * regc) / regb + vol_low)  ;
     return temp;
 }
