本貼針對學完單片機并且有讀懂代碼的非新手同學。本人目前放寒假,這個是本人在上個學期的單片機課上要求做的綜合實驗,現在重新修改了下增加了菜單目前測試毫無問題可以完美使用。有志向做鬧鐘的同學可以參考一下,原碼上由本人寫的大量注釋可以方便看懂。
使用了LCD1602、DS1302、DS18B20用來測試溫度、內部含鬧鐘系統但本人沒有做EEPROM有需要的同學可以自行添加。
單片機源程序如下:
- #include<reg52.h>
- #include<key.h>
- #include<LCD1602.h>
- #include<DS1302.h>
- #include<music.h>
- #include<DS18B20.H>
- #define normal 0//正常顯示時鐘界面
- #define settime 1//設定時鐘界面
- #define setalarm 2//設定鬧鐘界面
- #define displayalarm 3//顯示鬧鐘界面
- #define normal_12 4//顯示十二小時制界面
- #define caidan 5
- unsigned char system=normal;//我一開始就把界面切換為正常顯示時鐘界面
- extern unsigned char i,k;
- extern unsigned int code song[3][300];
- unsigned char code *week[8]={"NO ","Mon ","Tue ","Wed ","Thu ","Fri ","Sat ","Sun "};
- unsigned char code *clockzifu[4]={"ON ","OFF ","REP ","NRE "};
- struct Time timeset={0x18,0x01,0x16,0x14,0x30,0x50,0x03};
- //第一個鬧鐘
- //第二個鬧鐘
- //第三個鬧鐘
- //第四個鬧鐘
- //第五個鬧鐘
- struct alarmtime xdata clock[5]={{1,16,14,31,0,1,0,1},{1,8,14,32,3,0,0,0},{1,7,18,49,1,1,1,0},{0,0,0,0,0,0,1,0},{1,25,0,0,0,0,1,2}};
- unsigned char alarmnum;//鬧鐘
- unsigned char a;
- unsigned char flag=0;
- unsigned char xinghao=0;
- unsigned char tentoBCD(unsigned char dat)//十進制轉換為BCD碼函數
- {
- unsigned char dat1,dat2;
- dat1=dat/10;
- dat2=dat%10;
- dat2=dat2+dat1*16;
- return dat2;
- }
- unsigned char BCDtoten(unsigned char dat)//BCD碼轉為十進制函數
- {
- unsigned char dat1,dat2;
- dat1=dat/16;
- dat2=dat%16;
- dat2=dat2+dat1*10;
- return dat2;
- }
- void DS18B20deal(int temp)//DS18B20數據處理函數 顯示溫度更新溫度
- {
- //先判斷溫度值是否大于0或小于0等于0
- float tp;//保存的數據可能帶小數
- if(temp<0)//當溫度值為負數
- {
- LCD1602_writechar(9,1,0x2D);//ASCII碼中的-符號
- temp=temp-1;//因為讀取的溫度是實際溫度的補碼,所以減1,再取反求出原碼
- temp=~temp;//還原讀取的數據
- tp=temp;//保存到變量里面
- temp=tp*0.0625*100+0.5;//強制轉換成一個整形的數據.留兩個小數點就*100,+0.5是四舍五入,因為C語言浮點數轉換為整型的時候把小數點后面的數自動去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進1了,小于0.5的就算加上0.5,還是在小數點后面。
- }
- else//當溫度值為正數
- {
- LCD1602_writechar(9,1,0x20);//ASCII碼中的空格
- tp=temp;//因為數據處理有小數點所以將溫度賦給一個浮點型變量。如果溫度是正的那么,那么正數的原碼就是補碼它本身
- temp=tp*0.0625*100+0.5;//留兩個小數點就*100,+0.5是四舍五入,因為C語言浮點數轉換為整型的時候把小數點。后面的數自動去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進1了,小于0.5的就算加上0.5,還是在小數點后面。
- }
- LCD1602_writechar(10,1,temp/10000+'0');//溫度百位
- LCD1602_writechar(11,1,temp%10000/1000+'0');//溫度十位
- LCD1602_writechar(12,1,temp%1000/100+'0');//溫度個位
- LCD1602_writechar(13,1,0x2E);//ASCII碼小數點
- LCD1602_writechar(14,1,temp%100/10+'0');//小數點后一位
- LCD1602_writechar(15,1,temp%10+'0');//小數點后兩位
- }
- void updatetime()//更新時鐘上的時間
- {
- unsigned char time[9];//存儲變量
- DS1302_gettime(×et);//讀取時間
- time[0]=BCDtoten(timeset.hour)/10+'0';//小時的十位
- time[1]=BCDtoten(timeset.hour)%10+'0';//小時的個位
- time[2]=':';
- time[3]=BCDtoten(timeset.min)/10+'0';//分的十位
- time[4]=BCDtoten(timeset.min)%10+'0';//分的個位
- time[5]=':';
- time[6]=BCDtoten(timeset.sec)/10+'0';//秒的十位
- time[7]=BCDtoten(timeset.sec)%10+'0';//秒的個位
- time[8]='\0';//字符串結束標志
- LCD1602_writestr(0,1,time);//在LCD上面打印時間
- }
- void updatetime_12()//更新十二小時制界面的時間
- {
- unsigned char time[9];
- DS1302_gettime(×et);//讀取時間
- time[0]= BCDtoten(timeset.hour)%12/10+'0';//小時的十位
- time[1]= BCDtoten(timeset.hour)%12%10+'0';//小時的個位
- time[2]=':';
- time[3]= BCDtoten(timeset.min)/10+'0';//分的十位
- time[4]= BCDtoten(timeset.min)%10+'0';//分的個位
- time[5]=':';
- time[6]= BCDtoten(timeset.sec)/10+'0';//秒的十位
- time[7]= BCDtoten(timeset.sec)%10+'0';//秒的個位
- time[8]='\0';//字符串結束標志
- LCD1602_writestr(3,1,"TIME:");//打印出TIME的字符串
- LCD1602_writestr(8,1,time);//在第二行第四列顯示時間
- if(BCDtoten(timeset.hour)>12)//要是小時大于12時
- {
- LCD1602_writestr(0,1,"PM");//則顯示PM
- }
- else//小時不大于12
- {
- LCD1602_writestr(0,1,"AM");//則顯示AM
- }
- }
- void updatedate()//更新日歷
- {
- unsigned char date[12];
- date[0]= '2';
- date[1]= '0';
- date[2]= BCDtoten(timeset.year)/10%10+'0';//年的十位
- date[3]= BCDtoten(timeset.year)%10+'0';//年的個位
- date[4]='.';
- date[5]= BCDtoten(timeset.mon)/10+'0';//月的十位
- date[6]= BCDtoten(timeset.mon)%10+'0';//月的個位
- date[7]='.';
- date[8]= BCDtoten(timeset.day)/10+'0';//日的十位
- date[9]= BCDtoten(timeset.day)%10+'0';//日的個位
- date[10]='\0';
- LCD1602_writestr(0,0,date);//顯示年月日
- LCD1602_writestr(11,0,week[timeset.week]);//顯示星期
- }
- void updatealarm()//更新鬧鐘設定值
- {
- unsigned char str0[14];
- unsigned char str1[2];
- str0[0]=alarmnum+'0';
- str0[1]=' ';
- str0[2]=clock[alarmnum].mon/10+'0';//月份十位
- str0[3]=clock[alarmnum].mon%10+'0';//月份個位
- str0[4]='-';
- str0[5]=clock[alarmnum].day/10+'0';//日期十位
- str0[6]=clock[alarmnum].day%10+'0';//日期個位
- str0[7]=' ';
- str0[8]=clock[alarmnum].hour/10+'0';//小時十位
- str0[9]=clock[alarmnum].hour%10+'0';//小時個位
- str0[10]=':';
- str0[11]=clock[alarmnum].min/10+'0';//分鐘十位
- str0[12]=clock[alarmnum].min%10+'0';//分鐘個位
- str0[13]='\0';
- LCD1602_writestr(0,1,str0);
- str1[0]=clock[alarmnum].music+'0';//鈴聲
- str1[1]='\0';
- LCD1602_writestr(0,0,"U");
- LCD1602_writestr(1,0,str1);//顯示鈴聲
- LCD1602_writestr(3,0,clockzifu[clock[alarmnum].alarmre+2]);//顯示重不重復
- LCD1602_writestr(7,0,week[clock[alarmnum].week]);//顯示星期
- LCD1602_writestr(11,0,clockzifu[clock[alarmnum].alarmon]);//顯示開關
- }
- void anjian4();
- void anjian1()
- {
- if(system==normal)
- {
- system=caidan;
- xinghao=0;
- LCD1602_clear();
- LCD1602_writechar(0,0,'*');
- LCD1602_writestr(1,0,"12");
- LCD1602_writestr(1,1,"alarm");
- LCD1602_writestr(8,0,"setclock");
- LCD1602_writestr(8,1,"setalarm");
- }
- else if(system==caidan&&xinghao==0)
- {
- system=normal_12;//切換到12小時制
- LCD1602_clear();//清屏
- updatetime_12();//顯示12小時制的時間
- updatedate();//顯示日期
- }
- else if(system==caidan&&xinghao==1)
- {
- system=displayalarm;//切換到鬧鐘顯示
- LCD1602_clear();//清屏
- updatealarm();//顯示鬧鐘界面
- }
- else if(system==caidan&&xinghao==2)
- {
- system=settime;//進入設置時間界面
- LCD1602_clear();
- updatetime();//刷新時間
- updatedate();//刷新日期
- DS18B20deal(DS18B20readtemp());//DS18B20數據處理函數 同時輸出溫度
- flag=0;//光標索引設置到秒鐘上
- anjian4();//顯示光標位置
- LCD1602_openguangbiao();//LCD1602打開光標顯示
- }
- else if(system==caidan&&xinghao==3)
- {
- system=setalarm;//進入設置鬧鐘
- LCD1602_clear();//清屏
- updatealarm();//顯示鬧鐘界面
- flag=0;//光標索引設置到多鬧鐘選擇處上
- anjian4();//顯示光標位置
- LCD1602_openguangbiao();//LCD1602打開光標顯示
- }
- else if(system==settime)
- {
- system=normal;//切換回正常顯示時鐘的界面,顯示日歷時鐘、溫度。
- DS1302_settime(×et);//把設定時間寫入實時時鐘
- LCD1602_closeguangbiao();//LCD1602關閉光標顯示
- LCD1602_clear();//LCD1602清屏
- updatetime();//刷新時間
- updatedate();//立即刷新日期
- DS18B20deal(DS18B20readtemp());//DS18B20數據處理函數 顯示溫度
- }
- else if(system==setalarm)
- {
- system=displayalarm;//返回到鬧鐘顯示
- LCD1602_closeguangbiao();//LCD1602關閉光標顯示
- LCD1602_clear();//清屏
- updatealarm();//刷新鬧鐘界面
- }
- }
- void anjian4()
- {
- if(system==caidan)
- {
- system=normal;
- LCD1602_clear();//清屏
- updatetime();//顯示時鐘時間
- updatedate();//顯示日期
- DS18B20deal(DS18B20readtemp());//DS18B20數據處理函數
- }
- else if(system==normal_12)
- {
- system=normal;//返回時鐘顯示界面
- LCD1602_clear();//清屏
- updatetime();//顯示時鐘時間
- updatedate();//顯示日期
- DS18B20deal(DS18B20readtemp());//DS18B20數據處理函數
- }
- else if(system==displayalarm)
- {
- system=caidan;
- xinghao=1;
- LCD1602_clear();
- LCD1602_writechar(0,1,'*');
- LCD1602_writestr(1,0,"12");
- LCD1602_writestr(1,1,"alarm");
- LCD1602_writestr(8,0,"setclock");
- LCD1602_writestr(8,1,"setalarm");
- }
- else if(system==settime)//當前系統狀態位于設置時間時 定義光標的位置
- {
- switch(flag)//保存的設置位
- {
- case 0:LCD1602_setcur(7,1);flag=1;break;//定位于秒鐘個位處
- case 1:LCD1602_setcur(4,1);flag=2;break;//定位于分鐘處
- case 2:LCD1602_setcur(1,1);flag=3;break;//定位于小時處
- case 3:LCD1602_setcur(11,0);flag=4;break;//定位于星期處
- case 4:LCD1602_setcur(9,0);flag=5;break;//定位于日處
- case 5:LCD1602_setcur(6,0);flag=6;break;//定位于月處
- default:LCD1602_setcur(3,0);flag=0;break;//定位于年處
- }
- }
- else if(system==setalarm)//當前系統狀態位于設置鬧鐘時 定義光標的位置
- {
- switch(flag)//保存的設置位
- {
- case 0:LCD1602_setcur(0,1);flag=1;break;//定位于多鬧鐘選擇處
- case 1:LCD1602_setcur(3,1);flag=2;break;//定位于鬧鐘月份處
- case 2:LCD1602_setcur(6,1);flag=3;break;//定位于鬧鐘日處
- case 3:LCD1602_setcur(9,1);flag=4;break;//定位于鬧鐘分鐘處
- case 4:LCD1602_setcur(12,1);flag=5;break;//定位于鬧鐘小時處
- case 5:LCD1602_setcur(1,0);flag=6;break;//定位于鬧鐘鈴聲選擇處
- case 6:LCD1602_setcur(3,0);flag=7;break;//定位于鬧鐘重復與不重復選擇處
- case 7:LCD1602_setcur(7,0);flag=8;break;//定位于鬧鐘星期選擇處
- default:LCD1602_setcur(11,0);flag=0;break;//定位于鬧鐘開關處
- }
- }
- }
- void zengjia()//增加
- {
- if(system==caidan)
- {
- if(xinghao==0)
- {
- LCD1602_clear();
- LCD1602_writechar(0,1,'*');
- LCD1602_writestr(1,0,"12");
- LCD1602_writestr(1,1,"alarm");
- LCD1602_writestr(8,0,"setclock");
- LCD1602_writestr(8,1,"setalarm");
- xinghao=1;
- }
- else if(xinghao==1)
- {
- LCD1602_clear();
- LCD1602_writechar(7,0,'*');
- LCD1602_writestr(1,0,"12");
- LCD1602_writestr(1,1,"alarm");
- LCD1602_writestr(8,0,"setclock");
- LCD1602_writestr(8,1,"setalarm");
- xinghao=2;
- }
- else if(xinghao==2)
- {
- LCD1602_clear();
- LCD1602_writechar(7,1,'*');
- LCD1602_writestr(1,0,"12");
- LCD1602_writestr(1,1,"alarm");
- LCD1602_writestr(8,0,"setclock");
- LCD1602_writestr(8,1,"setalarm");
- xinghao=3;
- }
- else if(xinghao==3)
- {
- LCD1602_clear();
- LCD1602_writechar(0,0,'*');
- LCD1602_writestr(1,0,"12");
- LCD1602_writestr(1,1,"alarm");
- LCD1602_writestr(8,0,"setclock");
- LCD1602_writestr(8,1,"setalarm");
- xinghao=0;
- }
- }
- else if(system==settime)//當設置日歷時間的界面時
- {
- switch(flag)//檢查光標位置
- {
- case 1: a=BCDtoten(timeset.sec);//把BCD碼轉為十進制 因為DS1302里時鐘程序讀寫時都是BCD碼 轉為10進制更好處理
- if(a<59)
- {
- a++;
- }
- else
- {
- a=0;//限制設置秒鐘不超過59秒,超過則回到0
- }
- timeset.sec=tentoBCD(a);//把十進制轉為BCD碼 因為DS1302時鐘程序讀寫時都是BCD碼 將加完的東西重新賦值給sec
- LCD1602_writechar(6,1,(timeset.sec>>4)+'0');//秒的十位
- LCD1602_writechar(7,1,(timeset.sec&0x0f)+'0');//秒的個位
- LCD1602_setcur(7,1);//光標保持原位
- break;
- case 2: a=BCDtoten(timeset.min);//把BCD碼轉為十進制
- if(a<59)
- {
- a++;
- }
- else
- {
- a=0;//限制設置分鐘不超過59分,超過則回到0
- }
- timeset.min=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(3,1,(timeset.min>>4)+'0');//分的十位
- LCD1602_writechar(4,1,(timeset.min&0x0f)+'0');//分的個位
- LCD1602_setcur(4,1);//光標保持原位
- break;
- case 3: a=BCDtoten(timeset.hour);//把BCD碼轉為十進制
- if(a<23)
- {
- a++;
- }
- else
- {
- a=0;//限制設置小時不超過23時,超過則回到0
- }
- timeset.hour=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(0,1,(timeset.hour>>4)+'0');//小時的十位
- LCD1602_writechar(1,1,(timeset.hour&0x0f)+'0');//小時的個位
- LCD1602_setcur(1,1);//光標保持原位
- break;
- case 4: if(timeset.week<7)//限制不超過星期日,如果超過則回到周一
- {
- timeset.week++;
- }
- else
- {
- timeset.week=1;//回到星期一
- }
- LCD1602_writestr(11,0,week[timeset.week]);//
- LCD1602_setcur(11,0);//光標保持原位
- break;
- case 5: a=BCDtoten(timeset.day);//把BCD碼轉為十進制
- if(a<31)
- {
- a++;
- }
- else
- {
- a=1;//限制設置日期不超過31日,超過則回到1
- }
- timeset.day=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(8,0,(timeset.day>>4)+'0');//日的十位
- LCD1602_writechar(9,0,(timeset.day&0x0f)+'0');//日的個位
- LCD1602_setcur(9,0);//光標保持原位
- break;
- case 6: a=BCDtoten(timeset.mon);//把BCD碼轉為十進制
- if(a<12)
- {
- a++;
- }
- else
- {
- a=1;//限制設置月份不超過12月,超過則回到1
- }
- timeset.mon=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(5,0,(timeset.mon>>4)+'0');//月的十位
- LCD1602_writechar(6,0,(timeset.mon&0x0f)+'0');//月的個位
- LCD1602_setcur(6,0);//光標保持原位
- break;
- case 0: a=BCDtoten(timeset.year);//把BCD碼轉為十進制
- if(a<99)
- {
- a++;
- }
- else
- {
- a=0;//限制設置年不超過99年,超過則回到0
- }
- timeset.year=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(2,0,(timeset.year>>4)+'0');//年的十位
- LCD1602_writechar(3,0,(timeset.year&0x0f)+'0');//年的個位
- LCD1602_setcur(3,0);//光標保持原位
- break;
- }
- }
- else if(system==setalarm)//當設置鬧鐘的時候
- {
- switch(flag)//檢查光標位置
- {
- case 1: if(alarmnum<4)//換鬧鐘
- {
- alarmnum++;
- }
- else
- {
- alarmnum=0;
- }
- updatealarm();//更新鬧鐘設定值
- LCD1602_setcur(0,1);//光標保持原位
- break;
- case 2: if(clock[alarmnum].mon<12)
- {
- clock[alarmnum].mon++;
- }
- else
- {
- clock[alarmnum].mon=1;//限制設置月份不超過12月,超過則回到1
- }
- LCD1602_writechar(2,1,(clock[alarmnum].mon/10)+'0');//月的十位
- LCD1602_writechar(3,1,(clock[alarmnum].mon%10)+'0');//月的個位
- LCD1602_setcur(3,1);//光標保持原位
- break;
- case 3: if(clock[alarmnum].day<31)
- {
- clock[alarmnum].day++;
- }
- else
- {
- clock[alarmnum].day=1;//限制設置日期不超過31日,超過則回到1
- }
- LCD1602_writechar(5,1,(clock[alarmnum].day/10)+'0');//日的十位
- LCD1602_writechar(6,1,(clock[alarmnum].day%10)+'0');//日的個位
- LCD1602_setcur(6,1);//光標保持原位
- break;
- case 4: if(clock[alarmnum].hour<23)
- {
- clock[alarmnum].hour++;
- }
- else
- {
- clock[alarmnum].hour=0;//限制設置小時不超過23時,超過則回到0
- }
- LCD1602_writechar(8,1,(clock[alarmnum].hour/10)+'0');//小時的十位
- LCD1602_writechar(9,1,(clock[alarmnum].hour%10)+'0');//小時的個位
- LCD1602_setcur(9,1);//光標保持原位
- break;
- case 5: if(clock[alarmnum].min<59)
- {
- clock[alarmnum].min++;
- }
- else
- {
- clock[alarmnum].min=0;//限制設置分鐘不超過59分,超過則回到0
- }
- LCD1602_writechar(11,1,(clock[alarmnum].min/10)+'0');//分鐘的十位
- LCD1602_writechar(12,1,(clock[alarmnum].min%10)+'0');//分鐘的個位
- LCD1602_setcur(12,1);//光標保持原位
- break;
-
- case 6: if(clock[alarmnum].music<2)
- {
- clock[alarmnum].music++;
- }
- else
- {
- clock[alarmnum].music=0;
- }
- LCD1602_writechar(1,0,clock[alarmnum].music+'0');//音樂曲目
- LCD1602_setcur(1,0);//光標保持原位
- break;
-
- case 7: clock[alarmnum].alarmre=~clock[alarmnum].alarmre;//取反
- LCD1602_writestr(3,0,clockzifu[clock[alarmnum].alarmre+2]);//顯示鬧鐘狀態
- LCD1602_setcur(3,0);//光標保持原位
- break;
- case 8: if(clock[alarmnum].week<7)
- {
- clock[alarmnum].week++;
- }
- else
- {
- clock[alarmnum].week=0;//限制不超過星期日,如果超過則回到不設星期
- }
- LCD1602_writestr(7,0,week[clock[alarmnum].week]);//顯示到液晶上;
- LCD1602_setcur(7,0);//光標保持原位
- break;
- case 0: clock[alarmnum].alarmon=~clock[alarmnum].alarmon;//取反
- LCD1602_writestr(11,0,clockzifu[clock[alarmnum].alarmon]);//顯示鬧鐘狀態
- LCD1602_setcur(11,0);//光標保持原位
- break;
- }
- }
- }
- void jianxiao()//S4按鍵功能函數,數據減
- {
- if(system==caidan)
- {
- if(xinghao==0)
- {
- LCD1602_clear();
- LCD1602_writechar(7,1,'*');
- LCD1602_writestr(1,0,"12");
- LCD1602_writestr(1,1,"alarm");
- LCD1602_writestr(8,0,"setclock");
- LCD1602_writestr(8,1,"setalarm");
- xinghao=3;
- }
- else if(xinghao==3)
- {
- LCD1602_clear();
- LCD1602_writechar(7,0,'*');
- LCD1602_writestr(1,0,"12");
- LCD1602_writestr(1,1,"alarm");
- LCD1602_writestr(8,0,"setclock");
- LCD1602_writestr(8,1,"setalarm");
- xinghao=2;
- }
- else if(xinghao==2)
- {
- LCD1602_clear();
- LCD1602_writechar(0,1,'*');
- LCD1602_writestr(1,0,"12");
- LCD1602_writestr(1,1,"alarm");
- LCD1602_writestr(8,0,"setclock");
- LCD1602_writestr(8,1,"setalarm");
- xinghao=1;
- }
- else if(xinghao==1)
- {
- LCD1602_clear();
- LCD1602_writechar(0,0,'*');
- LCD1602_writestr(1,0,"12");
- LCD1602_writestr(1,1,"alarm");
- LCD1602_writestr(8,0,"setclock");
- LCD1602_writestr(8,1,"setalarm");
- xinghao=0;
- }
- }
- else if(system==settime)//設置日期/時間
- {
- switch(flag)//檢查光標位置
- {
- case 1: a=BCDtoten(timeset.sec);//把BCD碼轉為十進制
- if(a!=0)
- {
- a--;
- }
- else
- {
- a=59;//限制設置秒鐘不為0時減1,為0時回到59
- }
- timeset.sec=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(6,1,(timeset.sec>>4)+'0');//秒的十位
- LCD1602_writechar(7,1,(timeset.sec&0x0f)+'0');//秒的個位
- LCD1602_setcur(7,1);//光標保持原位
- break;
- case 2: a=BCDtoten(timeset.min);//把BCD碼轉為十進制
- if(a!=0)
- {
- a--;
- }
- else
- {
- a=59;//限制設置分鐘不為0時減1,為0時回到59
- }
- timeset.min=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(3,1,(timeset.min>>4)+'0');//分的十位
- LCD1602_writechar(4,1,(timeset.min&0x0f)+'0');//分的個位
- LCD1602_setcur(4,1);//光標保持原位
- break;
- case 3: a=BCDtoten(timeset.hour);//把BCD碼轉為十進制
- if(a!=0)
- {
- a--;
- }
- else
- {
- a=23;//限制設置小時不為0時減1,為0時回到23
- }
- timeset.hour=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(0,1,(timeset.hour>>4)+'0');//小時的十位
- LCD1602_writechar(1,1,(timeset.hour&0x0f)+'0');//小時的個位
- LCD1602_setcur(1,1);//光標保持原位
- break;
- case 4: //如果為當前為星期一時,回到星期天
- if(timeset.week!=1)
- {
- timeset.week--;
- }
- else
- {
- timeset.week=7;
- }
- LCD1602_writestr(11,0,week[timeset.week]);//顯示到液晶上;
- LCD1602_setcur(11,0);//光標保持原位
- break;
- case 5: a=BCDtoten(timeset.day);//把BCD碼轉為十進制
- if(a!=1)
- {
- a--;
- }
- else
- {
- a=31;
- }//限制設置日期不為1時減1,為0時回到31
- timeset.day=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(8,0,(timeset.day>>4)+'0');//日期的十位
- LCD1602_writechar(9,0,(timeset.day&0x0f)+'0');//日期的個位
- LCD1602_setcur(9,0);//光標保持原位
- break;
- case 6: a=BCDtoten(timeset.mon);//把BCD碼轉為十進制
- if(a!=1)
- {
- a--;
- }
- else
- {
- a=12;//限制設置月份不為1時減1,為0時回到12
- }
- timeset.mon=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(5,0,(timeset.mon>>4)+'0');//月份的十位
- LCD1602_writechar(6,0,(timeset.mon&0x0f)+'0');//月份的個位
- LCD1602_setcur(6,0);//光標保持原位
- break;
- case 0: a=BCDtoten(timeset.year);//把BCD碼轉為十進制
- if(a!=0)
- {
- a--;
- }
- else
- {
- a=99;//限制設置年不為0時減1,為0時回到99
- }
- timeset.year=tentoBCD(a);//把十進制轉為BCD碼
- LCD1602_writechar(2,0,(timeset.year>>4)+'0');//年的十位
- LCD1602_writechar(3,0,(timeset.year&0x0f)+'0');//年的個位
- LCD1602_setcur(3,0);//光標保持原位
- break;
- }
- }
- else if(system==setalarm)//設置鬧鐘
- {
- switch(flag)//檢查光標位置
- {
- case 1: if(alarmnum!=0)//換鬧鐘
- {
- alarmnum--;
- }
- else
- {
- alarmnum=4;
- }
- updatealarm();//刷新鬧鐘界面
- LCD1602_setcur(0,1);//光標保持原位
- break;
- case 2: if(clock[alarmnum].mon!=1)
- {
- clock[alarmnum].mon--;
- }
- else
- {
- clock[alarmnum].mon=12;//限制設置月份不超過12月,超過則回到1
- }
- LCD1602_writechar(2,1,(clock[alarmnum].mon/10)+'0');//月份十位
- LCD1602_writechar(3,1,(clock[alarmnum].mon%10)+'0');//月份個位
- LCD1602_setcur(3,1);//光標保持原位
- break;
- case 3: if(clock[alarmnum].day!=1)
- {
- clock[alarmnum].day--;
- }
- else
- {
- clock[alarmnum].day=31;//限制設置日期不超過31日,超過則回到1
- }
- LCD1602_writechar(5,1,(clock[alarmnum].day/10)+'0');//日期十位
- LCD1602_writechar(6,1,(clock[alarmnum].day%10)+'0');//日期個位
- LCD1602_setcur(6,1);//光標保持原位
- break;
- case 4: if(clock[alarmnum].hour!=0)
- {
- clock[alarmnum].hour--;
- }
- else
- {
- clock[alarmnum].hour=23;//限制設置小時不超過23時,超過則回到0
- }
- LCD1602_writechar(8,1,(clock[alarmnum].hour/10)+'0');//小時十位
- LCD1602_writechar(9,1,(clock[alarmnum].hour%10)+'0');//小時個位
- LCD1602_setcur(9,1);//光標保持原位
- break;
- case 5: if(clock[alarmnum].min!=0)
- {
- clock[alarmnum].min--;
- }
- else
- {
- clock[alarmnum].min=59;//限制設置分鐘不超過59分,超過則回到0
- }
- LCD1602_writechar(11,1,(clock[alarmnum].min/10)+'0');//分鐘十位
- LCD1602_writechar(12,1,(clock[alarmnum].min%10)+'0');//分鐘個位
- LCD1602_setcur(12,1);//光標保持原位
- break;
-
- case 6: if(clock[alarmnum].music!=0)
- {
- clock[alarmnum].music--;
- }
- else
- {
- clock[alarmnum].music=2;
- }
- LCD1602_writechar(1,0,clock[alarmnum].music+'0');
- LCD1602_setcur(1,0);//光標保持原位
- break;
-
- case 7: clock[alarmnum].alarmre=~clock[alarmnum].alarmre;
- LCD1602_writestr(3,0,clockzifu[clock[alarmnum].alarmre+2]);//顯示鬧鐘狀態
- LCD1602_setcur(3,0);//光標保持原位
- break;
- case 8: if (clock[alarmnum].week!=0)
- {
- clock[alarmnum].week--;
- }
- else
- {
- clock[alarmnum].week=7;
- }
- LCD1602_writestr(7,0,week[clock[alarmnum].week]);//顯示到液晶上;
- LCD1602_setcur(7,0);//光標保持原位
- break;
- case 0: clock[alarmnum].alarmon=~clock[alarmnum].alarmon;
- LCD1602_writestr(11,0,clockzifu[clock[alarmnum].alarmon]);//顯示鬧鐘狀態
- LCD1602_setcur(11,0);//光標保持原位
- break;
- }
- }
- }
- void alarmset()//鬧鐘函數
- {
- unsigned char i;
- for(i=0;i<5;i++)//掃描鬧鐘
- {
- //0就是重復 1不重復
- if(clock[i].alarmre)//不重復時
- {
- if((BCDtoten(timeset.hour)==clock[i].hour)&&(BCDtoten(timeset.min)==clock[i].min)&&(BCDtoten(timeset.mon)==clock[i].mon)&&(BCDtoten(timeset.day)==clock[i].day)&&(BCDtoten(timeset.sec))==0)//檢查鬧鐘的時間和日期是否跟目前的時鐘時間日期匹配
- {
- //0為打開 1為關閉
- if(!clock[i].alarmon)//檢查鬧鐘是否打開
- {
- LCD1602_clear();//清屏
- LCD1602_writestr(0,0,"Alarm");
- LCD1602_writechar(6,0,i+'0');
- LCD1602_writestr(8,0,"ring!");
- LCD1602_writestr(0,1,"Please press!");
- playmusic(clock[i].music);//播放鈴聲
- LCD1602_clear();//清屏
- }
- }
- }
- else//如果重復
- {
- if(clock[i].week)//有設置星期 則是每一個特定星期重復
- {
- if(clock[i].week==timeset.week)//看鬧鐘設置的星期是否為現在的星期
- {
- if((BCDtoten(timeset.hour)==clock[i].hour)&&(BCDtoten(timeset.min)==clock[i].min)&&(BCDtoten(timeset.sec))==0)//檢查鬧鐘的時間是否跟目前的時鐘時間匹配
- {
- if(!clock[i].alarmon)//檢查鬧鐘是否打開
- {
- LCD1602_clear();//清屏
- LCD1602_writestr(0,0,"Alarm");
- LCD1602_writechar(6,0,i+'0');
- LCD1602_writestr(8,0,"ring!");
- LCD1602_writestr(0,1,"Please press!");
- playmusic(clock[i].music);//播放音樂
- LCD1602_clear();//清屏
- }
- }
-
- }
-
- }
- else//沒有設置星期且在重復的情況下 則為每天都響
- {
- if((BCDtoten(timeset.hour)==clock[i].hour)&&(BCDtoten(timeset.min)==clock[i].min)&&(BCDtoten(timeset.sec))==0)//檢查鬧鐘的時間是否跟目前的時鐘時間匹配
- {
- if (!clock[i].alarmon)//檢查鬧鐘是否打開
- {
- LCD1602_clear();//清屏
- LCD1602_writestr(0,0,"Alarm");
- LCD1602_writechar(6,0,i+'0');
- LCD1602_writestr(8,0,"ring!");
- LCD1602_writestr(0,1,"Please press!");
- playmusic(clock[i].music);//播放音樂
- LCD1602_clear();//清屏
- }
- }
- }
- }
- }
- }
- void dingshiqi0()
- {
- TMOD|=0x01;
- TH0=0;
- TL0=0;
- TR0=0;
- ET0=1;
- PT0=1;
- EA=1;
- }
- void dingshiqi1()
- {
- TMOD|=0x10;
- EA=1;
- ET1=1;
- TR1=1;
- TH1=0xED;
- TL1=0xFE;
- }
- void timer0() interrupt 1
- {
- TH0=song[k][i]/256;
- TL0=song[k][i]%256;
- beep=~beep;
- }
- void timer1() interrupt 3
- {
- TH1=0xED;
- TL1=0xFE;
- key_scan();
- }
- void main()
- {
- dingshiqi0();//定時器0初始化
- dingshiqi1();//定時器1初始化
- LCD1602_init();//LCD1602初始化
- DS1302_init();//DS1302初始化
- while(1)
- {
- key_driver();
- alarmset();//鬧鐘設定函數
- if(system==normal)//當狀態為正常顯示時間時
- {
- updatetime();//刷新時間
- updatedate();//刷新日期
- DS18B20deal(DS18B20readtemp());//DS18B20數據處理函數 同時輸出溫度
- }
- else if(system==normal_12)//當狀態為顯示12小時制
- {
- updatetime_12();//刷新時間
- updatedate();//刷新日期
- }
- }
- }
復制代碼
所有資料51hei提供下載:
單片機考試:51單片機時鐘鬧鐘.zip
(143.44 KB, 下載次數: 391)
2019-1-30 22:44 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|