STM32實現(xiàn)萬年歷_第1頁
STM32實現(xiàn)萬年歷_第2頁
STM32實現(xiàn)萬年歷_第3頁
STM32實現(xiàn)萬年歷_第4頁
STM32實現(xiàn)萬年歷_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、STM32學(xué)習(xí)筆記一 竹天笑實現(xiàn)的功能:1、日歷功能。2、數(shù)字和模擬時鐘功能。圖1(為LCD截屏保存在SD卡中的圖像)最終界面如下,但還存在不少漏洞。1、沒有更改時間的設(shè)置;2、只有節(jié)氣顯示沒有節(jié)假日顯示3、背景不是用uCGUI畫的,是在PS中畫好然后存在SD卡中,然后顯示的BMP格式圖像。要點分析:1、STM32自帶了RTC時鐘計數(shù)器,從0開始計數(shù)到232。每一個計數(shù)代表秒計數(shù),每六十個計數(shù)代表分計數(shù),以此類推。24(小時)*60(分鐘)*60(秒鐘)=86400代表一天的計數(shù)時間。假設(shè)當(dāng)前計數(shù)為count,count/86400得到計數(shù)的天數(shù),根據(jù)這個得到年月日。Count%86400得到

2、時分秒。2、一些根據(jù)1中得到的年月日時分秒,進行計算的程序有:陽歷轉(zhuǎn)陰歷,閏年判斷,節(jié)氣判斷,星期幾計算,當(dāng)前月有多少天等等。3、模擬時鐘的繪制:時鐘指針運動算法、屏幕重繪方法、RTC消息、畫筆/畫刷等。指針運動算法和屏幕重繪方法是本程序主要難點所在。(以下參照百度文庫之模擬時鐘)不論何種指針,每次轉(zhuǎn)動均以/30弧度(一秒的角度)為基本單位,且都以表盤中心為轉(zhuǎn)動圓心。計算指針端點(x, y)的公式如下:x =圓心x坐標(biāo) + 指針長度 * cos (指針方向角)y =圓心y坐標(biāo) + 指針長度 * sin (指針方向角)注意,指針長度是指自圓心至指針一個端點的長度(是整個指針的一部分),由于指針可

3、能跨越圓心,因此一個指針需要計算兩個端點。由于屏幕的重繪1秒鐘一次,如果采用全屏刪除式重繪則閃爍十分明顯,顯示效果不佳。本程序采用非刪除式重繪,假定指針將要移動一格,則先采用背景色(這里是白色)重繪原來指針以刪除原來位置的指針,再采用指針的顏色在當(dāng)前位置繪制指針(如果指針沒有動,則直接繪制指針,此句在程序中被我刪除,具體原因,為數(shù)據(jù)截斷導(dǎo)致一些誤差)。另外,秒表為RTC一秒鐘定時計數(shù)。程序分析: uCGUI+uCOS,一共三個任務(wù):主處理任務(wù)、觸摸屏任務(wù)、秒更新任務(wù)。void App_UCGUI_TaskCreate (void) CPU_INT08U os_err;os_err = os_e

4、rr; Clock_SEM=OSSemCreate(1); /建立秒更新中斷的信號量 /硬件平臺初始化 BSP_Init(); /主處理任務(wù)- os_err = OSTaskCreateExt(AppTaskUserIF,(void *)0,(OS_STK *)&AppTaskUserIFStkAPP_TASK_USER_IF_STK_SIZE-1,APP_TASK_USER_IF_PRIO,APP_TASK_USER_IF_PRIO,(OS_STK *)&AppTaskUserIFStk0,APP_TASK_USER_IF_STK_SIZE,(void *)0,OS_TASK_OPT_STK

5、_CHK|OS_TASK_OPT_STK_CLR); /觸摸屏任務(wù)- os_err = OSTaskCreateExt(AppTaskKbd, (void *)0, (OS_STK *)&AppTaskKbdStkAPP_TASK_KBD_STK_SIZE-1, APP_TASK_KBD_PRIO, APP_TASK_KBD_PRIO, (OS_STK *)&AppTaskKbdStk0, APP_TASK_KBD_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); /秒更新任務(wù) os_err = OSTaskCreat

