forked from SZV10X_Software/SZV103_FM33A0xxEV_SiZhu

wujiazhi
2024-06-13 72def895431ad7a08e635b11f3da738e2b2c4618
Soft/billing.c
New file
@@ -0,0 +1,408 @@
#include "billing.h"
#include "sundry.h"
#include "string.h"
#include "system_parameter.h"
#include "main.h"
#include "system_log.h"
double yesterday_cumulate_sc = 0;
uint8_t no_use_gas_days_cnt = 0;
ErrorStatus_STM32 have_gprs_send_flag = ERROR_1;
uint8_t no_gprs_days_cnt = 0;
BILLING_REAL_PARA_T billing_real_para_g = {
    .price_type_mode_now = 0,
    .price_now = 10000,     // Ä¬Èϵ¥¼Û ·Å´ó10000±¶
    .balance_now = 10.0f // Ä¬ÈÏÓà¶î
};
TYPE_CHECK_SIZE(BILLING_ALARM_CFG_T,39);//ºË²é½á¹¹Ìå´óС
BILLING_ALARM_CFG_T billing_alarm_cfg_g = {
    .balance_small_value = {10000, 5000, 0, -5000, -10000}, //·Å´ó100±¶
    .cumulate_flow_value = 0,
    .no_gprs_days = 5,
    .no_use_gas_days = 7};
