/** ****************************************************************************** * @file gpio.c * @author Jerry Cai * @version V2.1 * @date 19-April-2022 * @brief gpio program body. ****************************************************************************** * @attention * * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stm32f10x.h" #include "rtc.h" #include "global.h" #define sleepEnd 60*(paraMem.sleep_min_disable&0x7FFF) //休眠1等待时长min,单位1s #define sleep2End 60*(paraMem.sleep2_min_disable&0x7FFF) //休眠2等待时长min,单位1s #define sleep2Vol paraMem.sleep2_vol //休眠方案2对应休眠电压,单位1mV #define uvoffEnd 300 //强制欠压复位等待时长5min,单位1s #define ocvEnd 60*(paraMem.ocv_min_disable&0x7FFF) //开路电压校准等待时长min,单位1s #define fcccaliEnd 60*(paraMem.cali_min_disable&0x7FFF) //校准满充容量等待时长min,单位1s _calendar_obj calendar; //时钟结构体 _calendar_obj calendar_WRITE; _calendar_obj calendar_BACKUP; uint8_t const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //平年的月修正数据表(基准是1900年1月1日),闰年其他相同只是1.2月要-1 const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31}; //平年的月份日期表.闰年的2月有29天 uint32_t timecount; //当前计时s uint32_t oldtimecnt; //上一秒的计时s uint8_t LSEErrFlag; //外部低频晶振有问题的标志,需要让屏幕的时间不再显示 uint8_t LSEErrCount;//时间不走的计数,满足了会把时间清零,标志置1 uint8_t sleep_flag; //休眠执行标志位 uint8_t sleep_enableflag;//开启休眠功能标志位 uint32_t sleeptimecount; //休眠1的计时起点s uint32_t sleeptime; //休眠启动的倒计时数 uint32_t sleep2timecount; //休眠2的计时起点s uint32_t sleep2time; //休眠2启动的倒计时数 uint32_t uvofftimecount; //关闭欠压功能后的计时起点 uint16_t uvofftime; //关闭欠压功能的倒计时数(会在屏幕显示故只设uint16) uint32_t ocvtimecount; //开路电压法的计时起点 uint32_t ocvtime; //开路电压法的倒计时数 uint32_t fcc_Calitimecount; //校准满充容量的计时起点 uint32_t fcc_Calitime; //校准满充容量的倒计时数,超过则不可更新 uint8_t RTC_UpdateFlag; //起始点刷新标志位,用以刷新休眠和欠压强制复位的时间 /* * 函数名:Is_Leap_Year * 描述 :判断是否为闰年 月份 1 2 3 4 5 6 7 8 9 10 11 12 闰年 31 29 31 30 31 30 31 31 30 31 30 31 非闰年 31 28 31 30 31 30 31 31 30 31 30 31 * 输入 :年份 * 输出 :该年份是不是闰年.1,是.0,不是 * 调用 : */ uint8_t Is_Leap_Year(uint8_t yed) { uint8_t year; year=2000+yed; if(year%4==0) //必须能被4整除 { if(year%100==0) { if(year%400==0) return 1;//如果以00结尾,还要能被400整除 else return 0; } else { return 1; } } else { return 0; } } /* * 函数名:RTC_Get_Week * 描述 :输入公历日期得到星期 * 输入 :公历年月日 * 输出 :星期号 * 调用 : */ uint8_t RTC_Get_Week(uint8_t ye, uint8_t month, uint8_t day) { uint16_t temp2; uint16_t year; uint8_t yearH,yearL; ye=ye/16*10+ye%16; //十六进制转十进制 month=month/16*10+month%16; day=day/16*10+day%16; year=2000+ye; //(输入格式决定了必定是21世纪) yearH=year/100;//用于判断是21世纪 yearL=year%100;//用于计算多的年数 //计算自1900年1月1日以来积累的多出来的天数 temp2=yearL+yearL/4; //平年365%7=1 闰年366%7=2 (自动把可以略去的7的倍数略掉了)(不用计算/100和/400) temp2=temp2%7; temp2=temp2+day+table_week[month-1]; // 21世纪需要加6(因为1900年1月1日是星期一,2000年1月1日是星期六) if(yearH == 20) { temp2+=6; } //若日期是闰年的1.2月,星期修正要-1 if(yearL%4==0&&month<3) { temp2--; } return(temp2%7!=0)?temp2%7:7; //周一到周日=1~7 } /* * 函数名:RTC_Get * 描述 :根据RTC计算器值计算当前年/月/日/时/分/秒/星期放入calendar结构体 * 输入 :无 * 输出 :0,成功;其他:错误代码 * 调用 : */ uint8_t RTC_Get(void) { static uint16_t daycnt=0; uint32_t temp=0; uint16_t temp1=0; uint16_t tempppy; timecount=RTC_GetCounter(); /*时分秒的计算*/ #if LTE_Conn temp=(timecount+28800)/86400; //得到(总秒钟数对应的)天数 //在计算年月日时,中国时区-8h #else temp=timecount/86400; //得到(总秒钟数对应的)天数 #endif if(daycnt!=temp)//超过一天了 { daycnt=temp; temp1=1970; //计算年份,从1970年开始 while(temp>=365) { if(Is_Leap_Year(temp1))//闰年-366 { if(temp>=366)temp-=366; else {temp1++;break;} } else temp-=365; //平年-365 temp1++; } tempppy=temp1; temp1=0; //计算月份,最后的temp就是日期 while(temp>=28) { if(Is_Leap_Year(tempppy)&&temp1==1)//闰年且是2月份-29 { if(temp>=29)temp-=29; else break; } else { if(temp>=mon_table[temp1])temp-=mon_table[temp1];//其他都按表上来 else break; } temp1++; } tempppy=tempppy-2000;//得到年份 calendar.w_year =(tempppy/10)*16+(tempppy%10); temp1=temp1+1; //得到月份 calendar.w_month=(temp1/10)*16+(temp1%10); temp=temp+1; //得到日期 calendar.w_date=(temp/10)*16+(temp%10); } #if LTE_Conn temp=(timecount+28800)%86400; //得到(去掉天数后 当天的)秒钟数 //在计算年月日时,中国时区-8h #else temp=timecount%86400; //得到(去掉天数后 当天的)秒钟数 #endif tempppy=temp/3600; //得到小时 calendar.hour=(tempppy/10)*16+(tempppy%10); tempppy=(temp%3600)/60;//得到分钟 calendar.min=(tempppy/10)*16+(tempppy%10); tempppy=(temp%3600)%60;//得到秒钟 calendar.sec=(tempppy/10)*16+(tempppy%10); calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期 /*判断合法*/ //在初始化后的第一次调用时,oldtimecnt还未赋值,此时将合法的当前时间写入EEPROM if(oldtimecnt==0) { oldtimecnt = timecount; if(calendar.w_month != 0) { uint8_t tmpRd[6]; tmpRd[0] = calendar.w_year; tmpRd[1] = calendar.w_month; tmpRd[2] = calendar.w_date; tmpRd[3] = calendar.hour; tmpRd[4] = calendar.min; tmpRd[5] = calendar.sec; EEPROM_WrMulByte(EE_TIME_BACKUP,tmpRd); delay_ms(5); } } //当时钟一直不走,判定有问题 if(timecount==oldtimecnt) { LSEErrCount++; if(LSEErrCount>10) { LSEErrFlag=1; sleep_Moni_Count=SLEEP_MON_CNT; sleep2_Moni_Count = SLEEP2_MON_CNT; calendar.w_year = 0; //结构体清零,方便此时的报警记录计入的时间为全0无效值 calendar.w_month = 0; calendar.w_date = 0; calendar.week = 0; calendar.hour = 0; calendar.min = 0; calendar.sec = 0; return 1; //数据异常,返回1 } } else { LSEErrCount=0; oldtimecnt = timecount; } //休眠功能-RTC,比较当前秒与开始秒的差别来定时 //方案1 if((sleep_flag == 0) && ((sleep_enableflag & 0x01) != 0)) //未进入休眠+启用休眠方案1 { if(sleeptimecount != 0) { if(RTC_UpdateFlag == 1) { sleeptimecount = timecount - (sleepEnd - sleeptime); //更新起始点=当前时间-已消耗时间,此时剩余时间保持原值 } else { sleeptime = sleepEnd - (timecount - sleeptimecount); //更新剩余时间 } if((sleeptime == 0) || (sleeptime > sleepEnd)) { sleep_flag = 1; #if LTE_Conn pre_sleep_flag = 2; pre_sleep_waitCnt = 0; sleepOn_time=timecount; #endif } } else { sleeptimecount = timecount; } } //方案2 if((sleep_flag == 0) && ((sleep_enableflag & 0x02) != 0)) //未进入休眠+启用休眠方案2 { //满足休眠电压,无充电电流 if((cellVoltageMin <= sleep2Vol) && (bmsMem.packCurrent < 500)) { if(sleep2timecount != 0) { if(RTC_UpdateFlag == 1) { sleep2timecount = timecount - (sleep2End - sleep2time); //更新起始点=当前时间-已消耗时间,此时剩余时间保持原值 } else { sleep2time = sleep2End - (timecount - sleep2timecount); //更新剩余时间 } if((sleep2time == 0) || (sleep2time > sleep2End)) { #if Key_PressLong power_old = 4; //写入关机 power_state = 0; #else sleep_flag = 1; #if LTE_Conn pre_sleep_flag = 2; pre_sleep_waitCnt = 0; sleepOn_time=timecount; #endif #endif } } else { sleep2timecount = timecount; } } //否则停止计时 else { sleep2timecount = 0; } } //不启用任何休眠方案 if(sleep_enableflag == 0) { sleep_flag = 0; } //屏幕手动关欠压启动了 if((bmsMem.balanceStatus & 0x20) != 0) { if(RTC_UpdateFlag == 1) { uvofftimecount = timecount - (uvoffEnd - uvofftime); //更新起始点=当前时间-已消耗时间,此时剩余时间保持原值 } else { uvofftime = uvoffEnd - (timecount - uvofftimecount); } if((uvofftime == 0) || (uvofftime > uvoffEnd)) //防止反向溢出 { bmsMem.balanceStatus &= 0xffdf; } } //开路电压法校准SOC启动了 if(OCV_Wait_flag == 1) { if(RTC_UpdateFlag == 1) { ocvtimecount = timecount - (ocvEnd - ocvtime); //更新起始点=当前时间-已消耗时间,此时剩余时间保持原值 } else { ocvtime = ocvEnd - (timecount - ocvtimecount); } if((ocvtime == 0) || (ocvtime > ocvEnd)) //防止反向溢出 { OCV_CaliSOC_flag = 1; } } //充电校准满充容量的倒计时启动了 if(fcc_CaliStartFlag == 1) { if(RTC_UpdateFlag == 1) { fcc_Calitimecount = timecount - (fcccaliEnd - fcc_Calitime); //更新起始点=当前时间-已消耗时间,此时剩余时间保持原值 } else { fcc_Calitime = fcccaliEnd - (timecount - fcc_Calitimecount); } if((fcc_Calitime == 0) || (fcc_Calitime > fcccaliEnd)) //防止反向溢出 { fcc_CaliStartFlag = 0; EEPROM_WrMulByte(EE_FCC_TIME,ClearEE); delay_ms(5); } } //该刷新的都刷新后,标志置0 if(RTC_UpdateFlag != 0) { RTC_UpdateFlag = 0; } return 0; } /* * 函数名:RTC_Set * 描述 :把输入的年/月/日/时/分/秒转换为秒钟 写入RTC计数器 以1970年1月1日为基准 * 输入 :无 * 输出 :0,成功;1:错误代码 * 调用 : */ uint8_t RTC_Set(uint8_t ear,uint8_t smon,uint8_t sday,uint8_t hour,uint8_t min,uint8_t sec) { uint16_t t,syear; uint32_t seccount=0; ear=(ear/16)*10+ear%16; smon=(smon/16)*10+smon%16; sday=(sday/16)*10+sday%16; hour=(hour/16)*10+hour%16; min=(min/16)*10+min%16; sec=(sec/16)*10+sec%16; syear=2000+ear; if(syear<1970||syear>2099) //1970~2099年为合法年份 { return 1; } for(t=1970;tCRL &= (uint16_t)~RTC_FLAG_RSF; /* Loop until RSF flag is set */ while ((RTC->CRL & RTC_FLAG_RSF) == (uint16_t)RESET) { temp++; if(temp>=2000) return 1; //初始化时钟失败,晶振有问题 delay_ms(1); //1ms延时,总共2s } return 0; } /* * 函数名:uf_RTC_Init * 描述 :RTC初始化配置.第一次配置时会写入2023-6-25 14:00:00. * 输入 :无 * 输出 :0,成功;1:错误代码 * 调用 : */ //开机执行一次 //第一次配置写入2023-6-25 14:00:00,此后正常读RTC后备寄存器的存值。若RTC值意外丢失则读EEPROM存值使用 uint8_t uf_RTC_Init(void) { uint16_t temp=0; uint8_t tmpRd[6]; //上电读备份的时间信息 EEPROM_RdMulByte(EE_TIME_BACKUP,tmpRd); if((tmpRd[0]!=0xff) && (tmpRd[1]!=0xff) && (tmpRd[2]!=0xff) && (tmpRd[3]!=0xff) && (tmpRd[4]!=0xff) && (tmpRd[5]!=0xff)) //时分秒格式存储,不可能存在0xff { calendar_BACKUP.w_year = tmpRd[0]; calendar_BACKUP.w_month = tmpRd[1]; calendar_BACKUP.w_date = tmpRd[2]; calendar_BACKUP.hour = tmpRd[3]; calendar_BACKUP.min = tmpRd[4]; calendar_BACKUP.sec = tmpRd[5]; } else { //0x23,0x06,0x25,0x14,0x00,0x00 calendar_BACKUP.w_year = 0x23; calendar_BACKUP.w_month = 0x06; calendar_BACKUP.w_date = 0x25; calendar_BACKUP.hour = 0x14; calendar_BACKUP.min = 0x00; calendar_BACKUP.sec = 0x00; } RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外设时钟 PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问 if(BKP_ReadBackupRegister(BKP_DR1) != 0x5050) //检查是不是第一次配置时钟 { // /*使用内部低速晶振*/ // BKP_DeInit(); //复位备份区域 // RCC_LSICmd(ENABLE); //使能LSI时钟 // while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) //等待LSI晶振就绪 // { // temp++; // if(temp>=5000) return 1; //持续5s无法起振,初始化时钟失败,晶振有问题 // delay_ms(1); // 1ms延时 // } // RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //设置RTC时钟(RTCCLK),选择LSI作为RTC的时钟源 // RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 // RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 // RTC_WaitForSynchro(); //等待RTC寄存器同步 // RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断 // RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 // RTC_EnterConfigMode(); //允许配置 // RTC_SetPrescaler(40000 - 1); //设置RTC预分频的值40kHz // RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 // /*使用内部低速晶振*/ /*使用外部低速晶振*/ BKP_DeInit(); //复位备份区域 RCC_LSEConfig(RCC_LSE_ON); //设置外部低速晶振(LSE),使用外设低速晶振 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //检查指定的RCC标志位设置与否,等待低速晶振就绪 { temp++; if(temp>=5000) return 1; //持续5s无法起振,初始化时钟失败,晶振有问题 delay_ms(1); // 1ms延时 } RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟 RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 RTC_WaitForSynchro(); //等待RTC寄存器同步 RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 RTC_EnterConfigMode(); // 允许配置 RTC_SetPrescaler(32767); //设置RTC预分频的值 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 /*使用外部低速晶振*/ //RTC_Set(0x23,0x06,0x25,0x14,0x00,0x00); RTC_Set(calendar_BACKUP.w_year,calendar_BACKUP.w_month,calendar_BACKUP.w_date,calendar_BACKUP.hour,calendar_BACKUP.min,calendar_BACKUP.sec); RTC_ExitConfigMode(); //退出配置模式 BKP_WriteBackupRegister(BKP_DR1, 0x5050); //向指定的后备寄存器中写入指定数据 } else//系统继续计时 { // /*使用内部低速晶振*/ // RCC_LSICmd(ENABLE); //使能LSI时钟 // while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) //等待LSI晶振就绪 // { // temp++; // if(temp>=5000) return 1; //持续5s无法起振,初始化时钟失败,晶振有问题 // delay_ms(1); // 1ms延时 // } // RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 // /*使用内部低速晶振*/ if(RTC_GetSynchro() == 1)return 1; //等待RTC寄存器同步 //10.8 晶振坏了这里会卡死,所以增加超时失败退出 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 } /**更多功能**/ //更新当前时间 timecount=RTC_GetCounter(); //若启用休眠1,则以当前秒数为起始点 if((paraMem.sleep_min_disable & 0x8000) == 0) //0代表启用休眠 { sleep_enableflag |= 0x01; sleeptimecount=timecount; } else { sleep_enableflag &= 0xfe; } //若启用休眠2,则判断此时最低电压是否满足条件,满足则以当前秒数为起始点 if((paraMem.sleep2_min_disable & 0x8000) == 0) //0代表启用休眠 { sleep_enableflag |= 0x02; //满足休眠电压,无均衡,无电流 if((cellVoltageMin <= sleep2Vol) && ((bmsMem.balanceStatus & 0x0001) == 0) && (bmsMem.packCurrent > (-200)) && (bmsMem.packCurrent < 200)) { //无除过压以外的保护 if(((bmsMem.bStatus1 & 0x067e) == 0) && ((bmsMem.bStatus2 & 0x00ff) == 0) && ((bmsMem.bStatus3 & 0x0008) == 0) && ((bmsMem.temperaStatus & 0x0f7f) == 0)) { sleep2timecount=timecount; } } } else { sleep_enableflag &= 0xfd; } return 0; //ok } /* * 函数名:uf_RTC_Update * 描述 :将calendar_WRITE结构体的值写入RTC时间 * 输入 :无 * 输出 :0,成功;1:错误代码 * 调用 : */ uint8_t uf_RTC_Update(void) { if(calendar_WRITE.w_month != 0) //有写入的数组 { uint16_t temp=0; uint8_t Wrtime[6]; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外设时钟 PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问 // /*使用内部低速晶振*/ // BKP_DeInit(); //复位备份区域 // RCC_LSICmd(ENABLE); //使能LSI时钟 // while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) //等待LSI晶振就绪 // { // temp++; // if(temp>=5000) return 1; //持续5s无法起振,初始化时钟失败,晶振有问题 // delay_ms(1); // 1ms延时 // } // RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //设置RTC时钟(RTCCLK),选择LSI作为RTC的时钟源 // RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 // RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 // RTC_WaitForSynchro(); //等待RTC寄存器同步 // RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断 // RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 // RTC_EnterConfigMode(); //允许配置 // RTC_SetPrescaler(40000 - 1); //设置RTC预分频的值40kHz // RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 // /*使用内部低速晶振*/ /*使用外部低速晶振*/ BKP_DeInit(); //复位备份区域 RCC_LSEConfig(RCC_LSE_ON); //设置外部低速晶振(LSE),使用外设低速晶振 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //检查指定的RCC标志位设置与否,等待低速晶振就绪 { temp++; if(temp>=5000) return 1; //持续5s无法起振,初始化时钟失败,晶振有问题 delay_ms(1); // 1ms延时 } RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟 RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 RTC_WaitForSynchro(); //等待RTC寄存器同步 RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 RTC_EnterConfigMode(); // 允许配置 RTC_SetPrescaler(32767); //设置RTC预分频的值 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 /*使用外部低速晶振*/ RTC_Set(calendar_WRITE.w_year,calendar_WRITE.w_month,calendar_WRITE.w_date,calendar_WRITE.hour,calendar_WRITE.min,calendar_WRITE.sec); RTC_ExitConfigMode(); //退出配置模式 BKP_WriteBackupRegister(BKP_DR1, 0x5050); //向指定的后备寄存器中写入用户程序数据 //刷新休眠和欠压复位的时间 RTC_UpdateFlag = 1; //存储时间备份 Wrtime[0] = calendar_WRITE.w_year; Wrtime[1] = calendar_WRITE.w_month; Wrtime[2] = calendar_WRITE.w_date; Wrtime[3] = calendar_WRITE.hour; Wrtime[4] = calendar_WRITE.min; Wrtime[5] = calendar_WRITE.sec; EEPROM_WrMulByte(EE_TIME_BACKUP,Wrtime); delay_ms(5); //清零 calendar_WRITE.w_year = 0; calendar_WRITE.w_month = 0; calendar_WRITE.w_date = 0; calendar_WRITE.week = 0; calendar_WRITE.hour = 0; calendar_WRITE.min = 0; calendar_WRITE.sec = 0; } return 0; //ok } //用于处理因各种原因需要的时间备份 int32_t oldCur; void RTC_BackUp(void) { uint8_t WrFlag=0; //当正在充放电,开始时记录一次,之后每5分钟记录一次 if(bCHGING == 1) { if(oldCur <= 0) //原来在放电或待机 { WrFlag = 1; oldCur = bmsMem.packCurrent; } if((calendar.min%5 == 0x00) && (calendar.sec == 0x00)) { WrFlag = 1; } } else if(bDSGING == 1) { if(oldCur >= 0) //原来在充电或待机 { WrFlag = 1; oldCur = bmsMem.packCurrent; } if((calendar.min%5 == 0x00) && (calendar.sec == 0x00)) { WrFlag = 1; } } //在待机状态,每1h记录一次 else { oldCur = 0; if((calendar.min == 0x00) && (calendar.sec == 0x00)) { WrFlag = 1; } } //需要写入备份时间,执行 if(WrFlag == 1) { if(calendar.w_month != 0) { uint8_t tmpRd[6]; tmpRd[0] = calendar.w_year; tmpRd[1] = calendar.w_month; tmpRd[2] = calendar.w_date; tmpRd[3] = calendar.hour; tmpRd[4] = calendar.min; tmpRd[5] = calendar.sec; EEPROM_WrMulByte(EE_TIME_BACKUP,tmpRd); delay_ms(5); } } }