DS1302+DS18B20+LCD1602
a1. main.c
#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();//刷新日期
}
}
}
a2. key.h
#ifndef _KEY_H
#define _KEY_H
#include<reg52.h>
#include<intrins.h>
//键盘位定义
sbit key1=P1^0;
sbit key2=P1^1;
sbit key3=P1^2;
sbit key4=P1^3;
extern void key_scan();//更新按键状态
extern void key_driver();//按键动作
extern void key_action(unsigned char keycode);//按键状态检测
extern void delayms(unsigned int a);//延时
#endif
b2. key.c
#include<key.h>
extern unsigned char start;
unsigned int keysta[4]={1};//设置按键默认初始状态 初始状态为没用被按下
unsigned int keygroup[4]={0x01,0x02,0x04,0x08};//0000 0001 0000 0010 0000 0010 0000 1000 定义四个按键哪个被按下
unsigned int keybackup[4]={1};//设置按键备份初始化
void delayms(unsigned int a)//延时1ms
{
unsigned char i;
for(;a>0;a--)
for(i=0;i<144;i++);
}
void key_scan()//更新按键状态
{
unsigned char i;
for(i=0;i<4;i++)
{
if(!(P1&keygroup[i]))//如果某个按键被按下
{
delayms(5);//延时5ms消抖
if(!(P1&keygroup[i]))//重新检测是否真有某个按键按下
{
keysta[i]=0;//设置按键的状态是被按下
}
}else keysta[i]=1;//按键没有被按下
}
}
void key_action(unsigned char keycode)//按键动作
{ start=0;
switch(keycode)
{
case 0:anjian1();break;//第一个按键是切换界面
case 1:zengjia();break;//S3按键功能函数,数据加
case 2:jianxiao();break;//S4按键功能函数,数据减
case 3:anjian4();break;//在相应的界面中进入更改界面
}
}
void key_driver()//检测按键状态
{
unsigned char i;
for(i=0;i<4;i++)//扫描四个按键
{
if(keybackup[i]!=keysta[i])//如果四个按键其中有个跟原来的状态不一样
{
if(keybackup[i])
{
key_action(i);//按键作出其对应的动作
}
keybackup[i]=keysta[i];//让当前的按键状态覆盖掉原来的按键状态
}
}
}
a3. LCD1602.h
//1602液晶定义
#ifndef _LCD1602_H__
#define _LCD1602_H_
#include<reg52.h>
#include<intrins.h>
sbit LCD1602_RW=P2^5;//0-向LCD写入指令或数据 1-读取信息
sbit LCD1602_RS=P2^6;//选择指令还是数据 0-指令 1-数据
sbit LCD1602_EN=P2^7;//使能信号,下降沿时执行指令
extern void LCD1602_readok();//等待LCD1602空闲
extern void LCD1602_writecom(unsigned char cmd);//向LCD1602写入命令
extern void LCD1602_writedat(unsigned char dat);//向LCD1602写入数据
extern void LCD1602_setcur(unsigned int x,unsigned int y);//坐标定义
extern void LCD1602_clear();//清屏函数
extern void LCD1602_writechar(unsigned int x,unsigned int y,unsigned char i);//打印字符
extern void LCD1602_writestr(unsigned int x,unsigned int y,char *str);//打印字符串
extern void LCD1602_openguangbiao();//打开光标
extern void LCD1602_closeguangbiao();//关闭光标
extern void LCD1602_init();//LCD1602初始化
#endif
b3. LCD1602.c
#include <LCD1602.h>
void LCD1602_readok()//等待LCD1602空闲
{
unsigned char busy;
P0=0XFF;//初始化
LCD1602_RS=0;
LCD1602_RW=1;
do
{
LCD1602_EN=1;
busy=P0;
LCD1602_EN=0;
}while(busy&0X80);
}
void LCD1602_writecom(unsigned char cmd)//向LCD1602写入命令
{
LCD1602_readok();
LCD1602_RS=0;
LCD1602_RW=0;
P0=cmd;
LCD1602_EN=1;
LCD1602_EN=0;
}
void LCD1602_writedat(unsigned char dat)//向LCD1602写入数据
{
LCD1602_readok();
LCD1602_RS=1;
LCD1602_RW=0;
P0=dat;
LCD1602_EN=1;
LCD1602_EN=0;
}
void LCD1602_setcur(unsigned int x,unsigned int y)//坐标定位
{
if(y) x|=0x40;
x|=0x80;
LCD1602_writecom(x);
}
void LCD1602_clear()//清屏函数
{
LCD1602_writecom(0x01);
}
void LCD1602_writechar(unsigned int x,unsigned int y,unsigned char i)//打印字符
{
LCD1602_setcur(x,y);
LCD1602_writedat(i);
}
void LCD1602_writestr(unsigned int x,unsigned int y,char *str)//打印字符串
{
LCD1602_setcur(x,y);
while(*str!='\0')
LCD1602_writedat(*str++);
}
void LCD1602_openguangbiao()//打开光标
{
LCD1602_writecom(0x0F);//屏幕开、光标开、闪烁关
}
void LCD1602_closeguangbiao()//关闭光标
{
LCD1602_writecom(0x0C);//屏幕开、光标关、闪烁关
}
void LCD1602_init()//LCD1602初始化
{
LCD1602_writecom(0x38);//显示模式 8位、双行、5*7模式
LCD1602_writecom(0x0C);//开显示 屏幕开、光标关、闪烁关
LCD1602_writecom(0x06);//地址自增 光标右移
LCD1602_writecom(0x01);//清屏幕
// write_cmd(0x80);//设置数据指针
}
a4. DS1302.h#ifndef _DS1302_H
#define _DS1302_H
#include<reg52.h>
#include<intrins.h>
sbit TSCLK=P3^6;//串行时钟
sbit TIO =P3^4;//数据输入/输出管脚
sbit TCE =P3^5;//复位脚
struct Time{
unsigned int year; //年
unsigned char mon; //月
unsigned char day; //日
unsigned char hour; //时
unsigned char min; //分
unsigned char sec; //秒
unsigned char week; //星期
};
struct alarmtime{
unsigned char mon; //月
unsigned char day; //日
unsigned char hour; //时
unsigned char min; //分
unsigned char week; //星期
unsigned char alarmre:1;//闹钟重复
unsigned char alarmon:1;//闹钟开启
unsigned char music:2;//铃声
};
extern void DS1302_setwp();//打开写保护寄存器
extern void DS1302_clearwp();//关闭写保护寄存器
extern void DS1302_writebyte(unsigned char cmd);//向DS1302写入一个字节
extern unsigned char DS1302_readbyte();//向DS1302读取一个字节
extern void DS1302_writedata(unsigned char cmd,unsigned char DAT);//向DS1302写入数据
extern void DS1302_burstread();//DS1302在突发模式下的读取
extern void DS1302_burstwrite(unsigned char *dat);//DS1302在突发模式下的写入
extern void DS1302_gettime(struct Time *time);//DS1302读取时间
extern void DS1302_settime(struct Time *time);//对DS1302设置当前时间
extern void DS1302_init();//初始化DS1302中的寄存器
#endif
b4. DS1302.c
#include<DS1302.h>
void DS1302_setwp()//打开写保护寄存器
{
DS1302_writedata(0x8e,0x80);//WP在写保护寄存器的第七位=1时写保护
TCE=0;
TSCLK=0;
}
void DS1302_clearwp()//关闭写保护寄存器
{
DS1302_writedata(0x8e,0);//0x8e是写保护寄存器的地址
}
void DS1302_writebyte(unsigned char cmd)//向DS1302写入一个字节
{
unsigned char i;
for(i=0;i<8;i++)
{
TSCLK=0;
if(cmd&0x01)
TIO=1;
else
TIO=0;
TSCLK=1;
cmd>>=1;
}
}
unsigned char DS1302_readbyte()//向DS1302读取一个字节
{
unsigned char DAT,i;
for(i=0;i<8;i++)
{
DAT>>=1;
TSCLK=0;
if(TIO)
DAT|=0x80;
TSCLK=1;
}
return DAT;
}
void DS1302_writedata(unsigned char cmd,unsigned char DAT)//向DS1302写入数据
{
TCE=0;
TSCLK=0;
TCE=1;
DS1302_writebyte(cmd);
DS1302_writebyte(DAT);
TCE=0;
}
void DS1302_burstread(unsigned char *dat)//DS1302在突发模式下的读取
{
unsigned int i;
DS1302_clearwp();//关闭写保护
TCE=0;
TSCLK=0;
TCE=1;
DS1302_writebyte(0xbf);//进入时钟突发模式 读最后一个字节为1
for(i=0;i<8;i++)//写入8个字节的时钟初始值
{
dat[i]=DS1302_readbyte();//在突发模式下可以连续读数据
}
DS1302_setwp();//开启写保护
}
void DS1302_burstwrite(unsigned char *dat)//DS1302在突发模式下的写入
{
unsigned int i;
DS1302_clearwp();//关闭写保护
TCE=0;
TSCLK=0;
TCE=1;
DS1302_writebyte(0xbe);//进入时钟突发模式 写最后一个字节为0
for(i=0;i<8;i++)//写入8个字节的时钟初始值
{
DS1302_writebyte(dat[i]);//在突发模式下可以连续写数据
}
DS1302_setwp();//开启写保护
}
void DS1302_gettime(struct Time *time)//DS1302读取时间
{
unsigned char buf[8];
DS1302_burstread(buf);//在突发模式下连续读数据
time->year=buf[6]+0x2000;//BIT6 寄存器6 年,因为DS1302只能是0-99如显示2012年则通过2000这种方法显示年的千位和百位
time->mon=buf[4];//BIT4 寄存器4
time->day=buf[3];//BIT3 寄存器3
time->hour=buf[2];//BIT2 寄存器2
time->min=buf[1];//BIT1 寄存器1
time->sec=buf[0];//BIT0 寄存器0
time->week=buf[5];//BIT5 寄存器5
}
void DS1302_settime(struct Time *time)//对DS1302设置当前时间
{
unsigned char buf[8];
buf[7]=0;//寄存器7:最高位一个写保护位,如果这一位是 1,那么是禁止给任何其它寄存器或者那31个字节的RAM写数据的。因此在写数据之前,这一位必须先写成 0。
buf[6]=time->year;
buf[5]=time->week;
buf[4]=time->mon;
buf[3]=time->day;
buf[2]=time->hour;
buf[1]=time->min;
buf[0]=time->sec;
DS1302_burstwrite(buf);//在突发模式下可以连续写数据
}
void DS1302_init()//初始化DS1302中的寄存器
{
struct Time code times={0x18,0x01,0x16,0x14,0x30,0x55,0x03};//一开始初始化的时间 年 月 日 时 分 秒
DS1302_settime(×);//设置DS1302为默认的初始时间
}
a5. music.h
#ifndef _music_H__
#define _music_H__
#include<reg52.h>
#include<intrins.h>
//C 大调音频定义
#define L1 0xF88C//装进定时器初值里面
#define L2 0xF95B
#define L3 0xFA15
#define L4 0xFA67
#define L5 0xFB04
#define L6 0xFB90
#define L7 0xFC0C
#define M1 0xFC44
#define M2 0xFCAC
#define M3 0xFD09
#define M4 0xFD34
#define M5 0xFD82
#define M6 0xFDC8
#define M7 0xFE06
#define H1 0xFE22
#define H2 0xFE56
#define H3 0xFE85
#define H4 0xFE88
#define H5 0xFEC1
#define H6 0xFEE4
#define H7 0xFF02
sbit beep=P1^5;//蜂鸣器
extern void delay_ms();
extern void playmusic(unsigned char count);//音乐播放函数
#endif
b5. music.c
#include<MUSIC.h>
#include<key.h>
unsigned char i;
unsigned char k,start;
unsigned int code song[3][300]={
//LOSER
{
H3,4,M5,4,H3,2,H3,2,M5,4,H3,2,H2,2,H3,2,H3,2,H4,2,H3,2,H2,4,H1,4,M3,4,H1,2,H1,2,M3,4,H4,2,H4,2,H3,2,H3,2,H2,4,H1,2,H2,2,H3,4,M5,4,H3,2,H3,2,M5,4,H2,2,H2,2,H3,2,H3,2,H4,2,
H3,2,H2,4,H1,4,H2,4,M7,2,M7,2,H1,4,H4,2,H4,2,H3,2,H2,2,H2,4,H1,2,H2,2,H3,4,M5,4,H3,2,H3,2,M5,4,H3,2,H2,2,H3,2,H3,2,H4,2,H3,2,H2,4,H1,4,M3,4,H1,2,H1,2,M3,4,H4,2,H4,2,H3,2,H3,2,H2,4,H1,2,H2,2,H3,4,M5,4,H3,2,H3,2,M5,4,H2,2,H2,2,H3,2,H3,2,H4,2,
H3,2,H2,4,H1,4,H2,4,M7,2,M7,2,H1,4,H4,2,H4,2,H3,2,H2,2,H2,4,H1,2,H2,2,H1,4,H2,4,H3,4,0xff
},
{
L5,16,M1,8,M3,12,M1,4,M2,8,M1,24,M1,24,L5,16,M1,8,
M3,12,M1,4,M3,8,M2,24,M2,24,L6,16,M2,8,
M4,12,M3,4,M4,8,M2,24,M2,24,M5,16,M2,8,L7,12,L5,4,M2,8,
M1,24,M1,24,M2,16,M2,8,M2,16,M1,8,
M2,16,M3,8,M4,24,M2,16,M2,8,M2,8,M1,8,M2,8,
M3,24,M3,24,M2,16,M2,8,M2,16,M1,8,
M2,16,M3,8,M4,24,L7,16,L5,8,M4,12,M3,4,M2,8,
M1,24,M1,24,0xff
},
{
M7,8,M6,8,M6,6,M6,12,M1,8,M6,8,M7,12,M6,4,M6,4,M6,4,M6,8,M5,4,M5,5,M5,5,M5,4,M6,8,M7,8,M6,8,M6,6,M6,12,M1,8,M6,8,M7,12,M6,4,M6,4,M6,4,M7,8,M6,8,M6,6,M6,12,M1,8,M6,8,M7,12,M6,4,M6,4,M6,4,
M7,8,M6,8,M6,6,M6,12,M1,8,M6,8,M7,12,M6,4,M6,4,M6,4,M6,8,M5,4,M5,5,M5,5,M5,4,M6,8,M7,8,M6,8,M6,6,M6,12,M1,8,M6,8,M7,12,M6,4,M6,4,M6,4,M7,8,M6,8,M6,6,M6,12,M1,8,M6,8,M7,12,M6,4,M6,4,M6,4,0xff
}
};
void delay_ms()//节拍控制+按键退出
{
unsigned int i=300;
while(i--)
{
key_scan();//更新按键状态
key_driver();//检测按键状态
}
}
void playmusic(unsigned char count)//count是曲目编号
{
unsigned char j,playcount=0;
TR0=0;
beep=0;
k=count;
TR0=1;
while(start&&playcount!=1)
{
while(song[k][i]!=0xff&&start) //遍历整首歌
{
TH0=song[k][i]/256;
TL0=song[k][i]%256;
for(j=0;j<song[k][i+1];j++) //节拍延时
{
delay_ms();//控制节拍
}
i+=2;
}
playcount++;
i=0; //播放完一首要清0
}
playcount=0;
beep=0;
start=1;
TR0=0;
}
a6. DS18B20.h
#ifndef _DS18B20_H__
#define _DS18B20_H__
#include<reg52.h>
sbit DQ=P3^7;//单线运用的数据输入/输出引脚
extern void Delay_ms(unsigned int y);
extern unsigned char DS18B20init();//DS18B20初始化函数
extern void DS18B20writebyte(unsigned char dat);//DS18B20写字节函数
extern unsigned char DS18B20readbyte();//DS18B20读字节函数
extern void DS18B20changetemp();//让18B20开始转换温度函数
extern int DS18B20readtemp();//读取温度函数
#endif
b6. DS18B20.h
#include<DS18B20.H>
//在单总线上面要精确的延时时间,误差很大单总线通信会失败
void Delay_ms(unsigned int y)//参数改变延时时间
{
unsigned int x;
for(;y>0;y--)
{
for(x=110;x>0;x--);//1ms的延时
}
}
//DS18B20测温的话首先要为DS18B20初始化
unsigned char DS18B20init()//DS18B20初始化函数
{
unsigned char i=0;
DQ=0;//将总线延时480到960微秒
i = 70;
while(i--);//延时642us
DQ=1;//然后拉高总线,如果DS18B20初始化成功会将在15us~60us产生一个由DS18B20所返回的低电平“0”,表面DS18B20存在
i=0;
while(DQ)//判断总线电平,低电平表明DS18B20存在退出循环
{
Delay_ms(1);//延时1ms
i++;
if(i>5)//等待5ms的超时判断
{
return 0;//初始化失败
}
}
return 1;//返回1的话表示DS18B20存在初始化成功
}
//对DS18B20进行写字节或读字节
void DS18B20writebyte(unsigned char dat)//DS18B20写字节函数 按地位到高位的顺序发送数据(一次只发送一位)
{
unsigned int i,j;
for(i=0;i<8;i++)//一个字节有8位数据
{
DQ=0;//将总线拉低低电平
j++;
DQ=dat&0x01;//写入一个数据,从最低位开始 最低位是1还是0
j=6;//延时十几微妙
while(j--);//延时68us,延时时间最少60us
DQ=1;//拉高总线,至少1us给总线恢复时间才能接着写入第二个数值
dat>>=1;//每次只发送一位所以要进行移位 右移
}
}
unsigned char DS18B20readbyte()//DS18B20读字节函数
{
unsigned char byte,bi;//bi用来保存每一位的数据,byte用来返回出去
unsigned int i,j;
for(i=0;i<8;i++)//循环8次 一次读一位
{
DQ=0;//将总线拉低
j++;//延时大于1us
DQ=1;//总线拉高
j++;
j++;//延时6us等待数据稳定
bi=DQ;//读取数据得到状态位,先从最低位开始读取
byte=(byte>>1)|(bi<<7);//将byte右移一位(循环7次),然后获取与上右移7位后的bi,注意移动之后移掉那位补0。
j=4;
while(j--);//读取完之后等待48us再接着读取下一个数
}//重复步骤直到读完一个字节
return byte;
}
void DS18B20changetemp()//让18b20开始转换温度函数
{
DS18B20init();//先让DS18B20初始化
Delay_ms(1);//延时1ms等待传感器稳定
DS18B20writebyte(0xcc);//跳过ROM操作命令,功能是忽略64位ROM地址,直接向DS18B20发温度变换命令,适用于单机工作(一个温度传感器进行检测)
DS18B20writebyte(0x44);//温度转换命令,功能是启动DS18B20进行温度转换,默认使用12位进行转换,12位转换时最长为750ms(9位为93.75ms),结果存入内部9字节RAM中
//Delay_ms(100);//等待转换成功,而如果你是一直刷着的话,就不用这个延时了
}
int DS18B20readtemp()//读取温度函数
{
int temp=0;
unsigned char tmh,tml;//温度的低字节和高字节数据
EA=0;
DS18B20changetemp();//先写入转换命令
DS18B20init();
Delay_ms(1);
DS18B20writebyte(0xcc);//跳过ROM操作命令
DS18B20writebyte(0xbe);//发送读取温度命令,功能是读取内部RAM中9字节的内容
tml=DS18B20readbyte();//读取温度值共16位,先读低字节
tmh=DS18B20readbyte();//再读高字节
temp=tmh;
temp<<=8;
temp|=tml;
EA=1;
return temp;
}