TYPE_CHECK_SIZE(LADDER_PRICE_CFG_PARA_T,111);//ºË²é½á¹¹Ìå´óС
LADDER_PRICE_CFG_PARA_T ladder_price_cfg_para_true_g = {
    .price_ver = LADDER_PRICE_DEFAULT_VER,
    .normal_price_now = 10000,
    .set_price_type_mode = SPM_NORMAL,
    .period_state = PPS_CYCLICALLY,
    .period_start_time = {0x22, 0x11, 0x01, 0, 0, 0},
    .period_unit = PPU_DAY,
    .period_duration = 30,
    .set_ladder_price = {35000, 40000, 50000, 60000, 70000},
    .set_ladder_cumulate = {500, 1000, 1500, 2000, 2500},
    .set_time_price[0] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0},
    .set_time_price[1] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0},
    .set_time_price[2] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0},
    .set_time_price[3] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0},
    .set_time_price[4] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0},
    .time_unit = PPU_DAY,
    .price_scheme_start_time = {0x22, 0x11, 0x01, 0, 0, 0},
};
LADDER_PRICE_CFG_PARA_T ladder_price_cfg_para_new_g = {
    .price_ver = LADDER_PRICE_DEFAULT_VER,
    .normal_price_now = 10000,
    .set_price_type_mode = SPM_NORMAL,
    .period_state = PPS_CYCLICALLY,
    .period_start_time = {0x22, 0x11, 0x01, 0, 0, 0},
    .period_unit = PPU_DAY,
    .period_duration = 30,
    .set_ladder_price = {35000, 40000, 50000, 60000, 70000},
    .set_ladder_cumulate = {500, 1000, 1500, 2000, 2500},
    .set_time_price[0] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0},
    .set_time_price[1] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0},
    .set_time_price[2] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0},
    .set_time_price[3] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0},
    .set_time_price[4] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0},
    .time_unit = PPU_DAY,
    .price_scheme_start_time = {0x22, 0x11, 0x01, 0, 0, 0},
};
/*¼ÆÁ¿Êý¾Ý״̬/±¨¾¯×Ö´¦Àí*/
void State_Alarm_Bytes_BillingDataHandler(double balance, BILLING_ALARM_CFG_T *billing_alarm_cfg_p)
{
   if (balance > (billing_alarm_cfg_p->balance_small_value[0] * 0.01f)) // 100 ~ ÕýÎÞÇî
   {
      __SYS_STATUS_BYTES_STATUS(balance_small_1, RESET, AV_BALANCE_1);
      __SYS_STATUS_BYTES_STATUS(balance_small_2, RESET, AV_BALANCE_2);
      __SYS_STATUS_BYTES_STATUS(balance_small_3, RESET, AV_BALANCE_3);
      __SYS_STATUS_BYTES_STATUS(balance_small_4, RESET, AV_BALANCE_4);
   }
   else if (balance > (billing_alarm_cfg_p->balance_small_value[1] * 0.01f)) // 50~100
      __SYS_STATUS_ALARM_BYTES_SET(balance_small_1);
   else if (balance > (billing_alarm_cfg_p->balance_small_value[2] * 0.01f)) // 0~50
   {
      __SYS_STATUS_ALARM_BYTES_SET(balance_small_1);
      __SYS_STATUS_ALARM_BYTES_SET(balance_small_2);
   }
   else if (balance > (billing_alarm_cfg_p->balance_small_value[3] * 0.01f)) // -50~0
   {
      __SYS_STATUS_ALARM_BYTES_SET(balance_small_1);
      __SYS_STATUS_ALARM_BYTES_SET(balance_small_2);
      __SYS_STATUS_ALARM_BYTES_SET(balance_small_3);
   }
   else // if (balance > (billing_alarm_cfg_p->balance_small_value[4] * 0.01f)) //-100 ~ -50
   {
      __SYS_STATUS_ALARM_BYTES_SET(balance_small_1);
      __SYS_STATUS_ALARM_BYTES_SET(balance_small_2);
      __SYS_STATUS_ALARM_BYTES_SET(balance_small_3);
      __SYS_STATUS_ALARM_BYTES_SET(balance_small_4);
   }
//   else // ¸ºÎÞÇî ~ -100
//   {
//      __SYS_STATUS_ALARM_BYTES_SET(balance_small_1);
//      __SYS_STATUS_ALARM_BYTES_SET(balance_small_2);
//      __SYS_STATUS_ALARM_BYTES_SET(balance_small_3);
//      __SYS_STATUS_ALARM_BYTES_SET(balance_small_4);
//      __SYS_STATUS_ALARM_BYTES_SET(balance_small_5);
//   }
  /*ÀÛ¼ÆÆøÁ¿µ½*/
  if (billing_alarm_cfg_p->cumulate_flow_value != 0)
  {
    if (sys_realtime_data_g.measure_para_s.forward_cumulate_sc >= billing_alarm_cfg_p->cumulate_flow_value)
    {
      //      Sys_Log_E2pParaWrite(cumulate_close_valve_flag,AV_SET_CUMULATE);
      __SYS_STATUS_ALARM_BYTES_SET(set_cumulate_up_to);
    }
  }
}
/*ÎÞÓÃÆø/Éϱ¨Êý¾Ý״̬/±¨¾¯×Ö´¦Àí*/
void State_Alarm_Bytes_NoGpra_NoGasHandler(BILLING_ALARM_CFG_T *billing_alarm_cfg_p)
{
   if (DAILY_ZERO) // 0µã0·Ö0Ãë
  {
    /*ÎÞÓÃÆøÌìÊýµ½*/
    if (billing_alarm_cfg_p->no_use_gas_days)
    {
      if (sys_realtime_data_g.measure_para_s.forward_cumulate_sc > yesterday_cumulate_sc)
      {
        yesterday_cumulate_sc = sys_realtime_data_g.measure_para_s.forward_cumulate_sc;
        no_use_gas_days_cnt = 0;
        __SYS_STATUS_BYTES_STATUS(no_use_gas_date_up_to, RESET, AV_NO_USE_GAS);
      }
      else
      {
        if (++no_use_gas_days_cnt >= billing_alarm_cfg_p->no_use_gas_days)
          __SYS_STATUS_ALARM_BYTES_SET(no_use_gas_date_up_to);
      }
    }
    /*ÎÞÉϱ¨ÌìÊýµ½*/
    if (billing_alarm_cfg_p->no_gprs_days)
    {
      if (have_gprs_send_flag == SUCCESS_0)
      {
        have_gprs_send_flag = ERROR_1;
        no_gprs_days_cnt = 0;
        __SYS_STATUS_BYTES_STATUS(no_gprs_date_up_to, RESET, AV_NO_GPRS);
      }
      else
      {
        if (++no_gprs_days_cnt >= billing_alarm_cfg_p->no_gprs_days)
          __SYS_STATUS_ALARM_BYTES_SET(no_gprs_date_up_to);
      }
    }
  }
}
/*ʵʱ¼Æ·Ñ³ÌÐò
 * single_flow_sum£ºµ¥´ÎµÄÁ÷Á¿ºÍ
 */
