基于单片机的多功能电子钟设计Proteus仿真程序.docx

上传人:b****6 文档编号:5999399 上传时间:2023-01-02 格式:DOCX 页数:21 大小:46.13KB
下载 相关 举报
基于单片机的多功能电子钟设计Proteus仿真程序.docx_第1页
第1页 / 共21页
基于单片机的多功能电子钟设计Proteus仿真程序.docx_第2页
第2页 / 共21页
基于单片机的多功能电子钟设计Proteus仿真程序.docx_第3页
第3页 / 共21页
基于单片机的多功能电子钟设计Proteus仿真程序.docx_第4页
第4页 / 共21页
基于单片机的多功能电子钟设计Proteus仿真程序.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

基于单片机的多功能电子钟设计Proteus仿真程序.docx

《基于单片机的多功能电子钟设计Proteus仿真程序.docx》由会员分享,可在线阅读,更多相关《基于单片机的多功能电子钟设计Proteus仿真程序.docx(21页珍藏版)》请在冰豆网上搜索。

基于单片机的多功能电子钟设计Proteus仿真程序.docx

基于单片机的多功能电子钟设计Proteus仿真程序

#include

#defineucharunsignedchar

#defineuintunsignedint

#definelcddataP0

#definereadalarmsecond0xc7//定义从DS1302中读闹钟秒值的命令字节.

#definewritealarmsecond0xc6//定义往DS1302中写闹钟秒值的命令字节.

#definereadalarmminute0xc5//定义从DS1302中读闹钟分值的命令字节.

#definewritealarmminute0xc4//定义往DS1302中写闹钟分值的命令字节.

#definereadalarmhour0xc3//定义从DS1302中读闹钟小时值的命令字节.

#definewritealarmhour0xc2//定义往DS1302中写闹钟小时值的命令字节.

sbitlcdrs=P2^0;//LCD数据/命令选择端(H/L)

sbitlcdrw=P2^1;//LCD读/写选择端(H/L)

sbitlcden=P2^2;//LCD使能控制

sbitDQ=P3^4;

sbitbeep=P2^3;//蜂鸣器控制端

sbitkmenu=P3^0;//功能键

sbitkup=P3^1;//增大键

sbitkdown=P3^2;//减小键

sbitkalarm=P3^3;//闹钟查看键

sbitdsclk=P1^1;//ds1302的时钟信号端

sbitdsdata=P1^0;//ds1302的数据I/O端

sbitdsrst=P1^2;//ds1302的复位端

sbitACC7=ACC^7;//定义累加器的最高和最低位。

sbitACC0=ACC^0;

bitflagalarm,flagseta,flagset;//分别定义闹钟响标志位,闹钟设置标志位,

//和时间设置标志位.

ucharkmenunum,s,m,h;//功能键被按次数的计数器.

charsecond,minute,hour,year,month,day,week;

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>0;y--);

}

ds18b20_delay(ucharxus)//延时xus

{

while(xus--);

}

/**********************ds18b20***********************/

voidds18b20_init()//DS18B20初始化

{

ucharx=0;

DQ=1;

ds18b20_delay(8);

DQ=0;

ds18b20_delay(80);

DQ=1;

ds18b20_delay(14);

x=DQ;

ds18b20_delay(20);

}

voidwrite_onechar(uchardat)//写一字节

{

uchari;

for(i=8;i>0;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;

for(i=8;i>0;i--)

{

value>>=1;

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);

ds18b20_init();//初始化

write_onechar(0xcc);//跳过读序号列号的操作

write_onechar(0xbe);//读取温度寄存器等(共可读9个寄存器)前两个就是温度

ds18b20_delay(150);

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;

delay(3);

lcden=0;

}

voidwritedata(uchardat)//液晶写数据函数。

{

lcden=0;

lcdrw=0;

lcdrs=1;

lcddata=dat;

delay(3);

lcden=1;

delay(3);

lcden=0;

}

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为日。

charshi,ge;

shi=dat/10;

ge=dat%10;

writecom(0x80+add);

writedata(0x30+shi);

writedata(0x30+ge);

}

