#include "system.h" #include "rtc.h" #include "Systick.h" #include "USART.h" _calendar_obj calendar;//时钟结构体 extern u8 RS485_RX_BUF[64]; extern u8 buf[51]; u8 a,b; void static RTC_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //RTC全局中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级1位,从优先级3位 //NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //先占优先级0位,从优先级4位 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能该通道中断 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 } //实时时钟配置 //初始化RTC时钟,同时检测时钟是否工作正常 //BKP->DR1用于保存是否第一次配置的设置 //返回0:正常 //其他:错误代码 //void RCC_Configuration(void) //{ // // 错误处理函数 // ErrorStatus HSEStartUpStatus; // // 重置RCC配置为默认值 // RCC_DeInit(); // // 打开HSE // RCC_HSEConfig(RCC_HSE_ON); // // 等待HSE启动 // HSEStartUpStatus = RCC_WaitForHSEStartUp(); // if(HSEStartUpStatus == SUCCESS) // { // // 使能预取指 // FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); // // 设置FLASH等待状态 // FLASH_SetLatency(FLASH_Latency_2); // // HCLK = SYSCLK // RCC_HCLKConfig(RCC_SYSCLK_Div1); // // PCLK2 = HCLK // RCC_PCLK2Config(RCC_HCLK_Div1); // // PCLK1 = HCLK/2 // RCC_PCLK1Config(RCC_HCLK_Div2); // // PLLCLK = 8MHz * 9 = 72 MHz // RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); // // 使能PLL // RCC_PLLCmd(ENABLE); // // 等待PLL准备就绪 // while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) // { // } // // 选择PLL作为系统时钟源 // RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // // 等待PLL成为系统时钟源 // while(RCC_GetSYSCLKSource() != 0x08) // { // } // } //} u8 RTC_Init(void) { //检查是不是第一次配置时钟 //printf("rtc_init start\r\n"); u8 temp=0; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外设时钟 PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问 if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050) //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎 { BKP_DeInit(); //复位备份区域 // 使用外部晶振 RCC_HSEConfig(RCC_HSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET&&temp<250) //检查指定的RCC标志位设置与否,等待低速晶振就绪 { temp++; delay_ms(10); } if(temp>=250)return 1;//初始化时钟失败,晶振有问题 //printf("rtc_init \r\n"); RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128); //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟 //printf("HSE is timesource\r\n"); RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 RTC_WaitForSynchro(); //等待RTC寄存器同步 RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 RTC_EnterConfigMode();/// 允许配置 RTC_SetPrescaler(62500); //设置RTC预分频的值 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 RTC_Set(2023,9,1,0,00,00); //设置时间 RTC_ExitConfigMode(); //退出配置模式 BKP_WriteBackupRegister(BKP_DR1, 0X5050); //向指定的后备寄存器中写入用户程序数据 } else//系统继续计时 { RTC_WaitForSynchro(); //等待最近一次对RTC寄存器的写操作完成 RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 } RTC_NVIC_Config();//RCT中断分组设置 RTC_Get(&a,&b);//更新时间 return 0; //ok } //void RTC_Init(void) //{ // // 配置系统时钟 // RCC_Configuration(); // // 配置RTC // RTC_Configuration(); //} u8 RTC_synchronization_ins(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)//时钟同步 { //u16 year=buf[3]+2000; //检查是不是第一次配置时钟 u8 temp=0; 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); RCC_HSEConfig(RCC_HSE_ON); //设置外RCC_FLAG_LSIRDY部低速晶振(LSE),使用外设低速晶振 while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET&&temp<250) //检查指定的RCC标志位设置与否,等待低速晶振就绪 { temp++; delay_ms(10); } if(temp>=250)return 1;//初始化时钟失败,晶振有问题 RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128); //设置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(62500); //设置RTC预分频的值 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 //RTC_Set(2017,4,30,20,17,00); //设置时间 RTC_Set( syear, smon, sday, hour, min, sec); //设置时间 RTC_ExitConfigMode(); //退出配置模式 BKP_WriteBackupRegister(BKP_DR1, 0X5050); //向指定的后备寄存器中写入用户程序数据 // } // else//系统继续计时 // { // RTC_WaitForSynchro(); //等待最近一次对RTC寄存器的写操作完成 // RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断 // RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 // } RTC_NVIC_Config();//RCT中断分组设置 RTC_Get(&a,&b);//更新时间 return 0; } //RTC时钟中断 //每秒触发一次 //extern u16 tcnt; void RTC_IRQHandler(void) { if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断 { RTC_Get(&a,&b);//更新时间 //printf("RTC Time:%d-%d-%d %d:%d:%d\r\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec); } if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断 { RTC_ClearITPendingBit(RTC_IT_ALR); //清闹钟中断 RTC_Get(&a,&b); //更新时间 //printf("Alarm Time:%d-%d-%d %d:%d:%d\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);//输出闹铃时间 } RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW); //清闹钟中断 RTC_WaitForLastTask(); } //判断是否是闰年函数 //月份 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,不是 u8 Is_Leap_Year(u16 year) { 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; } //设置时钟 //把输入的时钟转换为秒钟 //以1970年1月1日为基准 //1970~2099年为合法年份 //返回值:0,成功;其他:错误代码. //月份数据表 u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表 //平年的月份日期表 const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31}; u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec) { u16 t; u32 seccount=0; if(syear<1970||syear>2099)return 1; for(t=1970;t2099)return 1; for(t=1970;t=365) { if(Is_Leap_Year(temp1))//是闰年 { if(temp>=366)temp-=366;//闰年的秒钟数 else {temp1++;break;} } else temp-=365; //平年 temp1++; } calendar.w_year=temp1;//得到年份 temp1=0; while(temp>=28)//超过了一个月 { if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份 { if(temp>=29)temp-=29;//闰年的秒钟数 else break; } else { if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年 else break; } temp1++; } calendar.w_month=temp1+1; //得到月份 calendar.w_date=temp+1; //得到日期 } temp=timecount%86400; //得到秒钟数 calendar.hour=temp/3600; //小时 calendar.min=(temp%3600)/60; //分钟 calendar.sec=(temp%3600)%60; //秒钟 calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期 *hour=calendar.hour; *minute=calendar.min; return 0; //return calendar.hour; } //获得现在是星期几 //功能描述:输入公历日期得到星期(只允许1901-2099年) //输入参数:公历年月日 //返回值:星期号 u8 RTC_Get_Week(u16 year,u8 month,u8 day) { u16 temp2; u8 yearH,yearL; yearH=year/100; yearL=year%100; // 如果为21世纪,年份数加100 if (yearH>19)yearL+=100; // 所过闰年数只算1900年之后的 temp2=yearL+yearL/4; temp2=temp2%7; temp2=temp2+day+table_week[month-1]; if (yearL%4==0&&month<3)temp2--; return(temp2%7); }