void Billing_RealTimeProcess(BILLING_MODE_T start_flag, __IO double single_flow_sum, LADDER_PRICE_CFG_PARA_T *ladder_cfg_real_p, BILLING_REAL_PARA_T *billing_para_p)
{
  if ((start_flag == BM_DEVICE || (start_flag == BM_PLATFORM && __SYS_STATUS_BYTES_GET(virtual_billing) == SET)) && single_flow_sum > 0)
  {
    double price_double = 0;
    double single_use_money = 0;
    /*²ÎÊýÅäÖÃ*/
    GasCumulant_Ladder_PeriodCfg(ladder_cfg_real_p, &ladder_price_cfg_para_new_g, &calendar_g);
    /*ËãÇ®*/
    if (ladder_cfg_real_p->set_price_type_mode == SPM_NORMAL) // ÆÕͨ¼Æ·Ñ
    {
         if(start_flag == BM_DEVICE)
            billing_para_p->price_type_mode_now = BPM_NORMAL;
         billing_para_p->price_now = ladder_cfg_real_p->normal_price_now;
      price_double = ladder_cfg_real_p->normal_price_now * 0.0001f;
      single_use_money = single_flow_sum * price_double;
      billing_para_p->residual_gas_now = billing_para_p->balance_now / price_double;
    }
    else if (ladder_cfg_real_p->set_price_type_mode == SPM_LADDER) // °´ÆøÁ¿½×ÌݼƷÑ
    {
      single_use_money = GasCumulant_Ladder_PeriodCalculation(start_flag,single_flow_sum, ladder_cfg_real_p, billing_para_p);
    }
    else if (ladder_cfg_real_p->set_price_type_mode == SPM_TIME) // °´Ê±¼ä¶Î¼Æ·Ñ
    {
    }
    billing_para_p->use_money_sum += single_use_money; // µÃ³öÀÛ¼ÆÊ¹Óýð¶î
    billing_para_p->balance_now -= single_use_money;   // µÃ³öÓà¶î
    /*¼Æ·Ñ/ÓÃÆøÏà¹Ø±¨¾¯ÅжÏ*/
    State_Alarm_Bytes_BillingDataHandler(billing_para_p->balance_now, &billing_alarm_cfg_g);
  }
   State_Alarm_Bytes_NoGpra_NoGasHandler(&billing_alarm_cfg_g);
   if(billing_para_p->balance_now > (billing_alarm_cfg_g.balance_small_value[0] * 0.01f))
   {
      /*½öÓà¶î²úÉúµÄÇ¿ÖÆÐÔ±¨¾¯¹Ø·§£¬µ±Óà¶î³ä×ãʱ×Ô¶¯½âËø*/
      if(op_cl_valve_cause_id >= 0x90 && op_cl_valve_cause_id <= 0x94 && __SYS_STATUS_BYTES_GET(valve_state) == VALVE_CL)
      {
         if(__SYS_STATUS_BYTES_GET(valve_lock) == SET)
         {
            __VALVE_WORK_TYPE_SET(VWT_UNLOCK);                       // ½âËø£¨ÓÃÓÚ´æ´¢¼Ç¼£©
            __SYS_STATUS_BYTES_STATUS(valve_lock, RESET, AV_NORMAL); // ½âËø£¨ÓÃÓÚÕæÕý¿ØÖÆ£©
         }
      }
   }
}
/*ÆøÌåÀÛ»ýÁ¿-½×ÌݼÆËã*/
double GasCumulant_Ladder_PeriodCalculation(BILLING_MODE_T mode_flag,double single_flow_sum,
                                                                  LADDER_PRICE_CFG_PARA_T *ladder_cfg_p_p, BILLING_REAL_PARA_T *billing_para_p_p)
{
  double price_double = 0;     // µ¥¼Û
  double single_use_money = 0; // µ¥´ÎµÄʹÓýð¶î
  double ladder_cumulate_sc_before = billing_para_p_p->ladder_cumulate_sc;
  billing_para_p_p->ladder_cumulate_sc += single_flow_sum;                            // ½×ÌÝÖÜÆÚÄÚµÄÀÛ»ýÁ¿
  if (billing_para_p_p->ladder_cumulate_sc <= ladder_cfg_p_p->set_ladder_cumulate[0]) // 0~100
  {
      if(mode_flag == BM_DEVICE)
         billing_para_p_p->price_type_mode_now = BPM_LADDER_1;
    /*¼ÆËãµ¥´ÎµÄʹÓýð¶î*/
    billing_para_p_p->price_now = ladder_cfg_p_p->set_ladder_price[0];
    price_double = ladder_cfg_p_p->set_ladder_price[0] * 0.0001f;
    single_use_money = single_flow_sum * price_double;
  }
  else if (billing_para_p_p->ladder_cumulate_sc <= ladder_cfg_p_p->set_ladder_cumulate[1]) // 100~200
  {
    price_double = ladder_cfg_p_p->set_ladder_price[1] * 0.0001f;
    if (ladder_cumulate_sc_before < ladder_cfg_p_p->set_ladder_cumulate[0]) // ÉÏ´ÎÊý¾ÝСÓÚÁÙ½çÖµ£¬±¾´ÎÊý¾ÝÈ´´óÓÚÁÙ½çÖµ
    {
         if(mode_flag == BM_DEVICE)
            billing_para_p_p->price_type_mode_now = BPM_LADDER_2;
      single_use_money = (ladder_cfg_p_p->set_ladder_cumulate[0] - ladder_cumulate_sc_before) * (ladder_cfg_p_p->set_ladder_price[0] * 0.0001f) +
                         (billing_para_p_p->ladder_cumulate_sc - ladder_cfg_p_p->set_ladder_cumulate[0]) * price_double;
      billing_para_p_p->price_now = ladder_cfg_p_p->set_ladder_price[1];
    }
    else
      single_use_money = single_flow_sum * price_double;
  }
  else if (billing_para_p_p->ladder_cumulate_sc <= ladder_cfg_p_p->set_ladder_cumulate[2]) // 200~300
  {
    price_double = ladder_cfg_p_p->set_ladder_price[2] * 0.0001f;
    if (ladder_cumulate_sc_before < ladder_cfg_p_p->set_ladder_cumulate[1]) // ÉÏ´ÎÊý¾ÝСÓÚÁÙ½çÖµ£¬±¾´ÎÊý¾ÝÈ´´óÓÚÁÙ½çÖµ
    {
         if(mode_flag == BM_DEVICE)
            billing_para_p_p->price_type_mode_now = BPM_LADDER_3;
      single_use_money = (ladder_cfg_p_p->set_ladder_cumulate[1] - ladder_cumulate_sc_before) * (ladder_cfg_p_p->set_ladder_price[1] * 0.0001f) +
                         (billing_para_p_p->ladder_cumulate_sc - ladder_cfg_p_p->set_ladder_cumulate[1]) * price_double;
      billing_para_p_p->price_now = ladder_cfg_p_p->set_ladder_price[2];
    }
    else
      single_use_money = single_flow_sum * price_double;
  }
  else if (billing_para_p_p->ladder_cumulate_sc <= ladder_cfg_p_p->set_ladder_cumulate[3]) // 300~400
  {
    price_double = ladder_cfg_p_p->set_ladder_price[3] * 0.0001f;
    if (ladder_cumulate_sc_before < ladder_cfg_p_p->set_ladder_cumulate[2]) // ÉÏ´ÎÊý¾ÝСÓÚÁÙ½çÖµ£¬±¾´ÎÊý¾ÝÈ´´óÓÚÁÙ½çÖµ
    {
         if(mode_flag == BM_DEVICE)
            billing_para_p_p->price_type_mode_now = BPM_LADDER_4;
      single_use_money = (ladder_cfg_p_p->set_ladder_cumulate[2] - ladder_cumulate_sc_before) * (ladder_cfg_p_p->set_ladder_price[2] * 0.0001f) +
                         (billing_para_p_p->ladder_cumulate_sc - ladder_cfg_p_p->set_ladder_cumulate[2]) * price_double;
      billing_para_p_p->price_now = ladder_cfg_p_p->set_ladder_price[3];
    }
    else
      single_use_money = single_flow_sum * price_double;
  }
  else // >400
  {
    price_double = ladder_cfg_p_p->set_ladder_price[4] * 0.0001f;
    if (ladder_cumulate_sc_before < ladder_cfg_p_p->set_ladder_cumulate[3]) // ÉÏ´ÎÊý¾ÝСÓÚÁÙ½çÖµ£¬±¾´ÎÊý¾ÝÈ´´óÓÚÁÙ½çÖµ
    {
         if(mode_flag == BM_DEVICE)
            billing_para_p_p->price_type_mode_now = BPM_LADDER_5;
      single_use_money = (ladder_cfg_p_p->set_ladder_cumulate[3] - ladder_cumulate_sc_before) * (ladder_cfg_p_p->set_ladder_price[3] * 0.0001f) +
                         (billing_para_p_p->ladder_cumulate_sc - ladder_cfg_p_p->set_ladder_cumulate[3]) * price_double;
      billing_para_p_p->price_now = ladder_cfg_p_p->set_ladder_price[4];
    }
    else
      single_use_money = single_flow_sum * price_double;
  }
  return single_use_money;
}
/*ÆøÌåÀÛ»ýÁ¿-½×ÌÝÖÜÆÚÅäÖã¨ÖÜÆÚʱ¼äµ½½×ÌÝÀÛ»ýÁ¿ÇåÁ㣩*/
void GasCumulant_Ladder_PeriodCfg(LADDER_PRICE_CFG_PARA_T *ladder_cfg_old, LADDER_PRICE_CFG_PARA_T *ladder_cfg_new, __IO RTC_TimeDateTypeDef *calendar)
{
  static uint8_t period_flag = 0;                                                                                                     // ÖÜÆÚÊ״αê־λ
  static uint8_t next_period_start_time[6] = {0};                                                                                     // ÏÂÒ»´ÎµÄÖÜÆÚ¿ªÊ¼Ê±¼ä
  uint8_t real_time[6] = {calendar->Year & 0xFF, calendar->Month, calendar->Date, calendar->Hour, calendar->Minute, calendar->Second}; // µ±Ç°Ê±¼ä
  /*ÐÂÀϰ汾²»Í¬ÇÒеļ۸ñ·½°¸ÉúЧʱ¼äµ½*/
  if ((ladder_cfg_old->price_ver != ladder_cfg_new->price_ver) &&
      Datecmp(ladder_cfg_new->price_scheme_start_time, real_time) <= 0) // Ð¼۸ñ·½°¸ÉúЧʱ¼ä <= µ±Ç°Ê±¼ä£¨Ð¼۸ñʱ¼äµ½£©
  {
    memcpy(ladder_cfg_old, ladder_cfg_new, sizeof(LADDER_PRICE_CFG_PARA_T)); // ¼Û¸ñ·½°¸Ìæ»»
    period_flag = 0;
  }
  if (ladder_cfg_old->set_price_type_mode == SPM_LADDER) // Èç¹ûµ±Ç°Êǽ×ÌݼƷÑ
  {
    if (period_flag == 0 && Datecmp(ladder_cfg_old->period_start_time, real_time) <= 0) // Ê״ε½´ïÖÜÆÚʱ¼ä
    {
      billing_real_para_g.ladder_cumulate_sc = 0;
      period_flag = 1;
      memcpy(next_period_start_time, ladder_cfg_old->period_start_time, sizeof(next_period_start_time));
      StartTime_NextCalculation(ladder_cfg_old->period_unit, ladder_cfg_old->period_duration, next_period_start_time);
    }
    else if (period_flag)
    {
      if (Datecmp(next_period_start_time, real_time) <= 0)
      {
        if (ladder_cfg_old->period_state == PPS_CYCLICALLY) // Ñ­»·Ö´ÐÐ
          StartTime_NextCalculation(ladder_cfg_old->period_unit, ladder_cfg_old->period_duration, next_period_start_time);
        else if (ladder_cfg_old->period_state == PPS_ONLY_ONE) // Ö»Ö´ÐÐÒ»´Î
          ladder_cfg_old->set_price_type_mode = SPM_NORMAL;
        billing_real_para_g.ladder_cumulate_sc = 0;
      }
    }
  }
}
/*¼ÆËãÏ´οªÊ¼Ê±¼ä*/
void StartTime_NextCalculation(PRICE_PERIOD_UNIT_T price_unit, uint16_t time_duration, uint8_t *pNext_time)
{
  uint8_t year_h, month_h, day_h, hour_h;
  uint8_t temp_quarter = 0;
  switch (price_unit)
  {
  case PPU_HOUR:
    hour_h = BCD_2_HEX_U8(pNext_time[3]) + time_duration;
    day_h = hour_h / 24;
    pNext_time[3] = HEX_2_BCD_U8(hour_h % 24);
    if (day_h)
      Add_days_CalculateYearMonTHDay(&pNext_time[0], &pNext_time[1], &pNext_time[2], day_h);
    break;
  case PPU_DAY:
    Add_days_CalculateYearMonTHDay(&pNext_time[0], &pNext_time[1], &pNext_time[2], time_duration);
    break;
  case PPU_MONTH:
    month_h = BCD_2_HEX_U8(pNext_time[1]) + time_duration;
    year_h = BCD_2_HEX_U8(pNext_time[0]);
    while (month_h > 12)
    {
      month_h -= 12;
      year_h++;
    }
    pNext_time[0] = HEX_2_BCD_U8(year_h);
    pNext_time[1] = HEX_2_BCD_U8(month_h);
    break;
  case PPU_QUARTER:
    year_h = BCD_2_HEX_U8(pNext_time[0]);
    month_h = BCD_2_HEX_U8(pNext_time[1]);
    temp_quarter = (month_h - 1) / 3; // 1~3Ϊ1 4~6Ϊ2 7~9Ϊ3 10~12Ϊ4
    temp_quarter += time_duration;
    while (temp_quarter > 3)
    {
      temp_quarter -= 4;
      year_h++;
    }
    month_h = temp_quarter * 3 + 1;
    pNext_time[0] = HEX_2_BCD_U8(year_h);
    pNext_time[1] = HEX_2_BCD_U8(month_h);
    pNext_time[2] = 1;
    pNext_time[3] = 0;
    pNext_time[4] = 0;
    pNext_time[5] = 0;
    break;
  default:
    break;
  }
}
/******************************************
 * func: Add_days_CalculateYearMonTHDay
 * desc: ¼ÆËãijÄêijÔÂijÌìÔö¼ÓЩÐíÌìÊýºó£¬ÎªÄ³ÄêijÔÂijÌì
 * input:  pYear_bcd Äê·Ýbcd
 *         pMonth_bcd Ô·Ýbcd
 *         pDay_bcd  Ììbcd
 *         add_days  Ôö¼ÓµÄÌìÊý
 * output: *pYear_bcd ¼ÆËãµÄ½á¹ûÄê·Ýbcd
 *         *pMonth_bcd ¼ÆËãµÄ½á¹ûÔ·Ýbcd
 *         *pDay_bcd ¼ÆËãµÄ½á¹ûÌìbcd
 * return: none
 * bug: ¸Ãº¯ÊýÌí¼ÓµÄÌìÊý²»ÄÜ¿äÁ½ÄêÒÔÉÏ£¬·ñÔò»á³ö´í¡£È磺¿ÉÒÔ´Ó2016ÄêÌí¼ÓÌìÊýµ½2017Ä꣬µ«Êǵ½2018ÄêÒÔÉÏ»á³ö´í
 *****************************************/