6、eExt(Clock_Updata,(void *)0,(OS_STK *)&Clock_Updata_StkClock_Updata_STK_SIZE-1,Clock_Updata_PRIO,Clock_Updata_PRIO,(OS_STK *)&Clock_Updata_Stk0,Clock_Updata_STK_SIZE,(void *)0,OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);萬年歷中的時間用的是STM32自帶的RTC實時時鐘。1、主處理任務(wù):界面背景初始化,并根據(jù)當(dāng)前時間,畫出圖1的數(shù)據(jù)。static void AppTaskUserIF

7、 (void *p_arg) (void)p_arg;INT8U err; /界面初始化 GUI_Init();/ucgui 初始化_ExecCalibration(); /* 觸摸屏校準(zhǔn) */GUI_SetBkColor(GUI_WHITE);/設(shè)置背景色GUI_SetColor(GUI_GRAY); /設(shè)置前景色 GUI_Clear();/清屏 Lcd_show_bmp(0, 0,/RTC.bmp);/顯示萬年歷背景GUI_SetFont(&GUI_FontHZ_SimSun_16);GUI_DispStringAt(一,15,47); /顯示星期一GUI_DispStringAt(二,4

8、4,47);/顯示星期二GUI_DispStringAt(三,73,47);/顯示星期三GUI_DispStringAt(四,102,47);/顯示星期四GUI_DispStringAt(五,131,47);/顯示星期五GUI_SetColor(GUI_RED);/用紅字顯示周末GUI_DispStringAt(六,160,47);/顯示星期六GUI_DispStringAt(日,189,47);/顯示星期日to_tm(RTC_GetCounter(), &s_time); /根據(jù)RTC時鐘得到萬年歷時間的初值,注意,這個值是根據(jù)用戶查詢?nèi)f年歷變化GUI_SetFont(&GUI_Font16

9、_1 );/設(shè)置英文字體GUI_DispDecAt(s_time.tm_year,4,13,4);/顯示萬年歷的年份GUI_SetFont(&GUI_FontHZ_SimSun_16); /設(shè)置中文字體GUI_DispString(年);/顯示年GUI_SetFont(&GUI_Font16_1 );/設(shè)置英文字體GUI_DispDec(s_time.tm_mon,2);/顯示萬年歷的月份GUI_SetFont(&GUI_FontHZ_SimSun_16);/設(shè)置中文字體GUI_DispString(月);/顯示月GUI_SetFont(&GUI_Font16_1 );/設(shè)置英文字體GUI_D

