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

提交評論