本設計中,在按鍵處理方面,下了不少功夫,雖然只有三個按鍵,不同狀態下,實現不同的功能.
為了節省用電,設計背景燈有按鍵銨下才亮,延時5秒后滅.長按K1進入設置狀態,按K2移位,K3數字加.依次設置年月日,星期,時分秒,鬧鐘1,鬧鐘2.
在走時狀態下,按K2顯示鬧鐘1,按K3顯示鬧鐘2,延時5秒后返回走時.在顯示鬧鐘狀態下,按K1,開關鬧鐘,顯示"*"為開.走時狀態下顯示"%"為只有一個鬧鐘開,顯示"@"為兩個鬧鐘開.在鬧鐘響鈴時,按任意鍵關閉聲音.
制作出來的原理圖如下:
1532689260920.jpg (988.63 KB, 下載次數: 86)
下載附件
2018-7-27 19:10 上傳
IMG_20180725_214417.jpg (1.44 MB, 下載次數: 65)
下載附件
2018-7-27 19:13 上傳
IMG_20180724_101645.jpg (1.11 MB, 下載次數: 69)
下載附件
2018-7-27 19:13 上傳
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
IMG_20180727_191855.jpg (1.61 MB, 下載次數: 67)
下載附件
2018-7-27 19:23 上傳
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
IMG_20180727_191906.jpg (1.64 MB, 下載次數: 69)
下載附件
2018-7-27 19:24 上傳
單片機源程序如下:
- #include "Lcd1602.h"
- #include "KEY.h"
- #include "DS18B20.h"
- #include "DS1302.h"
- uchar T0RH,T0RL;
- bit flag1s = 1; //1秒標志
- bit flag200ms = 1; //200毫秒標志
- bit beeonoff1=0,beeonoff2=0; //鬧鐘1,2開關標志
- bit beeon = 0; //峰鳴開關
- uchar keybee = 0; //按鍵鬧鐘1,2切換
- uchar hourbee1=0x08,minbee1=0x00,hourbee2=0x13,minbee2=0x30; //鬧鐘1,2存放值
- uchar flag = 0; //鬧鐘顯示時間
- uchar pos = 0; //設置時間引索
- sint buftemp; //溫度暫存
- struct sTime {
- uchar year;
- uchar mon;
- uchar day;
- uchar hour;
- uchar min;
- uchar sec;
- uchar week;
- };
- struct sTime buftime;
- void ConfigTimer0(uchar ms);
- void ShowTemp();
- void RefrTime();
- void main()
- {
- bit reg = 0;
- uchar bufsec = 0xaa;
-
- EA = 1;
- ConfigTimer0(2);
- LcdInit();
- DS1302Init();
- Start18B20();
- GainTime(&buftime);
- RefrTime();
- while(1)
- {
- KeyDriver();
- if (!pos)
- {
- if (flag200ms)
- {
- flag200ms = 0;
- GainTime(&buftime);
- if (bufsec != buftime.sec)
- {
- RefrTime();
- bufsec = buftime.sec;
- }
- if (((hourbee1==buftime.hour) && (minbee1==buftime.min) && beeonoff1) || (hourbee2==buftime.hour) && (minbee2==buftime.min) && beeonoff2)
- {
- beeon = 1;
- }
- else
- {
- beeon = 0;
- }
- }
- if (flag1s )
- {
- flag1s = 0;
- reg = Get18B20Temp(&buftemp);
- if (reg)
- {
- ShowTemp();
- }
- Start18B20();
- }
- }
- }
- }
- void ShowTemp() //溫度顯示
- {
- schar i = 0;
- uchar len=0;
- uchar tempint,tempdec; //溫度整數部分,小數部分存放
- uchar buf[4],str[6];
- tempint = (buftemp>>4) & 0x7f; //取出整數部分
- tempdec = buftemp & 0x0f; //取出小數部分
- do {
- buf[i++] = tempint%10;
- tempint = tempint/10;
- }while (tempint > 0);
- if (i < 2)
- {
- str[len++] = ' ';
- }
- while (i-- > 0)
- {
- str[len++] = buf[i] + '0';
- }
- str[len++] = '.';
- str[len++] = (tempdec*10/16) +'0';
-
- str[len] = '\0';
- LcdShowStr(11,1,str);
- }
- void NumToStr(uchar x,uchar y, uchar *str) //數據轉換字符
- {
- uchar buf[3];
- buf[0] = (*str>>4) + '0';
- buf[1] = (*str&0x0f) + '0';
- buf[2] = '\0';
- LcdShowStr(x,y,buf);
- }
- void RefrTime() //刷新時間
- {
- NumToStr(2,0,&buftime.year);
- NumToStr(5,0,&buftime.mon);
- NumToStr(8,0,&buftime.day);
- LcdShowStr(15,0,&buftime.week);
- if (((flag>0) && (keybee ==1)) || ((pos>=14) && (pos<=17))) //鬧鐘1顯示
- {
- NumToStr(2,1,&hourbee1);
- NumToStr(5,1,&minbee1);
- LcdShowStr(8,1,"-1");
- }
- else if (((flag>0) && (keybee ==2)) || ((pos>=18) && (pos<=21))) //鬧鐘2顯示
- {
- NumToStr(2,1,&hourbee2);
- NumToStr(5,1,&minbee2);
- LcdShowStr(8,1,"-2");
- }
- else
- {
- NumToStr(2,1,&buftime.hour);
- NumToStr(5,1,&buftime.min);
- NumToStr(8,1,&buftime.sec);
- if (beeonoff1 && beeonoff2) //如果兩個鬧鐘開,則顯示"@"
- LcdShowStr(0,1,"@");
- else if (!beeonoff1 && !beeonoff2) //如果兩個鬧鐘關,則不顯示,
- LcdShowStr(0,1," ");
- else
- LcdShowStr(0,1,"%"); //如果其中一個鬧鐘開,則顯示"%"
- }
- }
- void BeeOnroOff() //鬧鐘開關時顯示
- {
- if (keybee == 1) //鬧鐘1開關
- {
- beeonoff1 = ~beeonoff1;
- if (beeonoff1)
- {
- LcdShowStr(0,1,"*"); //顯示"*",表示鬧鐘開
- }
- else
- {
- LcdShowStr(0,1," ");
- }
- }
- else if (keybee == 2) //鬧鐘2開關
- {
- beeonoff2 = ~beeonoff2;
- if (beeonoff1 || beeonoff2)
- {
- LcdShowStr(0,1,"*");
- }
- else
- {
- LcdShowStr(0,1," ");
- }
- }
- }
- void CurPosit() //光標位置,設置修改的位置
- {
- switch(pos)
- {
- case 1: LcdSetCort(2,0); break; //日期
- case 2: LcdSetCort(3,0); break;
- case 3: LcdSetCort(5,0); break;
- case 4: LcdSetCort(6,0); break;
- case 5: LcdSetCort(8,0); break;
- case 6: LcdSetCort(9,0); break;
- case 7: LcdSetCort(15,0); break; //星期
- case 8: LcdSetCort(2,1); break; //時間
- case 9: LcdSetCort(3,1); break;
- case 10: LcdSetCort(5,1); break;
- case 11: LcdSetCort(6,1); break;
- case 12: LcdSetCort(8,1); break;
- case 13: LcdSetCort(9,1); break;
- case 14: LcdSetCort(2,1); break; //鬧鐘1
- case 15: LcdSetCort(3,1); break;
- case 16: LcdSetCort(5,1); break;
- case 17: LcdSetCort(6,1); break;
- case 18: LcdSetCort(2,1); break; //鬧鐘2
- case 19: LcdSetCort(3,1); break;
- case 20: LcdSetCort(5,1); break;
- case 21: LcdSetCort(6,1); break;
- default: break;
- }
- }
- void RightShift() //向右移動
- {
- if (pos != 0)
- {
- if (pos < 21)
- pos++;
- else
- pos = 1;
- if ((pos==14) || (pos==18) || (pos==1))
- RefrTime();
- CurPosit();
- }
- }
- uchar IncBcdHigh(uchar dat, uchar n) //高位加
- {
- if ((dat&0xf0) < (n<<4))
- dat += 0x10;
- else
- dat &= 0x0f;
- return dat;
- }
- uchar IncBcdLow(uchar dat, uchar n) //低位加
- {
- if ((dat&0x0f) < n)
- dat += 0x01;
- else
- dat &= 0xf0;
- return dat;
- }
- uchar IncBcdWeek(uchar dat, uchar n) //星期加
- {
- if ((dat&0x0f) < n)
- dat += 0x01;
- else
- dat = 1;
- return dat;
- }
- void IncSetTime() //向上(加)
- {
- switch (pos)
- {
- case 1: buftime.year = IncBcdHigh(buftime.year,9); break;
- case 2: buftime.year = IncBcdLow(buftime.year,9); break;
- case 3: buftime.mon = IncBcdHigh(buftime.mon,1); break;
- case 4: buftime.mon = IncBcdLow(buftime.mon,9); break;
- case 5: buftime.day = IncBcdHigh(buftime.day,3); break;
- case 6: buftime.day = IncBcdLow(buftime.day,9); break;
- case 7: buftime.week = IncBcdWeek(buftime.week,7); break;
- case 8: buftime.hour = IncBcdHigh(buftime.hour,2); break;
- case 9: buftime.hour = IncBcdLow(buftime.hour,9); break;
- case 10: buftime.min = IncBcdHigh(buftime.min,5); break;
- case 11: buftime.min = IncBcdLow(buftime.min,9); break;
- case 12: buftime.sec = IncBcdHigh(buftime.sec,5); break;
- case 13: buftime.sec = IncBcdLow(buftime.sec,9); break;
- case 14: hourbee1 = IncBcdHigh(hourbee1,2); break;
- case 15: hourbee1 = IncBcdLow(hourbee1,9); break;
- case 16: minbee1 = IncBcdHigh(minbee1,5); break;
- case 17: minbee1 = IncBcdLow(minbee1,9); break;
- case 18: hourbee2 = IncBcdHigh(hourbee2,2); break;
- case 19: hourbee2 = IncBcdLow(hourbee2,9); break;
- case 20: minbee2 = IncBcdHigh(minbee2,5); break;
- case 21: minbee2 = IncBcdLow(minbee2,9); break;
- default: break;
- }
- RefrTime();
- CurPosit();
- }
- void EntertimeSet() //進入時間設置
- {
- pos = 21;
- RightShift();
- LcdCoorTwin(); //光標閃動
- }
- void KeyAction(uchar cod,bit set) //按鍵動作
- {
- switch(cod)
- {
- case 0: if (!set)
- {
- if (flag > 0) //鬧鐘延時顯示狀態下,則可以設置鬧鐘開關
- BeeOnroOff();
- pos = 0;
- SetTime(&buftime);
- LcdClsCur(); //光標閃動清除
- }
- else //進入設置
- {
- flag = 0; //延時顯示時間清零
- EntertimeSet();
- }
- break;
- case 1: if (!set && (pos==0)) //非設置狀態,顯示鬧鐘1
- {
- keybee = 1;
- flag = 3; //延時6秒計算
- if (beeonoff1)
- {
- LcdShowStr(0,1,"*"); //顯示鬧鐘標志
- }
- else
- {
- LcdShowStr(0,1," ");
- }
- RefrTime();
- }
- else if (pos!=0) //設置狀態,數字移動
- {
- RightShift();
- }
- break;
- case 2: if (!set && (pos==0)) //非設置狀態,顯示鬧鐘2
- {
- keybee = 2;
- flag = 3; //延時6秒計算
- if (beeonoff2)
- {
- LcdShowStr(0,1,"*"); //顯示鬧鐘標志
- }
- else
- {
- LcdShowStr(0,1," ");
- }
- RefrTime();
- }
- else if (pos!=0) //設置狀態,數字加
- {
- IncSetTime();
- }
- break;
- }
- }
- void LedLigh(bit ledt) //背影燈開啟
- {
- static bit ledflag = 0;
- static uint ledcou=0;
- if (ledt)
- {
- ledflag = 1;
- ledcou = 3000;
- LED = 0;
- }
- if (ledflag)
- {
- if (ledcou > 0)
- {
- ledcou--;
- }
- else
- {
- ledflag = 0;
- LED = 1;
- }
- }
- }
- void AlarmClock(bit on, bit beet) //鬧鐘發聲 on 鬧鐘觸發開關,beet為按鍵暫時關
- {
- static bit off = 0;
- static uchar alcou=0;
- if (on)
- {
- if (beet)
- off = 1;
- if (!off)
- {
- alcou++;
- if (alcou == 255)
- {
- alcou = 0;
- }
- if (alcou > 150)
- {
- BEE = ~BEE;
- }
- }
- else
- {
- BEE = 1;
- }
- }
- else
- {
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
0.png (41.79 KB, 下載次數: 65)
下載附件
2018-7-27 22:09 上傳
所有資料51hei提供下載:
自制小型萬年歷.zip
(440.2 KB, 下載次數: 150)
2018-7-27 19:14 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|