10、ispDec(s_time.tm_mday,2);/顯示萬年歷的日子GUI_SetFont(&GUI_FontHZ_SimSun_16);/設(shè)置中文字體GUI_DispString(日);/顯示日/畫模擬時鐘界面u16 index,x,y;GUI_SetPenSize(1);GUI_SetColor(GUI_RED);GUI_DrawCircle(264,170, 45);/畫時鐘最外層的圓, for( index = 0; index 2099)/超過范圍處理s_time.tm_year=1970;else if(key=41)/年數(shù)減小按鈕s_time.tm_year-; /F2if(s_

11、time.tm_year12)/超過范圍處理s_time.tm_mon=1;else if(key=43) /月數(shù)減小按鈕s_time.tm_mon-; /F4if(s_time.tm_mongetDays(s_time.tm_year,s_time.tm_mon)/超過范圍處理s_time.tm_mday=1;else if(key=45) /日數(shù)減小按鈕s_time.tm_mday-; /F6if(s_time.tm_mday0)/超過范圍處理s_time.tm_mday=getDays(s_time.tm_year,s_time.tm_mon);GUI_SetFont(&GUI_Font

12、16_1 );GUI_DispDecAt(s_time.tm_year,4,13,4);/顯示萬年歷的年數(shù)GUI_SetFont(&GUI_FontHZ_SimSun_16);GUI_DispString(年);/顯示年GUI_SetFont(&GUI_Font16_1 );GUI_DispDec(s_time.tm_mon,2);/顯示萬年歷的月數(shù)GUI_SetFont(&GUI_FontHZ_SimSun_16);GUI_DispString(月);/顯示月GUI_SetFont(&GUI_Font16_1 );GUI_DispDec(s_time.tm_mday,2);/顯示萬年歷的日數(shù)

13、GUI_SetFont(&GUI_FontHZ_SimSun_16);GUI_DispString(日);/顯示日GUI_DispString( );GetChinaCalendarStr(u16)systmtime.tm_year,(u8)systmtime.tm_mon,(u8)systmtime.tm_mday,str);/陽歷轉(zhuǎn)陰歷/見下面子程序1GUI_DispString(str); /顯示陰歷GUI_SetColor(GUI_RED); /字體顏色GUI_DispString(竹天笑萬年歷); k=getWeekDay(s_time.tm_year,s_time.tm_mon,1

14、);/得到某年某月的第一天的星期數(shù)/見下面子程序2 GUI_GotoXY(18,69);./位置設(shè)定 GUI_SetFont(&GUI_Font6x8); /萬年歷日子顯示 for(i=1;i=40;i+)/第一行最少顯示一個,第六行最多顯示二個,i的上限只需要大于37即可 if(igetDays(s_time.tm_year,s_time.tm_mon)+k)/本月1號前和最后一天后的格子顯示清零 /見子程序3 GUI_DispString( );/顯示空格,用于清除之前數(shù)據(jù) else if(i+1)%7=0|i%7=0)/如果為星期六和星期天,字體設(shè)置為紅色 GUI_SetColor(GU

15、I_RED); else/否則為黑色 GUI_SetColor(GUI_BLACK); if(i=s_time.tm_mday+k)/如果該天為所選日期,設(shè)置背景為黃色GUI_SetBkColor(GUI_YELLOW); GUI_DispDecSpace(i-k,2);/顯示日子GUI_SetBkColor(GUI_WHITE);/恢復(fù)之前背景色 GUI_GotoXY(GUI_GetDispPosX()+17,GUI_GetDispPosY();/光標(biāo)移動到下一個格子 if(i%7=0) GUI_GotoXY(18,GUI_GetDispPosY()+27);/7天換行顯示 GUI_Goto

16、XY(12,79); /光標(biāo)移動到下一行首行 GUI_SetFont(&GUI_FontHZ_SimSun_11);/顯示為初幾,若為節(jié)氣則顯示節(jié)氣 for(i=1;i=40;i+) if(igetDays(s_time.tm_year,s_time.tm_mon)+k)/本月1號前和最后一天后的格子顯示清零 GUI_DispString();/顯示兩個中文空格,占兩個中文字符 else if(GetJieQiDay(u16)s_time.tm_year, (u8)s_time.tm_mon, i-k, str)=1)/如果為節(jié)氣/見子程序4GUI_SetColor(GUI_MAGENTA);

17、/設(shè)置字體為橙色elseGUI_SetColor(GUI_BLUE);/正常顯示藍色if(i=s_time.tm_mday+k)/如果該天為所選日期,設(shè)置背景為黃色GUI_SetBkColor(GUI_YELLOW); GUI_DispString(str);/顯示陰歷號GUI_SetBkColor(GUI_WHITE);/恢復(fù)背景色 GUI_GotoXY(GUI_GetDispPosX()+7,GUI_GetDispPosY(); if(i%7=0) GUI_GotoXY(12,GUI_GetDispPosY()+27); WM_ExecIdle(); /刷新屏幕#defineDEG2RAD

18、 (3.1415926f / 180) GUI_POINT m_Hour2,m_Sec2,m_Min2;/時分秒兩個端點static GUI_POINT m_OldHour2,m_OldMin2,m_OldSec2;/時分秒之前的兩個端點 m_Hour0.x=-20*cos(systmtime.tm_hour*30+90)*DEG2RAD)+264;/時鐘指針端點計算,每一時旋轉(zhuǎn)30 m_Hour0.y=-20*sin(systmtime.tm_hour*30+90)*DEG2RAD)+170;/度,逆時針旋轉(zhuǎn),當(dāng)前時鐘*30得旋 m_Hour1.x=-2*cos(systmtime.tm_h

19、our*30+270)*DEG2RAD)+264;/轉(zhuǎn)的度數(shù), 時鐘另一端加上180度 m_Hour1.y=-2*sin(systmtime.tm_hour*30+270)*DEG2RAD)+170; /將極坐標(biāo)形式轉(zhuǎn)換成直角坐標(biāo)GUI_SetColor(GUI_WHITE);/重繪上一次時鐘指針覆蓋的背景 GUI_DrawLine(m_OldHour0.x,m_OldHour0.y, m_OldHour1.x,m_OldHour1.y);GUI_SetColor(GUI_RED);/畫新的時鐘指針 GUI_DrawLine(m_Hour0.x,m_Hour0.y, m_Hour1.x,m_H

20、our1.y); m_Min0.x=-30*cos(systmtime.tm_min*6+90)*DEG2RAD)+264;/分鐘指針端點計算,每一分旋轉(zhuǎn)6 m_Min0.y=-30*sin(systmtime.tm_min*6+90)*DEG2RAD)+170;/度,逆時針旋轉(zhuǎn),當(dāng)前分鐘*6得旋 m_Min1.x=-4*cos(systmtime.tm_min*6+270)*DEG2RAD)+264;/轉(zhuǎn)的度數(shù), 時鐘另一端加上180度 m_Min1.y=-4*sin(systmtime.tm_min*6+270)*DEG2RAD)+170; /將極坐標(biāo)形式轉(zhuǎn)換成直角坐標(biāo) GUI_SetCo

