- #include "rtc.h"
- #if 1
- //关闭半主机模式
- #pragma import(__use_no_semihosting)
- //标准库需要的支持函数
- struct __FILE{
- int handle;
- };
- FILE __stdin, __stdout, __stderr;
- //FILE __stdin;
- //避免使用半主机模式
- void _sys_exit(int x)
- {
- x=x;
- }
-
-
- /*重写fputc*/
- int fputc(int ch, FILE *f)
- {
-
- while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //通过串口把ch给发送出去
- USART_SendData(USART1,ch);
- return ch;
- }
-
- int fgetc(FILE *f){
- char ch;
- while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
- ch=USART_ReceiveData(USART1);
- return (int)ch;
- }
- int ferror(FILE * f){
- return EOF;
- }
- void _ttywrch(int ch){
- while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
- USART_SendData(USART1,ch);
- }
- //void _sys_exit(int return_code){
- // while(1);
- //}
- #endif
-
- cal calendar;
- int const month_table[12] ={31,28,31,30,31,30,31,31,30,31,30,31};
- __IO uint8_t TimeDisplay;
- //RTC内设配置
- void rtc_init(){
- uint32_t t;
- //使能rcu_bkpi时钟,pwr电源,bkp后备区域
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE);
- //使能备份区域,允许访问备份(Backup)区域
- PWR_BackupAccessCmd(ENABLE);
-
- //备份域复位
- BKP_DeInit();
- //使能外部低速时钟,32.768k
- RCC_LSEConfig(RCC_LSE_ON);
- //等待外部低速时钟稳定
- while((RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)&& (t<10)){
- t++;
- }
- //选择LSE作为RTC的时钟源
- RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
- //使能RTC时钟
- RCC_RTCCLKCmd(ENABLE);
-
- //等待RTC最后一次操作完成
- RTC_WaitForLastTask();
-
- //等待寄存器与APB1时钟同步,因为RTC时钟是低速的,内环时钟是高速的,所以要同步
- RTC_WaitForSynchro();
- //等待RTC最后一次操作完成
- RTC_WaitForLastTask();
- //使能RTC的秒中断
- RTC_ITConfig(RTC_IT_SEC,ENABLE);
- //等待RTC最后一次操作完成
- RTC_WaitForLastTask();
- //设置预分频寄存器,时间周期是1秒 = 32.768k/32768+1--------(RTCCLK/RTC_PR)
- RTC_SetPrescaler(32768-1);
- //等待RTC最后一次操作完成
- RTC_WaitForLastTask();
- }
-
- void RTC_NVIC_Config(void){
- NVIC_InitTypeDef NVIC_InitStructure;
- //设置优先级组为1,抢占1位(0-1),从3位(0-7)
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
- //设置优先级通道
- NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
-
- void clockinit_RTC(){
- RTC_NVIC_Config();
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE);
- PWR_BackupAccessCmd(ENABLE);
- //识别是不是后背备份区域
- if(BKP_ReadBackupRegister(BKP_DR1)!=0XA5A5){
- //通过判断后背寄存器的值来判断是否是系统第一次上电
- printf("RTC没有被配置过");
- //是的话就进行RTC配置,设置初试时间
- rtc_init();
- printf("RTC正在配置");
- Time_Adjust();
- BKP_WriteBackupRegister(BKP_DR1,0xA5A5);
-
- }else{
- //看是否是系统掉电
- if(RCC_GetFlagStatus(RCC_FLAG_PORRST)!=RESET){
- printf("Power On Resetm occurred...");
- }
- //看是否是复位引脚引起的复位
- else if(RCC_GetFlagStatus(RCC_FLAG_PINRST)!=RESET){
- printf("External Reset occured...");
- }
- printf("No need to configure RTC...");
- RTC_WaitForSynchro();
- RTC_ITConfig(RTC_IT_SEC,ENABLE);
- RTC_WaitForLastTask();
- }
- RCC_ClearFlag();
- Time_Show();
- }
- //RTC初始化(配置函数,Set引参,Get获得时间)
-
- //设置时间函数
- void Time_Adjust(void){
- //等待RTC最后一次操作完成
- RTC_WaitForLastTask();
- //将秒数存取寄存器
- RTC_SetCounter(rtc_timeSet(2023,9,22,14,30,0));
- //等待RTC最后一次操作完成
- RTC_WaitForLastTask();
- }
- //用设置的时间去获得秒,我们使用秒中断
- uint32_t rtc_timeSet(uint16_t syear,uint8_t smonth,uint8_t sdays,uint8_t shour,uint8_t sminute,uint8_t ssecond){
-
- uint16_t old_year=1970;
- //uint32_t all_second=0;
- uint16_t days=0;
- uint8_t month=0;
- uint32_t second=0;
- //时间大于一年的计算
- while(old_year<syear){
- if(IS_temp_year(old_year)){
- days += 366;
- }else{
- days +=365;
- }
- old_year++;
- }
- //时间不足一年的计算
- for(;month<smonth;month++){
- if(!IS_temp_year(syear)){
- days += month_table[month];
- }else{
- if(month==1){
- days = days + month_table[month]+1;
- }else{
- days += month_table[month];
- }
- }
- }
- days += sdays;
- //得到年月日的秒数,一天有86400秒
- second = days * 86400;
- //不足一天的秒数--时
- second +=shour * 3600;
- //不足一天的秒数--分
- second += sminute * 60;
- //不足一天的秒数--秒
- second += ssecond;
- return second;
-
- }
- //用得到的秒数去计算现在的日期
- uint8_t rtc_timeGet(){
- uint32_t getsecond = RTC_GetCounter();
- uint16_t gyear = 1970;
- uint16_t gdays = 0;
- uint8_t gmonth = 0;
- uint8_t ghour = 0;
- uint8_t gminute = 0;
- uint16_t gsecond = 0;
-
- gdays = getsecond / 86400;
- while(gdays < 365){
- if(IS_temp_year(gyear)){
- gdays -= 366;
- }else{
- gdays -= 365;
- }
- gyear++ ;
- }
-
- while(gdays >= 28){
- if(IS_temp_year(gyear)){
- gdays = gdays - month_table[gmonth]-1;
- }else{
- gdays -= month_table[gmonth];
- }
- gmonth++ ;
- }
- calendar.year = gyear;
- calendar.month = gmonth;
- calendar.day = (uint8_t)gdays;
- //不足一天的秒数
- gsecond = getsecond % 86400 ;
- ghour = gsecond / 3600;
- gminute = (gsecond % 3600) / 60;
- gsecond = (gsecond % 3600) %60 ;
- calendar.hour = ghour;
- calendar.minute = gminute;
- calendar.second = (uint8_t)gsecond;
- return 0;
-
- }
- //判断现在的年份是不是闰年
- int IS_temp_year(uint16_t year){
- if(year%4==0){
- if(year%100!=0){
- return 1;
- }else{
- return 0;
- }
-
- }else{
- if(year%400==0){
- return 1;
- }else{
- return 0;
- }
- }
- }
- void Time_Show(void){
- printf("\n\r");
- while(1){
- //秒标志位
- if(TimeDisplay == 1){
- //Time_Display(RTC_GetCounter());
- Time_Display2();
- TimeDisplay = 0;
- }
-
- }
-
- }
-
- void Time_Display(uint32_t time){
- uint32_t hh=0,mm=0,ss=0;
- /*当时间走到23:59:59,RTC复位,计数值清零*/
- if(RTC_GetCounter() == 0x0001517f){ //(23*3600=82800)+(59*60=3540)+(59)=86399变十六进制是0x0001517f
- RTC_SetCounter(0x0);
- RTC_WaitForLastTask();
- }
- hh=time/3600;
- mm=(time%3600)/60;
- ss=(time%3600)%60;
- }
- void RTC_IRQHandler(void){
- //秒中断是否开启
- if(RTC_GetITStatus(RTC_IT_SEC)==SET){
- /*清除秒中断标识位*/
- RTC_ClearITPendingBit(RTC_IT_SEC);
- /*置1s标志位*/
- TimeDisplay=1;
- RTC_WaitForLastTask();
- // //显示时间
- // Time_Display2();
-
- }
- RTC_WaitForLastTask();
-
- }
- void Time_Display2(void){
- rtc_timeGet();
- printf("Now time is: %d-%d-%d %d:%d:%d\r\n", calendar.year, calendar.month, calendar.day, calendar.hour, calendar.minute, calendar.second);
- }