ARM 【RTC时钟实验】
 
//main.c #include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "lcd.h" #include "usart.h" #include "usmart.h" #include "rtc.h" /************************************************ ALIENTEK 战舰STM32F103开发板实验15 RTC实时时钟实验 技术支持:www.openedv.com 淘宝店铺:http://eboard.taobao.com 关注微信公众平台微信号:"正点原子",免费获取STM32资料。 广州市星翼电子科技有限公司 作者:正点原子 @ALIENTEK ************************************************/ int main(void) { u8 t=0; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 LED_Init(); //LED端口初始化 LCD_Init(); usmart_dev.init(SystemCoreClock/1000000); //初始化USMART RTC_Init(); //RTC初始化 POINT_COLOR=RED;//设置字体为红色 LCD_ShowString(60,50,200,16,16,"WarShip STM32"); LCD_ShowString(60,70,200,16,16,"RTC TEST"); LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(60,110,200,16,16,"2015/1/14"); //显示时间 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); }; }
 
1 #include "sys.h" 2 #include "delay.h" 3 #include "usart.h" 4 #include "rtc.h" 5 //Mini STM32开发板 6 //RTC实时时钟 驱动代码 7 //正点原子@ALIENTEK 8 //2010/6/6 9 10 _calendar_obj calendar;//时钟结构体 11 12 static void RTC_NVIC_Config(void) 13 { 14 NVIC_InitTypeDef NVIC_InitStructure; 15 NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //RTC全局中断 16 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级1位,从优先级3位 17 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //先占优先级0位,从优先级4位 18 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能该通道中断 19 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 20 } 21 22 //实时时钟配置 23 //初始化RTC时钟,同时检测时钟是否工作正常 24 //BKP->DR1用于保存是否第一次配置的设置 25 //返回0:正常 26 //其他:错误代码 27 28 u8 RTC_Init(void) 29 { 30 //检查是不是第一次配置时钟 31 u8 temp=0; 32 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外设时钟 33 PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问 34 if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050) //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎 35 { 36 BKP_DeInit(); //复位备份区域 37 RCC_LSEConfig(RCC_LSE_ON); //设置外部低速晶振(LSE),使用外设低速晶振 38 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET&&temp<250) //检查指定的RCC标志位设置与否,等待低速晶振就绪 39 { 40 temp++; 41 delay_ms(10); 42 } 43 if(temp>=250)return 1;//初始化时钟失败,晶振有问题 44 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟 45 RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 46 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 47 RTC_WaitForSynchro(); //等待RTC寄存器同步 48 RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断 49 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 50 RTC_EnterConfigMode();/// 允许配置 51 RTC_SetPrescaler(32767); //设置RTC预分频的值 52 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 53 RTC_Set(2015,1,14,17,42,55); //设置时间 54 RTC_ExitConfigMode(); //退出配置模式 55 BKP_WriteBackupRegister(BKP_DR1, 0X5050); //向指定的后备寄存器中写入用户程序数据 56 } 57 else//系统继续计时 58 { 59 60 RTC_WaitForSynchro(); //等待最近一次对RTC寄存器的写操作完成 61 RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断 62 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 63 } 64 RTC_NVIC_Config();//RCT中断分组设置 65 RTC_Get();//更新时间 66 return 0; //ok 67 68 } 69 //RTC时钟中断 70 //每秒触发一次 71 //extern u16 tcnt; 72 void RTC_IRQHandler(void) 73 { 74 if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断 75 { 76 RTC_Get();//更新时间 77 } 78 if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断 79 { 80 RTC_ClearITPendingBit(RTC_IT_ALR); //清闹钟中断 81 RTC_Get(); //更新时间 82 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);//输出闹铃时间 83 84 } 85 RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW); //清闹钟中断 86 RTC_WaitForLastTask(); 87 } 88 //判断是否是闰年函数 89 //月份 1 2 3 4 5 6 7 8 9 10 11 12 90 //闰年 31 29 31 30 31 30 31 31 30 31 30 31 91 //非闰年 31 28 31 30 31 30 31 31 30 31 30 31 92 //输入:年份 93 //输出:该年份是不是闰年.1,是.0,不是 94 u8 Is_Leap_Year(u16 year) 95 { 96 if(year%4==0) //必须能被4整除 97 { 98 if(year%100==0) 99 { 100 if(year%400==0)return 1;//如果以00结尾,还要能被400整除 101 else return 0; 102 }else return 1; 103 }else return 0; 104 } 105 //设置时钟 106 //把输入的时钟转换为秒钟 107 //以1970年1月1日为基准 108 //1970~2099年为合法年份 109 //返回值:0,成功;其他:错误代码. 110 //月份数据表 111 u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表 112 //平年的月份日期表 113 const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31}; 114 u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec) 115 { 116 u16 t; 117 u32 seccount=0; 118 if(syear<1970||syear>2099)return 1; 119 for(t=1970;t<syear;t++) //把所有年份的秒钟相加 120 { 121 if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数 122 else seccount+=31536000; //平年的秒钟数 123 } 124 smon-=1; 125 for(t=0;t<smon;t++) //把前面月份的秒钟数相加 126 { 127 seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加 128 if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数 129 } 130 seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加 131 seccount+=(u32)hour*3600;//小时秒钟数 132 seccount+=(u32)min*60; //分钟秒钟数 133 seccount+=sec;//最后的秒钟加上去 134 135 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外设时钟 136 PWR_BackupAccessCmd(ENABLE); //使能RTC和后备寄存器访问 137 RTC_SetCounter(seccount); //设置RTC计数器的值 138 139 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 140 return 0; 141 } 142 143 //初始化闹钟 144 //以1970年1月1日为基准 145 //1970~2099年为合法年份 146 //syear,smon,sday,hour,min,sec:闹钟的年月日时分秒 147 //返回值:0,成功;其他:错误代码. 148 u8 RTC_Alarm_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec) 149 { 150 u16 t; 151 u32 seccount=0; 152 if(syear<1970||syear>2099)return 1; 153 for(t=1970;t<syear;t++) //把所有年份的秒钟相加 154 { 155 if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数 156 else seccount+=31536000; //平年的秒钟数 157 } 158 smon-=1; 159 for(t=0;t<smon;t++) //把前面月份的秒钟数相加 160 { 161 seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加 162 if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数 163 } 164 seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加 165 seccount+=(u32)hour*3600;//小时秒钟数 166 seccount+=(u32)min*60; //分钟秒钟数 167 seccount+=sec;//最后的秒钟加上去 168 //设置时钟 169 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外设时钟 170 PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问 171 //上面三步是必须的! 172 173 RTC_SetAlarm(seccount); 174 175 RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 176 177 return 0; 178 } 179 180 181 //得到当前的时间 182 //返回值:0,成功;其他:错误代码. 183 u8 RTC_Get(void) 184 { 185 static u16 daycnt=0; 186 u32 timecount=0; 187 u32 temp=0; 188 u16 temp1=0; 189 timecount=RTC_GetCounter(); 190 temp=timecount/86400; //得到天数(秒钟数对应的) 191 if(daycnt!=temp)//超过一天了 192 { 193 daycnt=temp; 194 temp1=1970; //从1970年开始 195 while(temp>=365) 196 { 197 if(Is_Leap_Year(temp1))//是闰年 198 { 199 if(temp>=366)temp-=366;//闰年的秒钟数 200 else {temp1++;break;} 201 } 202 else temp-=365; //平年 203 temp1++; 204 } 205 calendar.w_year=temp1;//得到年份 206 temp1=0; 207 while(temp>=28)//超过了一个月 208 { 209 if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份 210 { 211 if(temp>=29)temp-=29;//闰年的秒钟数 212 else break; 213 } 214 else 215 { 216 if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年 217 else break; 218 } 219 temp1++; 220 } 221 calendar.w_month=temp1+1; //得到月份 222 calendar.w_date=temp+1; //得到日期 223 } 224 temp=timecount%86400; //得到秒钟数 225 calendar.hour=temp/3600; //小时 226 calendar.min=(temp%3600)/60; //分钟 227 calendar.sec=(temp%3600)%60; //秒钟 228 calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期 229 return 0; 230 } 231 //获得现在是星期几 232 //功能描述:输入公历日期得到星期(只允许1901-2099年) 233 //输入参数:公历年月日 234 //返回值:星期号 235 u8 RTC_Get_Week(u16 year,u8 month,u8 day) 236 { 237 u16 temp2; 238 u8 yearH,yearL; 239 240 yearH=year/100; yearL=year%100; 241 // 如果为21世纪,年份数加100 242 if (yearH>19)yearL+=100; 243 // 所过闰年数只算1900年之后的 244 temp2=yearL+yearL/4; 245 temp2=temp2%7; 246 temp2=temp2+day+table_week[month-1]; 247 if (yearL%4==0&&month<3)temp2--; 248 return(temp2%7); 249 }
 
