STM32实时时钟RTC按键修改时间_第1页
STM32实时时钟RTC按键修改时间_第2页
STM32实时时钟RTC按键修改时间_第3页
STM32实时时钟RTC按键修改时间_第4页
STM32实时时钟RTC按键修改时间_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、User文件夹下main.c#include "sys.h"#include "usart.h"#include "delay.h"#include "led.h" #include "key.h"#include "exti.h"#include "wdg.h"#include "timerx.h"#include "adc.h"#include "rtc.h"#include "12

2、864.h" #include "ov7670.h"#include "usmart.h" #include "enc28j60.h"#include "uip.h"#include "uip_arp.h"#include "tapdev.h"#include "timer.h" #include "math.h" #include "string.h" #include "syn.h"

3、/Mini STM32开发板扩展实验21/ENC28J60网络模块 实验/正点原子ALIENTEK/技术论坛:/广州市星翼电子科技有限公司 void uip_polling(void);void Display_Time(void);void received_date(u8 *str);u16 Process_date(u8 q,u8 b,u8 s,u8 g);#define BUF (struct uip_eth_hdr *)&uip_buf0) u8 t,Addres_1=10,Addres_2=1,Addres_3=168,Addres_4=192;int main(void)

4、 Stm32_Clock_Init(9);/系统时钟设置/usart_init(72,9600); /串口初始化为9600USART3_Init(36,9600);USART2_Init(36,9600);delay_init(72); /延时初始化 LED_Init(); /初始化与LED连接的硬件接口LCD12864_InitPort(); /初始化LCDLCD12864_Init();/KEY_Init();/初始化按键RTC_Init();/初始化RTC /usmart_dev.init(72);/初始化USMART EXTIX_Init(); while(tapdev_init()/

5、初始化ENC28J60错误 LCD_ShowString(3,0,"28J60 InitError!"); delay_ms(200); LCD12864_Clr();/清除之前显示;uip_init();/uIP初始化 uip_ipaddr(ipaddr, 192,168,1,10);/设置本地设置IP地址uip_sethostaddr(ipaddr); uip_ipaddr(ipaddr, 192,168,1,1); /设置网关IP地址(其实就是你路由器的IP地址)uip_setdraddr(ipaddr); uip_ipaddr(ipaddr, 255,255,254

6、,0);/设置网络掩码uip_setnetmask(ipaddr);uip_listen(HTONS(1200);/监听1200端口,用于TCP Serveruip_listen(HTONS(80);/监听80端口,用于Web Server tcp_client_reconnect(); /尝试连接到TCP Server端,用于TCP Clientwhile (1) Display_Time(); uip_polling();/处理uip事件,必须插入到用户程序的循环体中 /key=KEY_Scan();if(tcp_client_tsta!=tcp_client_sta)/TCP Clien

7、t状态改变 if(tcp_client_sta&(1<<7) LCD_ShowString(3,0,"接收数据:"); disp_IP(); else LCD_ShowString(3,0,"已断开! "); disp_IP(); if(tcp_client_sta&(1<<6)/收到新数据 /LCD12864_Clr();/清除之前显示 received_date(tcp_client_databuf);tcp_client_sta&=(1<<6);tcp_client_tsta=tcp_cl

8、ient_sta;delay_ms(1); usart3_Receive_Process(); /uip事件处理函数/必须将该函数插入用户主循环,循环调用.void uip_polling(void)u8 i;static struct timer periodic_timer, arp_timer;static u8 timer_ok=0; if(timer_ok=0)/仅初始化一次timer_ok = 1;timer_set(&periodic_timer,CLOCK_SECOND/2); /创建1个0.5秒的定时器 timer_set(&arp_timer,CLOCK_S

9、ECOND*10); /创建1个10秒的定时器 uip_len=tapdev_read();/从网络设备读取一个IP包,得到数据长度.uip_len在uip.c中定义if(uip_len>0) /有数据 /处理IP数据包(只有校验通过的IP包才会被接收) if(BUF->type = htons(UIP_ETHTYPE_IP)/是否是IP包? uip_arp_ipin();/去除以太网头结构,更新ARP表uip_input(); /IP包处理/当上面的函数执行后,如果需要发送数据,则全局变量 uip_len > 0/需要发送的数据在uip_buf, 长度是uip_len (这

10、是2个全局变量) if(uip_len>0)/需要回应数据uip_arp_out();/加以太网头结构,在主动连接时可能要构造ARP请求tapdev_send();/发送数据到以太网else if (BUF->type=htons(UIP_ETHTYPE_ARP)/处理arp报文,是否是ARP请求包?uip_arp_arpin(); /当上面的函数执行后,如果需要发送数据,则全局变量uip_len>0/需要发送的数据在uip_buf, 长度是uip_len(这是2个全局变量) if(uip_len>0)tapdev_send();/需要发送数据,则通过tapdev_se

11、nd发送 else if(timer_expired(&periodic_timer)/0.5秒定时器超时timer_reset(&periodic_timer);/复位0.5秒定时器 /轮流处理每个TCP连接, UIP_CONNS缺省是40个 for(i=0;i<UIP_CONNS;i+)uip_periodic(i);/处理TCP通信事件 /当上面的函数执行后,如果需要发送数据,则全局变量uip_len>0/需要发送的数据在uip_buf, 长度是uip_len (这是2个全局变量) if(uip_len>0)uip_arp_out();/加以太网头结构,

12、在主动连接时可能要构造ARP请求tapdev_send();/发送数据到以太网#if UIP_UDP/UIP_UDP /轮流处理每个UDP连接, UIP_UDP_CONNS缺省是10个for(i=0;i<UIP_UDP_CONNS;i+)uip_udp_periodic(i);/处理UDP通信事件 /当上面的函数执行后,如果需要发送数据,则全局变量uip_len>0/需要发送的数据在uip_buf, 长度是uip_len (这是2个全局变量)if(uip_len > 0)uip_arp_out();/加以太网头结构,在主动连接时可能要构造ARP请求tapdev_send();

13、/发送数据到以太网#endif /每隔10秒调用1次ARP定时器函数 用于定期ARP处理,ARP表10秒更新一次,旧的条目会被抛弃if(timer_expired(&arp_timer)timer_reset(&arp_timer);uip_arp_timer();void Display_Time(void) if(t!=timer.sec)t=timer.sec; LCD_ShowString(1,5,"星期"); LCD_ShowString(0,3,"20"); LCD_Shownum(0,4,(timer.w_year%100)

14、; LCD12684_Wdat(0x2d); LCD_Shownum1(timer.w_month); LCD12684_Wdat(0x2d); LCD_Shownum1(timer.w_date); switch(timer.week) case 0:LCD_ShowString(1,7,"日");break;case 1:LCD_ShowString(1,7,"一");break;case 2:LCD_ShowString(1,7,"二");break;case 3:LCD_ShowString(1,7,"三"

15、);break;case 4:LCD_ShowString(1,7,"四");break;case 5:LCD_ShowString(1,7,"五");break;case 6:LCD_ShowString(1,7,"六");break; LCD_Shownum(1,0,timer.hour); LCD12684_Wdat(0x3a); LCD_Shownum1(timer.min); LCD12684_Wdat(0x3a); LCD_Shownum1(timer.sec);void received_date(u8 *str) u8

16、 len;len=(u8)strlen(str);switch(len)case 13: Addres_4= (u8)Process_date(0,(str0-0x30),str1,str2); Addres_3= (u8)Process_date(0,(str4-0x30),str5,str6); Addres_2=(u8)Process_date(0,0,str8,str9); Addres_1=(u8)Process_date(0,0,str11,str12); uip_ipaddr(ipaddr, Addres_4,Addres_3,Addres_2,Addres_1);/设置本地设置

17、IP地址 uip_sethostaddr(ipaddr); tcp_client_reconnect(); disp_IP(); break;case 19:RTC->CRH&=(0X01); while(!(RTC->CRL&(1<<5); /等待RTC寄存器操作完成 timer.w_year=(s16)Process_date(str0-0x30,str1-0x30,str2,str3); timer.w_month=(s8)Process_date(0,0,str5,str6); timer.w_date=(s8)Process_date(0,0,

18、str8,str9); timer.hour=(s8)Process_date(0,0,str11,str12); timer.min=(s8)Process_date(0,0,str14,str15); timer.sec=(s8)Process_date(0,0,str17,str18); RTC_Set(timer.w_year,timer.w_month,timer.w_date,timer.hour,timer.min,timer.sec); /设置时间 RTC->CRH|=0X01; while(!(RTC->CRL&(1<<5); /等待RTC寄存

19、器操作完成 break; case 6:case 7:case 8:case 9:case 10 : case 11 : LCD_ShowString(3,5,str); Speech(str);break;default : break; u16 Process_date(u8 q,u8 b,u8 s,u8 g) u16 temp; temp=q*1000+b*100+(s-0x30)*10+(g-0x30); return temp ;HARDWARE文件夹下rtc。C文件#include "sys.h"#include "rtc.h" #inclu

20、de "delay.h"#include "usart.h" / /本程序只供学习使用,未经作者许可,不得用于其它任何用途/Mini STM32开发板/RTC实时时钟 驱动代码 /正点原子ALIENTEK/技术论坛:/修改日期:2010/12/30 /版本:V1.1/版权所有,盗版必究。/Copyright(C) 正点原子 2009-2019/All rights reserved/*/V1.1修改说明/修改了RTC_Init函数分频设置无效的bug/修改了RTC_Get函数的一个bug/ /Mini STM32开发板/RTC实时时钟 驱动代码 /正点原

21、子ALIENTEK/2010/6/6 tm timer;/时钟结构体 /实时时钟配置/初始化RTC时钟,同时检测时钟是否工作正常/BKP->DR1用于保存是否第一次配置的设置/返回0:正常/其他:错误代码u8 RTC_Init(void)/检查是不是第一次配置时钟u8 temp=0;if(BKP->DR1!=0X5050)/第一次配置 RCC->APB1ENR|=1<<28; /使能电源时钟 RCC->APB1ENR|=1<<27; /使能备份时钟 PWR->CR|=1<<8; /取消备份区写保护RCC->BDCR|=1&

22、lt;<16; /备份区域软复位 RCC->BDCR&=(1<<16); /备份区域软复位结束 RCC->BDCR|=1<<0; /开启外部低速振荡器 while(!(RCC->BDCR&0X02)&&temp<250)/等待外部时钟就绪 temp+;delay_ms(10);if(temp>=250)return 1;/初始化时钟失败,晶振有问题 RCC->BDCR|=1<<8; /LSI作为RTC时钟 RCC->BDCR|=1<<15;/RTC时钟使能 while

23、(!(RTC->CRL&(1<<5);/等待RTC寄存器操作完成 while(!(RTC->CRL&(1<<3);/等待RTC寄存器同步 RTC->CRH|=0X01; /允许秒中断 while(!(RTC->CRL&(1<<5);/等待RTC寄存器操作完成 RTC->CRL|=1<<4; /允许配置 RTC->PRLH=0X0000;RTC->PRLL=32767; /时钟周期设置(有待观察,看是否跑慢了?)理论值:32767 Auto_Time_Set();/RTC_Set(2

24、009,12,2,10,0,55); /设置时间 RTC->CRL&=(1<<4); /配置更新while(!(RTC->CRL&(1<<5); /等待RTC寄存器操作完成 BKP->DR1=0X5050;/BKP_Write(1,0X5050);/在寄存器1标记已经开启了 /printf("FIRST TIMEn");else/系统继续计时 while(!(RTC->CRL&(1<<3);/等待RTC寄存器同步 RTC->CRH|=0x01; /允许秒中断 while(!(RTC-&

25、gt;CRL&(1<<5);/等待RTC寄存器操作完成/printf("OKn"); MY_NVIC_Init(0,0,RTC_IRQChannel,2);/RTC,G2,P2,S2.优先级最低 RTC_Get();/更新时间 return 0; /ok/RTC中断服务函数 /const u8* Week27=/"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday",&qu

26、ot;Saturday",/"日","一","二","三","四","五","六"/; /RTC时钟中断/每秒触发一次 void RTC_IRQHandler(void) if(RTC->CRL&0x0001)/秒钟中断RTC_Get();/更新时间 /printf("CRL:%dn",RTC->CRL); if(RTC->CRL&0x0002)/闹钟中断/printf("Alarm

27、!n");RTC->CRL&=(0x0002);/清闹钟中断 /闹钟处理 RTC->CRL&=0X0FFA; /清除溢出,秒钟中断标志while(!(RTC->CRL&(1<<5);/等待RTC寄存器操作完成 /判断是否是闰年函数/月份 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(u

28、16 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日为基准/19702099年为合法年份/返回值:0,成功;其他:错误代码./月份数据表 u8 const table_week12=0,3,3,6,1,4,6,2,5,0,3,5; /月修正数据表 /平年的月份日期表const u8 mon_table12=31,28,31,30

29、,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<syear;t+)/把所有年份的秒钟相加if(Is_Leap_Year(t)seccount+=31622400;/闰年的秒钟数else seccount+=31536000; /平年的秒钟数smon-=1;for(t=0;t<smon;t+) /把前面月份的秒钟数相加

30、seccount+=(u32)mon_tablet*86400;/月份秒钟数相加if(Is_Leap_Year(syear)&&t=1)seccount+=86400;/闰年2月份增加一天的秒钟数 seccount+=(u32)(sday-1)*86400;/把前面日期的秒钟数相加 seccount+=(u32)hour*3600;/小时秒钟数 seccount+=(u32)min*60; /分钟秒钟数seccount+=sec;/最后的秒钟加上去 /设置时钟 RCC->APB1ENR|=1<<28; /使能电源时钟 RCC->APB1ENR|=1<

31、;<27; /使能备份时钟PWR->CR|=1<<8; /取消备份区写保护/上面三步是必须的!RTC->CRL|=1<<4; /允许配置 RTC->CNTL=seccount&0xffff;RTC->CNTH=seccount>>16;RTC->CRL&=(1<<4);/配置更新while(!(RTC->CRL&(1<<5);/等待RTC寄存器操作完成 return 0; /得到当前的时间/返回值:0,成功;其他:错误代码.u8 RTC_Get(void)static

32、u16 daycnt=0;u32 timecount=0; u32 temp=0;u16 temp1=0; timecount=RTC->CNTH;/得到计数器中的值(秒钟数)timecount<<=16;timecount+=RTC->CNTL; temp=timecount/86400; /得到天数(秒钟数对应的)if(daycnt!=temp)/超过一天了 daycnt=temp;temp1=1970;/从1970年开始while(temp>=365) if(Is_Leap_Year(temp1)/是闰年if(temp>=366)temp-=366;/

33、闰年的秒钟数else break; else temp-=365; /平年 temp1+; timer.w_year=temp1;/得到年份temp1=0;while(temp>=28)/超过了一个月if(Is_Leap_Year(timer.w_year)&&temp1=1)/当年是不是闰年/2月份if(temp>=29)temp-=29;/闰年的秒钟数else break; else if(temp>=mon_tabletemp1)temp-=mon_tabletemp1;/平年else break;temp1+; timer.w_month=temp1+

34、1;/得到月份timer.w_date=temp+1; /得到日期 temp=timecount%86400; /得到秒钟数 timer.hour=temp/3600; /小时timer.min=(temp%3600)/60; /分钟timer.sec=(temp%3600)%60; /秒钟timer.week=RTC_Get_Week(timer.w_year,timer.w_month,timer.w_date);/获取星期 return 0; /获得现在是星期几/功能描述:输入公历日期得到星期(只允许1901-2099年)/输入参数:公历年月日 /返回值:星期号 u8 RTC_Get_W

35、eek(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_weekmonth-1;if (yearL%4=0&&month<3)temp2-;return(temp2%7); /比较两个字符串指定长度的内容是否相等/参数:s1

36、,s2要比较的两个字符串;len,比较长度/返回值:1,相等;0,不相等u8 str_cmpx(u8*s1,u8*s2,u8 len)u8 i;for(i=0;i<len;i+)if(*s1+)!=*s2+)return 0;return 1; extern const u8 *COMPILED_DATE;/获得编译日期extern const u8 *COMPILED_TIME;/获得编译时间const u8 Month_Tab123="Jan","Feb","Mar","Apr","May&qu

37、ot;,"Jun","Jul","Aug","Sep","Oct","Nov","Dec" /自动设置时间为编译器时间 void Auto_Time_Set(void)u8 temp3;u8 i;u8 mon,date;u16 year;u8 sec,min,hour;for(i=0;i<3;i+)tempi=COMPILED_DATEi; for(i=0;i<12;i+)if(str_cmpx(u8*)Month_Tabi,temp,3)br

38、eak;mon=i+1;/得到月份if(COMPILED_DATE4=' ')date=COMPILED_DATE5-'0' else date=10*(COMPILED_DATE4-'0')+COMPILED_DATE5-'0' year=1000*(COMPILED_DATE7-'0')+100*(COMPILED_DATE8-'0')+10*(COMPILED_DATE9-'0')+COMPILED_DATE10-'0' hour=10*(COMPILED_TI

39、ME0-'0')+COMPILED_TIME1-'0' min=10*(COMPILED_TIME3-'0')+COMPILED_TIME4-'0' sec=10*(COMPILED_TIME6-'0')+COMPILED_TIME7-'0' RTC_Set(year,mon,date,hour,min,sec);/printf("%d-%d-%d %d:%d:%dn",year,mon,date,hour,min,sec);Hardware文件夹下 exit。C#include

40、 "exti.h"#include "led.h"#include "key.h"#include "delay.h"#include "usart.h"#include "12864.h"#include "rtc.h"/ /本程序只供学习使用,未经作者许可,不得用于其它任何用途/Mini STM32开发板/外部中断 驱动代码 /正点原子ALIENTEK/技术论坛:/修改日期:2010/12/01 /版本:V1.0/版权所有,盗版必究。/Copyrigh

41、t(C) 正点原子 2009-2019/All rights reserved / /外部中断0服务程序void EXTI0_IRQHandler(void) delay_ms(100);/消抖if(KEY2=1) /按键2 count+; if(count<7) while(!(RTC->CRL&(1<<3);/等待RTC寄存器同步 RTC->CRH&=(0X01); /允许秒中断 while(!(RTC->CRL&(1<<5);/等待RTC寄存器操作完成 switch(count) case 1 : LCD_ShowS

42、tring(2,4,"设置秒");break; case 2 : LCD_ShowString(2,4,"设置分");break; case 3 : LCD_ShowString(2,4,"设置时");break; case 4 : LCD_ShowString(2,4,"设置日");break; case 5 : LCD_ShowString(2,4,"设置月");break; case 6 : LCD_ShowString(2,4,"设置年");break; case 7

43、 : RTC_Set(timer.w_year,timer.w_month,timer.w_date,timer.hour,timer.min,timer.sec); while(!(RTC->CRL&(1<<3);/等待RTC寄存器同步 RTC->CRH|=0X01; /允许秒中断 while(!(RTC->CRL&(1<<5);/等待RTC寄存器操作完成 LCD_ShowString(2,4,"设置IP ");LCD_ShowString(3,0,">");disp_IP(); brea

44、k; case 8 : LCD_ShowString(3,0,">>");break; case 9 : LCD_ShowString(3,0,">>>");break; case 10 : LCD_ShowString(3,0,">>>>");break; case 11 : count=0;LCD_ShowString(3,0," ");LCD_ShowString(2,4," ");break; EXTI->PR=1<<

45、;0; /清除LINE0上的中断标志位 /外部中断1510服务程序void EXTI15_10_IRQHandler(void)delay_ms(100); /消抖 if(KEY0=0) /按键0 LED1=!LED1;switch(count) case 1 : timer.sec-;if(timer.sec=0)timer.sec=59;LCD_Shownum(1,4,timer.sec);LCD_ShowString(2,7,"-");break; case 2 : timer.min-;if(timer.min=0)timer.min=59;LCD_Shownum(

46、1,2,timer.min);LCD_ShowString(2,7,"-");break; case 3 : timer.hour-;if(timer.hour=0)timer.hour=12;LCD_Shownum(1,0,timer.hour);LCD_ShowString(2,7,"-");break; case 4 : timer.w_date-;if(timer.w_date=0)timer.w_date=31;LCD_Shownum(0,4,timer.w_date);LCD_ShowString(2,7,"-");bre

47、ak; case 5 : timer.w_month-;if(timer.w_month=0)timer.w_month=12;LCD_Shownum(0,2,timer.w_month);LCD_ShowString(2,7,"-");break; case 6 : timer.w_year-;if(timer.w_year=0)timer.w_year=2099;LCD_Shownum(0,0,(timer.w_year%100);LCD_ShowString(2,7,"-");break; case 7 : Addres_1-;if(Addres_

48、1=0) Addres_1=99;disp_IP();break; case 8 : Addres_2-;if(Addres_2=0) Addres_2=9;disp_IP();break; case 9 : Addres_3-;if(Addres_3=0)Addres_3=200;disp_IP();break; case 10 : Addres_4-;if(Addres_4=0)Addres_4=200;disp_IP();break; else if(KEY1=0)/按键1LED0=!LED0;switch(count)case 1 : timer.sec+;if(timer.sec=6

49、0)timer.sec=0;LCD_Shownum(1,4,timer.sec);LCD_ShowString(2,7,"+");break;case 2 : timer.min+;if(timer.min=60)timer.min=0;LCD_Shownum(1,2,timer.min);LCD_ShowString(2,7,"+");break;case 3 : timer.hour+;if(timer.hour=12)timer.hour=0;LCD_Shownum(1,0,timer.hour);LCD_ShowString(2,7,"+");break;case 4 : timer.w_date+;if(timer.w_date=32)timer.w_date=0;LCD_Shownum(0,4,timer.w_date);LCD_ShowString(2,7,"+");break;case 5 :

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论