本贴针对学完单片机并且有读懂代码的非新手同学。本人目前放寒假,这个是本人在上个学期的单片机课上要求做的综合实验,现在重新修改了下增加了菜单目前测试毫无问题可以完美使用。有志向做闹钟的同学可以参考一下,原码上由本人写的大量注释可以方便看懂。
使用了LCD1602、DS1302、DS18B20用来测试温度、内部含闹钟系统但本人没有做EEPROM有需要的同学可以自行添加。
单片机源程序如下:
#include #include #include #include #include #include #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]='