21、lor(GUI_WHITE);/重繪上一次分鐘指針覆蓋的背景 GUI_DrawLine(m_OldMin0.x,m_OldMin0.y, m_OldMin1.x,m_OldMin1.y); GUI_SetColor(GUI_BLUE);/畫新的分鐘指針 GUI_DrawLine(m_Min0.x,m_Min0.y, m_Min1.x,m_Min1.y); m_Sec0.x=-35*cos(systmtime.tm_sec*6+90)*DEG2RAD)+264;/分鐘指針端點計算,每一秒旋轉(zhuǎn)6 m_Sec0.y=-35*sin(systmtime.tm_sec*6+90)*DEG2RAD)+17

22、0;/度,逆時針旋轉(zhuǎn),當(dāng)前秒鐘*6得旋 m_Sec1.x=-8*cos(systmtime.tm_sec*6+270)*DEG2RAD)+264;/轉(zhuǎn)的度數(shù), 時鐘另一端加上180度 m_Sec1.y=-8*sin(systmtime.tm_sec*6+270)*DEG2RAD)+170;/將極坐標(biāo)形式轉(zhuǎn)換成直角坐標(biāo) GUI_SetColor(GUI_WHITE); GUI_DrawLine(m_OldSec0.x,m_OldSec0.y, m_OldSec1.x,m_OldSec1.y); GUI_SetColor(GUI_BLACK); GUI_DrawLine(m_Sec0.x,m_Se

23、c0.y, m_Sec1.x,m_Sec1.y); for(i=0;i10) StrCopy(&str10,(u8 *)nonglidayNLyear3/10,2);elseStrCopy(&str10,(u8 *)初,2);StrCopy(&str12,(u8 *)monthcode(NLyear3-1)%10,2);子程序2u8 getWeekDay(u16 y, u8 m, u8 d) /得到指定年月日的星期數(shù) if (m = 1) m = 13; if (m = 2) m = 14; u8 week = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4

24、- y / 100 + y / 400) % 7 + 1; return week; 子程序3/*判斷是否閏年*參數(shù): y 整型, 接收年份值*返回值: 整型, 只為0或1, 0代表假, 1代表真*/u8 isRunNian(u16 y) return (y % 4 = 0 & y % 100 != 0 | y % 400 = 0) ? 1 : 0;/*計算某個月的天數(shù)*參數(shù): y 整型,接收年份值; m 整型,接收月份值;*返回值: 整型, 是0, 28, 29, 30, 31之間的一個數(shù)*注意: 返回值為0,表示你調(diào)用該函數(shù)時傳遞了不正確的年份值或月份值.*/u8 getDays(u16

25、y, u8 m) u8 days = 0; switch(m) case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break; case 4: case 6: case 9: case 11: days = 30; break; case 2: days = isRunNian(y) ? 29 : 28; break; default:; return days;子程序4/ 函數(shù)名稱:GetJieQiDay/ 功能描述:輸入公歷日期得到24節(jié)氣字符串/ 是否為節(jié)氣/ 輸入: year 公歷年/ month

