本贴针对学完单片机并且有读懂代码的非新手同学。本人目前放寒假,这个是本人在上个学期的单片机课上要求做的综合实验,现在重新修改了下增加了菜单目前测试毫无问题可以完美使用。有志向做闹钟的同学可以参考一下,原码上由本人写的大量注释可以方便看懂。
使用了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)
|