voidwriteweek(charweek)//液晶星期几显示函数。

{

writecom(0x80+12);

switch(week)

{

case1:

writedata('M');delay(5);

writedata('O');delay(5);

writedata('N');

break;

case2:

writedata('T');delay(5);

writedata('U');delay(5);

writedata('E');

break;

case3:

writedata('W');delay(5);

writedata('E');delay(5);

writedata('D');

break;

case4:

writedata('T');delay(5);

writedata('H');delay(5);

writedata('U');

break;

case5:

writedata('F');delay(5);

writedata('R');delay(5);

writedata('I');

break;

case6:

writedata('S');delay(5);

writedata('A');delay(5);

writedata('T');

break;

case7:

writedata('S');delay(5);

writedata('U');delay(5);

writedata('N');

break;

}

}

voidkeyscan()//键盘扫描函数。

{

uchari;

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);//分闪烁。

break;

case3:

writecom(0x80+0x40+1);//时闪烁。

break;

case4:

writecom(0x80+12);//星期闪烁.

break;

case5:

writecom(0x80+9);//日闪烁.

break;

case6:

writecom(0x80+6);//月闪烁.

break;

case7:

writecom(0x80+3);//年闪烁.

break;

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);/*禁止写操作*/

break;

}

}

}

if(kmenunum!

=0)//只有当功能键按下时,才检测增大,减小键.

{

if(kup==0)

{

delay

(2);

if(kup==0)

{

while(!

kup);

di();

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);

break;

case3:

hour++;

if(hour==24)

hour=0;

writetime(1,hour);

writecom(0x80+0x40+1);

break;

case4:

week++;

if(week==8)

week=1;

writeweek(week);

writecom(0x80+12);

break;

case5:

day++;

if(day==32)

day=1;

writenyr(9,day);

writecom(0x80+9);

break;

case6:

month++;

if(month==13)

month=1;

writenyr(6,month);

writecom(0x80+6);

break;

case7:

year++;

if(year==100)

year=0;

writenyr(3,year);

writecom(0x80+3);

break;

}

}

}

if(kdown==0)

{

delay

(2);

if(kdown==0)

{

while(!

kdown);

di();

switch(kmenunum)//根据功能键被按次数调节相应数值.

{

case1:

second--;

if(second==-1)

second=59;

writetime(7,second);

writecom(0x80+0x40+7);

break;

case2:

minute--;

if(minute==-1)

minute=59;

writetime(4,minute);

writecom(0x80+0x40+4);

break;

case3:

hour--;

if(hour==-1)

hour=23;

writetime(1,hour);

writecom(0x80+0x40+1);

break;

case4:

week--;

if(week==0)

week=7;

writeweek(week);

writecom(0x80+12);

break;

case5:

day--;

if(day==0)

day=31;

writenyr(9,day);

writecom(0x80+9);

break;

case6:

month--;

if(month==0)

month=12;

writenyr(6,month);

writecom(0x80+6);

break;

case7:

year--;

if(year==-1)

year=99;

writenyr(3,year);

writecom(0x80+3);

break;

}

}

}

}

if(kalarm==0)//检测闹钟调节键是否按下,此条if语句与if(kmenunum!

=0)

{//在同一个层次。

delay

(2);

if(kalarm==0)

{

flagseta=~flagseta;

while(!

kalarm);

di();

if(flagseta==0)//此时,退出闹钟设置,保存各相关数值。

{

flagset=0;//清除时间设置标志,在if(kalarm==0)这个if语句

writecom(0x80+0x40);//中,不用flagset=1这条语句来设置

//flagset标志位,因为,如果进行了闹钟时间的设置

//,就会执行前面if(kmenunum==0)语句中的flagset=1这条语句。

writedata('');//清除液晶上的“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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1