26、公歷月/ day 公歷日/ str 儲存24節(jié)氣字符串地址 5Byte/ 輸出: 1 成功/ 0 失敗 /u8 GetJieQiDay(u16 year,u8 month,u8 day,u8 *str)u8 JQdate,JQ;u8 NLyear4;StrCopy(&str0,(u8 *)初一,5);if(GetJieQi(year,month,day,&JQdate)=0)return 0;JQ = (month-1) *2 ; /獲得節(jié)氣順序標(biāo)號(023if(day = 15) JQ+; /判斷是否是上半月if(day=JQdate) /今天正是一個節(jié)氣日StrCopy(str,(u8 *

27、)JieQiStrJQ,5);return 1; /今天不是一個節(jié)氣日elseGetChinaCalendar(year,month,day,(u8 *)NLyear);if(NLyear310) StrCopy(&str0,(u8 *)nonglidayNLyear3/10,2);elseStrCopy(&str0,(u8 *)初,2);StrCopy(&str2,(u8 *)monthcode(NLyear3-1)%10,2);return 0;子程序5/ / 函數(shù)名稱:GetChinaCalendar/功能描述:公農(nóng)歷轉(zhuǎn)換(只允許1901-2099年)/ 輸入: year 公歷年/ mo

28、nth 公歷月/ day 公歷日/ p 儲存農(nóng)歷日期地址/ 輸出: 1 成功/ 0 失敗 /u8 GetChinaCalendar(u16 year,u8 month,u8 day,u8 *p) u8 temp1,temp2,temp3,month_p,yearH,yearL;u8 flag_y;unsigned short temp4,table_addr;yearH=year/100;yearL=year%100;/年份的高低兩個字節(jié) if(yearH!=19)&(yearH!=20)return(0);/日期不在19xx 20xx 范圍內(nèi),則退出/ 定位數(shù)據(jù)表地址 if(yearH=20

29、)table_addr=(yearL+100-1)*3;else table_addr=(yearL-1)*3;/ 取當(dāng)年春節(jié)所在的公歷月份 temp1=year_codetable_addr+2&0x60;temp1=5;/ 取當(dāng)年春節(jié)所在的公歷日 temp2=year_codetable_addr+2&31; / 計算當(dāng)年春年離當(dāng)年元旦的天數(shù),春節(jié)只會在公歷1月或2月 if(temp1=1) temp3=temp2-1; else temp3=temp2+31-1; / 計算公歷日離當(dāng)年元旦的天數(shù) if (month2)&(yearL%4=0) temp4+;/ 判斷公歷日在春節(jié)前還是春節(jié)

30、后 if (temp4=temp3) temp4-=temp3;month=1;month_p=1;flag_y=0;if(GetMoonDay(month_p,table_addr)=0)temp1=29; /小月29天else temp1=30; /大小30天/ 從數(shù)據(jù)表中取該年的閏月月份,如為0則該年無閏月 temp2=year_codetable_addr/16; while(temp4=temp1)temp4-=temp1;month_p+;if(month=temp2)flag_y=flag_y;if(flag_y=0)month+;else month+;if(GetMoonDa

31、y(month_p,table_addr)=0)temp1=29;else temp1=30;day=temp4+1;/ 公歷日在春節(jié)前使用下面代碼進行運算 else temp3-=temp4;if (yearL=0)yearL=100-1;yearH=19;else yearL-;table_addr-=3;month=12;temp2=year_codetable_addr/16; if (temp2=0)month_p=12; else month_p=13; flag_y=0;if(GetMoonDay(month_p,table_addr)=0)temp1=29; else temp

32、1=30; while(temp3temp1)temp3-=temp1;month_p-;if(flag_y=0)month-;if(month=temp2)flag_y=flag_y;if(GetMoonDay(month_p,table_addr)=0)temp1=29;else temp1=30;day=temp1-temp3+1;*p+=yearH;*p+=yearL;*p+=month;*p=day;return(1);2、觸摸屏任務(wù):處理觸摸屏按鍵任務(wù),更改要查詢的年月日。static void AppTaskKbd (void *p_arg) (void)p_arg; TP_Init();/觸摸初始化 while(1) OSTimeDlyHMSM(0,0,0,10); GUI_TOUCH_Exec(); /觸摸執(zhí)行程序,詳細請閱讀ucgui教程3、秒更新任務(wù):秒更新任務(wù)中一直等待一個OS_EVENT(信號量),RTC鬧鐘一秒鐘中斷一次,鬧鐘中斷程序中發(fā)送信號量,秒更新任務(wù)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論