void Add_days_CalculateYearMonTHDay(uint8_t *pYear_bcd, uint8_t *pMonth_bcd, uint8_t *pDay_bcd, uint16_t add_days)
{
  uint16_t year_h = BCD_2_HEX_U8(*pYear_bcd) + 2000, temp_year_h = 0, days_of_year = 0;
  uint8_t month_h = BCD_2_HEX_U8(*pMonth_bcd), day_h = BCD_2_HEX_U8(*pDay_bcd), i;
  uint8_t leap = ((year_h % 4 == 0) && (year_h % 100 != 0)) || (year_h % 400 == 0); // 1ΪÈòÄê 0ΪƽÄê
  uint8_t days_of_month[2][13] = {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
                                  {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
  /*¼ÆËã¸ÃÄê¸ÃÔ¸ÃÌìΪµÚ¼¸Ìì*/
  for (i = 1; i < month_h; i++)
    days_of_year += days_of_month[leap][i];
  days_of_year += day_h;
  /*Ôö¼ÓÌìÊý*/
  days_of_year += add_days;
  temp_year_h = year_h;
  if (leap)
  {
    if (days_of_year > 366)
    {
      temp_year_h += days_of_year / 366;
      days_of_year -= 366;
    }
  }
  else
  {
    if (days_of_year > 365)
    {
      temp_year_h += days_of_year / 365;
      days_of_year -= 365;
    }
  }
  leap = ((temp_year_h % 4 == 0) && (temp_year_h % 100 != 0)) || (temp_year_h % 400 == 0);
  for (i = 1; days_of_year > days_of_month[leap][i]; i++)
    days_of_year -= days_of_month[leap][i];
  *pYear_bcd = HEX_2_BCD_U8(temp_year_h - 2000);
  *pMonth_bcd = HEX_2_BCD_U8(i);
  *pDay_bcd = HEX_2_BCD_U8(days_of_year);
}