logo资料库

STM32-实时时钟和闹钟程序.pdf

第1页 / 共8页
第2页 / 共8页
第3页 / 共8页
第4页 / 共8页
第5页 / 共8页
第6页 / 共8页
第7页 / 共8页
第8页 / 共8页
资料共8页,全文预览结束
#include "led.h" #include "delay.h" #include "sys.h" #include "lcd.h" #include "usart.h" #include "rtc.h" int main(void) { u8 t=0; delay_init(); NVIC_Configuration(); 位抢占优先级,2 位响应优先级 uart_init(9600); LED_Init(); LCD_Init(); BEEP_Init(); //延时函数初始化 //设置 NVIC 中断分组 2:2 //串口初始化为 9600 //LED 端口初始化 //初始化蜂鸣器端口 //RTC 初始化 //设置字体为红色 //设置字体为蓝色 RTC_Init(); POINT_COLOR=GREEN; LCD_ShowString(70,50,200,16,16,"^_^ andy ^_^"); POINT_COLOR=BLUE; LCD_ShowString(60,130,200,16,16," - - "); LCD_ShowString(60,162,200,16,16," : : "); while(1) { if(t!=calendar.sec) { t=calendar.sec; LCD_ShowNum(60,130,calendar.w_year,4,16); LCD_ShowNum(100,130,calendar.w_month,2,16); LCD_ShowNum(124,130,calendar.w_date,2,16); switch(calendar.week) { case 0: LCD_ShowString(60,148,200,16,16,"Sunday "); break; case 1: LCD_ShowString(60,148,200,16,16,"Monday "); break; case 2: LCD_ShowString(60,148,200,16,16,"Tuesday ");
break; case 3: LCD_ShowString(60,148,200,16,16,"Wednesday"); break; case 4: LCD_ShowString(60,148,200,16,16,"Thursday "); break; case 5: LCD_ShowString(60,148,200,16,16,"Friday "); break; case 6: LCD_ShowString(60,148,200,16,16,"Saturday "); break; } LCD_ShowNum(60,162,calendar.hour,2,16); LCD_ShowNum(84,162,calendar.min,2,16); LCD_ShowNum(108,162,calendar.sec,2,16); LED0=!LED0; } delay_ms(10); } } #include "sys.h" #include "delay.h" #include "usart.h" #include "rtc.h" _calendar_obj calendar;//时钟结构体 static void RTC_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 1 位,从优先 //RTC 全局中断 级 3 位 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //先占优先级 0 位,从优先级 4 位 //使能该通道中断 //根据 NVIC_InitStruct 中指定的参数初始化外 设 NVIC 寄存器 } u8 RTC_Init(void) {
//检查是不是第一次配置时钟 u8 temp=0; u32 flag=0; if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050) 数据:读出了与写入的指定数据不相乎 { //从指定的后备寄存器中读出 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能 PWR 和 BKP 外设时钟 PWR_BackupAccessCmd(ENABLE); BKP_DeInit();//复位备份区域 RCC_LSEConfig(RCC_LSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //使能后备寄存器访问 //设置外部低速晶振(LSE),使用外设低速晶振 // 检 查 指 定 的 RCC 标志位设置与否,等待低速晶振就绪 { temp++; delay_ms(10); } if(temp>=250)return 1; RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //初始化时钟失败,晶振有问题 //设置 RTC 时钟(RTCCLK), 选择 LSE 作为 RTC 时钟 RCC_RTCCLKCmd(ENABLE); RTC_WaitForLastTask(); 的写操作完成 RTC_WaitForSynchro(); RTC_ITConfig(RTC_IT_SEC, ENABLE); RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); 的写操作完成 RTC_EnterConfigMode(); RTC_SetPrescaler(32767); RTC_WaitForLastTask(); 的写操作完成 //使能 RTC 时钟 //等待最近一次对 RTC 寄存器 //等待 RTC 寄存器同步 //使能 RTC 秒中断 //等待最近一次对 RTC 寄存器 /// 允许配置 //设置 RTC 预分频的值 //等待最近一次对 RTC 寄存器 RTC_Set(2014,12,2,10,0,55); RTC_ExitConfigMode(); flag=RTC_GetCounter(); RTC_WaitForLastTask(); RTC_SetAlarm(flag+1); BKP_WriteBackupRegister(BKP_DR1, 0X5050); //设置时间 //退出配置模式 //每秒钟闹一次 //向指定的后备寄存器中写入 用户程序数据 } else { //系统继续计时 RTC_WaitForSynchro(); //等待最近一次对 RTC 寄存器的写 操作完成
RTC_ITConfig(RTC_IT_SEC, ENABLE); RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); //使能 RTC 秒中断 //等待最近一次对 RTC 寄存器 的写操作完成 } RTC_NVIC_Config(); RTC_Get(); return 0; } void RTC_IRQHandler(void) { //RCT 中断分组设置 //更新时间 //ok u32 flag=0; if (RTC_GetITStatus(RTC_IT_SEC) != RESET) { RTC_Get(); } if(RTC_GetITStatus(RTC_IT_ALR)!= RESET) { RTC_ClearITPendingBit(RTC_IT_ALR); LED1=!LED1; flag=RTC_GetCounter(); RTC_WaitForLastTask(); RTC_SetAlarm(flag+1); //秒钟中断 //更新时间 //闹钟中断 //清闹钟中断 //绿色的 led 灯闪烁 //每秒钟闹一次 } 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) { if(year%100==0) { //清闹钟中断 //必须能被 4 整除 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;t
u8 RTC_Get(void) { static u16 daycnt=0; u32 timecount=0; u32 temp=0; u16 temp1=0; timecount=RTC_GetCounter(); temp=timecount/86400; if(daycnt!=temp) { daycnt=temp; temp1=1970; while(temp>=365) { //得到天数(秒钟数对应的) //超过一天了 //从 1970 年开始 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);// 获 取 //秒钟 星期 return 0; } //获得现在是星期几 //功能描述:输入公历日期得到星期(只允许 1901-2099 年) //输入参数:公历年月日 //返回值:星期号 u8 RTC_Get_Week(u16 year,u8 month,u8 day) { u16 temp2; u8 yearH,yearL; yearL=year%100; yearH=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); } #include "led.h" void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能 PB,PE 端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIOB.5 GPIO_SetBits(GPIOB,GPIO_Pin_5); //LED0-->PB.5 端口配置 //推挽输出 //IO 口速度为 50MHz // 根 据 设 定 参 数 初 始 化 //PB.5 输出高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口 配置 , 推
挽输出 GPIO_Init(GPIOE, &GPIO_InitStructure); 50MHz GPIO_SetBits(GPIOE,GPIO_Pin_5); } // 推 挽 输 出 , IO 口 速 度 为 //PE.5 输出高
分享到:
收藏