基于单片机的多功能电子钟设计Proteus仿真程序Word格式.docx
《基于单片机的多功能电子钟设计Proteus仿真程序Word格式.docx》由会员分享,可在线阅读,更多相关《基于单片机的多功能电子钟设计Proteus仿真程序Word格式.docx(21页珍藏版)》请在冰豆网上搜索。
ucharinittime[7]={0x00,0x00,0x16,0x01,0x05,0x07,0x11};
//初始化后设置为:
//11年5月1日星期日,16点0分0秒,
//从左往右的数据依次是,秒,分,时,日,月,星期,年。
ucharcodet1[]="
20--"
;
//液晶固定显示部分。
ucharcodet2[]="
:
"
ucharcodet3[]="
CLOCKALARM:
"
//各函数声明.
voiddelay(uintz);
//毫秒级延时函数。
voiddi();
//蜂鸣器发声函数。
voidwritecom(ucharcom);
//液晶写命令函数。
voidwritedata(uchardat);
//液晶写数据函数。
voidwritetime(ucharadd,chardat);
//液晶刷新时分秒。
voidwritenyr(ucharadd,chardat);
//液晶刷新日期。
voidwriteweek(charweek);
//液晶星期几显示函数。
voidkeyscan();
//键盘扫描函数。
voiddswritebyte(uchard);
//往DS1302写入一个字节。
uchardsreadbyte();
//从DS1302读出一个字节。
voiddswrite(ucharadd,uchardat);
//向DS1302的指定地址写入一个字节。
uchardsread(ucharadd);
//从DS1302的指定地址读出一个字节.
voidinit1302time(uchar*pClock);
//DS1302时间初始化函数.
voidinit();
//初始化函数。
ds18b20_delay(ucharxus);
//延时xus
voidwrite_onechar(uchardat);
//向18B20写一字节
ucharread_onechar();
//从18B20读一字节
uintread_wendu();
//DS18B20读温度
voidwendu_desplay(uintdat);
//温度值送液晶显示函数
voiddelay(uintz)//毫秒级延时函数。
{
uintx,y;
for(x=z;
x>
0;
x--)
for(y=110;
y>
y--);
}
ds18b20_delay(ucharxus)//延时xus
while(xus--);
/**********************ds18b20***********************/
voidds18b20_init()//DS18B20初始化
ucharx=0;
DQ=1;
ds18b20_delay(8);
DQ=0;
ds18b20_delay(80);
ds18b20_delay(14);
x=DQ;
ds18b20_delay(20);
voidwrite_onechar(uchardat)//写一字节
uchari;
for(i=8;
i>
i--)
{
DQ=0;
if(dat&
0x01==0x01)
DQ=1;
else
DQ=0;
ds18b20_delay(5);
DQ=1;
ds18b20_delay
(1);
dat>
>
=1;
}
ucharread_onechar()//读一字节
ucharvalue=0,i;
{
value>
DQ=0;
ds18b20_delay
(1);
DQ=1;
if(DQ==1)
value|=0x80;
else
value&
=0x7f;
ds18b20_delay(4);
}
returnvalue;
uintread_wendu()//DS18B20读温度
uchara=0,b=0;
uintwen=0x0000;
ds18b20_init();
//初始化
write_onechar(0xcc);
//跳过读序号列号的操作
write_onechar(0x44);
//启动温度转换
ds18b20_delay(150);
//跳过读序号列号的操作
write_onechar(0xbe);
//读取温度寄存器等(共可读9个寄存器)前两个就是温度
b=read_onechar();
//读取温度值低位
a=read_onechar();
//读取温度值高位
wen=a;
wen=(wen<
<
8)|b;
returnwen;
voidwendu_desplay(uintdat)//温度转换后送显示
floattemp;
unsignedchartemp_shi,temp_ge,temp_shu;
temp=dat*0.625;
//dat*0.0625*10
temp_shi=temp/100;
//取十位temp除不用定义类型
temp_ge=((uint)temp)%100/10;
//取个位temp求模要定义类型,为16位,故定义uint
temp_shu=((uint)temp)%100%10;
//取小数
writecom(0x80+0x40+10);
//送显示
writedata(0x30+temp_shi);
writedata(0x30+temp_ge);
writedata(0x2e);
writedata(0x30+temp_shu);
writedata(0xdf);
//温度符号
writedata(0x43);
voiddi()//蜂鸣器发声函数。
beep=0;
delay(100);
beep=1;
voidwritecom(ucharcom)//液晶写命令函数。
lcden=0;
lcdrw=0;
lcdrs=0;
lcddata=com;
delay(3);
lcden=1;
voidwritedata(uchardat)//液晶写数据函数。
lcdrs=1;
lcddata=dat;
voidwritetime(ucharadd,chardat)//液晶刷新时分秒。
{//0为时的开始位置,3为分,6为秒。
charshi,ge;
shi=dat/10;
ge=dat%10;
writecom(0x80+0x40+add);
writedata(0x30+shi);
writedata(0x30+ge);
voidwritenyr(ucharadd,chardat)//液晶刷新日期。
{//2为年,5为月,8为日。
writecom(0x80+add);
voidwriteweek(charweek)//液晶星期几显示函数。
writecom(0x80+12);
switch(week)
case1:
writedata('
M'
);
delay(5);
writedata('
O'
N'
break;
case2:
T'
U'
E'
case3:
W'
D'
case4:
H'
case5:
F'
R'
I'
case6:
S'
A'
case7:
voidkeyscan()//键盘扫描函数。
if(flagalarm==1)//如果闹钟在响,任意键停止闹钟响。
if((kmenu==0)||(kup==0)||(kdown==0)||(kalarm==0))
delay(4);
if((kmenu==0)||(kup==0)||(kdown==0)||(kalarm==0))
{
while(!
(kmenu&
&
kup&
kdown&
kalarm));
di();
flagalarm=0;
//清除闹钟标志。
}
}
if(kmenu==0)//检测功能键。
delay(4);
if(kmenu==0)
kmenunum++;
//记录功能键按下次数。
if(flagseta==1)//检测是否在进行闹钟设置。
if(kmenunum==4)
kmenunum=1;
//因为进行闹钟设置时,只调节
//时分秒,所以,kmenunum只能等于1,2,3。
flagset=1;
//设置标志位,表示在进行各种时间设置。
while(!
kmenu);
di();
switch(kmenunum)//定位光标闪烁点。
case1:
writecom(0x80+0x40+7);
//秒闪烁。
writecom(0x0f);
//开光标闪烁。
break;
case2:
writecom(0x80+0x40+4);
//分闪烁。
case3:
writecom(0x80+0x40+1);
//时闪烁。
case4:
//星期闪烁.
case5:
writecom(0x80+9);
//日闪烁.
case6:
writecom(0x80+6);
//月闪烁.
case7:
writecom(0x80+3);
//年闪烁.
case8:
kmenunum=0;
writecom(0x0c);
//取消光标闪烁。
flagset=0;
//取消时间调节标志。
dswrite(0x8e,0x00);
/*允许写操作*/
dswrite(0x80,second/10*16+second%10);
//退出时间设置功能时,往DS1302
dswrite(0x82,minute/10*16+minute%10);
//中保存所有时间变量的值。
dswrite(0x84,hour/10*16+hour%10);
dswrite(0x8a,week/10*16+week%10);
dswrite(0x86,day/10*16+day%10);
dswrite(0x88,month/10*16+month%10);
dswrite(0x8c,year/10*16+year%10);
dswrite(0x8e,0x80);
/*禁止写操作*/
}
if(kmenunum!
=0)//只有当功能键按下时,才检测增大,减小键.
if(kup==0)
delay
(2);
if(kup==0)
kup);
switch(kmenunum)//根据功能键被按下的次数,调节相应数值。
{
case1:
second++;
if(second==60)
second=0;
writetime(7,second);
writecom(0x80+0x40+7);
//因为,上面送液晶显示
break;
//一次,光标后移一位,所以要将光标复位.
case2:
minute++;
if(minute==60)
minute=0;
writetime(4,minute);
writecom(0x80+0x40+4);
case3:
hour++;
if(hour==24)
hour=0;
writetime(1,hour);
writecom(0x80+0x40+1);
case4:
week++;
if(week==8)
week=1;
writeweek(week);
writecom(0x80+12);
case5:
day++;
if(day==32)
day=1;
writenyr(9,day);
writecom(0x80+9);
case6:
month++;
if(month==13)
month=1;
writenyr(6,month);
writecom(0x80+6);
case7:
year++;
if(year==100)
year=0;
writenyr(3,year);
writecom(0x80+3);
}
if(kdown==0)
if(kdown==0)
kdown);
switch(kmenunum)//根据功能键被按次数调节相应数值.
second--;
if(second==-1)
second=59;
minute--;
if(minute==-1)
minute=59;
hour--;
if(hour==-1)
hour=23;
week--;
if(week==0)
week=7;
day--;
if(day==0)
day=31;
month--;
if(month==0)
month=12;
year--;
if(year==-1)
year=99;
}
}
if(kalarm==0)//检测闹钟调节键是否按下,此条if语句与if(kmenunum!
=0)
{//在同一个层次。
delay
(2);
if(kalarm==0)
flagseta=~flagseta;
kalarm);
if(flagseta==0)//此时,退出闹钟设置,保存各相关数值。
flagset=0;
//清除时间设置标志,在if(kalarm==0)这个if语句
writecom(0x80+0x40);
//中,不用flagset=1这条语句来设置
//flagset标志位,因为,如果进行了闹钟时间的设置
//,就会执行前面if(kmenunum==0)语句中的flagset=1这条语句。
'
//清除液晶上的“Ri”闹钟调节标志。
//writedata('
'
/*for(i=0;
i<
13;
i++)
writedata(t3[i]);
}*/
writecom(0x0c);
dswrite(0x8e,0x00);
dswrite(writealarmsecond,second/10*16+second%10);
//往DS1302中保存闹钟的时分秒值。
dswrite(writealarmminute,minute/10*16+minute%10);
dswrite(writealarmhour,hour/10*16+hour%10);
dswrite(0x8e,0x80);
else//进入闹钟设置。
s=dsread(readalarmsecond)/16*10+dsread(readalarmsecond)%16;
//读取DS1302中闹钟的原始时间,转化为十进制数存进s,m,h保存,用以后面判断闹钟时间是否到达。
m=dsread(readalarmminute)/16*10+dsread(re