1 #ifndef __RTC_H 2 #define __RTC_H 3 //Mini STM32开发板 4 //RTC实时时钟 驱动代码 5 //正点原子@ALIENTEK 6 //2010/6/6 7 8 //时间结构体 9 typedef struct 10 { 11 vu8 hour; 12 vu8 min; 13 vu8 sec; 14 //公历日月年周 15 vu16 w_year; 16 vu8 w_month; 17 vu8 w_date; 18 vu8 week; 19 }_calendar_obj; 20 extern _calendar_obj calendar; //日历结构体 21 22 extern u8 const mon_table[12]; //月份日期数据表 23 void Disp_Time(u8 x,u8 y,u8 size);//在制定位置开始显示时间 24 void Disp_Week(u8 x,u8 y,u8 size,u8 lang);//在指定位置显示星期 25 u8 RTC_Init(void); //初始化RTC,返回0,失败;1,成功; 26 u8 Is_Leap_Year(u16 year);//平年,闰年判断 27 u8 RTC_Alarm_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec); 28 u8 RTC_Get(void); //更新时间 29 u8 RTC_Get_Week(u16 year,u8 month,u8 day); 30 u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec);//设置时间 31 #endif
 
1 #include "stm32f10x.h" 2 #include "key.h" 3 #include "sys.h" 4 #include "delay.h" 5 ////////////////////////////////////////////////////////////////////////////////// 6 //本程序只供学习使用,未经作者许可,不得用于其它任何用途 7 //ALIENTEK战舰STM32开发板 8 //按键驱动代码 9 //正点原子@ALIENTEK 10 //技术论坛:www.openedv.com 11 //修改日期:2012/9/3 12 //版本:V1.0 13 //版权所有,盗版必究。 14 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 15 //All rights reserved 16 ////////////////////////////////////////////////////////////////////////////////// 17 18 //按键初始化函数 19 void KEY_Init(void) //IO初始化 20 { 21 GPIO_InitTypeDef GPIO_InitStructure; 22 23 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟 24 25 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//KEY0-KEY2 26 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入 27 GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4 28 29 //初始化 WK_UP-->GPIOA.0 下拉输入 30 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 31 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉 32 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0 33 34 } 35 //按键处理函数 36 //返回按键值 37 //mode:0,不支持连续按;1,支持连续按; 38 //0,没有任何按键按下 39 //1,KEY0按下 40 //2,KEY1按下 41 //3,KEY2按下 42 //4,KEY3按下 WK_UP 43 //注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!! 44 u8 KEY_Scan(u8 mode) 45 { 46 static u8 key_up=1;//按键按松开标志 47 if(mode)key_up=1; //支持连按 48 if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1)) 49 { 50 delay_ms(10);//去抖动 51 key_up=0; 52 if(KEY0==0)return KEY0_PRES; 53 else if(KEY1==0)return KEY1_PRES; 54 else if(KEY2==0)return KEY2_PRES; 55 else if(WK_UP==1)return WKUP_PRES; 56 }else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1; 57 return 0;// 无按键按下 58 }
    M54

 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号