基于51单片机的万年历闹钟秒表设计.docx
《基于51单片机的万年历闹钟秒表设计.docx》由会员分享,可在线阅读,更多相关《基于51单片机的万年历闹钟秒表设计.docx(41页珍藏版)》请在冰豆网上搜索。
基于51单片机的万年历闹钟秒表设计
基于51单片机的万年历,闹钟,秒表设计
有关接线图
完整的程序代码
#include
#defineucharunsignedchar
#defineuintunsignedint
ucharcodetable[]={"20年月日"};
ucharcodetable1[]={":
:
"};
ucharcodetable5[]={"QICHUANGLA"};
voidLCD_WRITE_COM(ucharcom);
voidLCD_WRITE_DAT(uchardat);
voidLCD_CSH();
voidLCD_GD();
voidLCD_CLR();
voidDELAYUS(uchari);
voidDELAY(uintt);
voidDELAY_A(uintn);
voidDISP_TIME();
voidDISL1();
voidDISL3();
voidDS1302_CSH();
voidDS1302_WRITE(ucharaddr,uchardat);
voidWRITE_BTY(uchardat);
voidDSweek(ucharnum);
voidDS1820RST();
voidDS1820WR(uchardat);
voidKEYSCAN();
voidKEYMOVE();
voidTIME_UP();
voidTIME_DOWN();
ucharDS1820RD();
ucharREAD_T();
ucharDS1302_READ(ucharaddr);
ucharREAD_BTY();
sbitIO=P3^5;
sbitRST=P1^7;
sbitSCLK=P1^6;
sbitFMQ=P2^4;
sbitDQ=P2^3;//DS18B20输出口
sbitRS=P2^5;//寄存器选择信号
sbitRW=P2^6;//读写控制信号线
sbitLCDEN=P2^7;//使能信号线
sbitS1=P1^0;
sbitS2=P1^1;
sbitS3=P1^2;
sbitS4=P1^3;
sbitS=P1^4;
charBW,SW,GW;
uchart,tflag;
ucharm,f,s,x,r,y,n;
ucharA,A_m,A_f,A_s,A_x;
ucharnum1,num2;
ucharflag,flag_A,flag_j;
ucharshi,ge;
ucharM_a,M_b,M_c,M_d,M_e,M_f,temp,ss;
longintz=0,m1,m2;
//*********延时*********
voidDELAY(uintt)//延时1MS
{
intx,y;
for(x=t;x>0;x--)
for(y=110;y>0;y--);
}
voidDELAY_US(uinti)//延时1US
{
while(i--);
}
voidDELAY_A(uinti)
{uintj;
chark;
for(j=0;j
{if(S4==0)
{DELAY(20);
if(S4==0)
{break;}
}
for(k=110;k>0;k--)
{
FMQ=1;
DELAY(10);
FMQ=0;
DELAY(10);
if(S4==0)
{DELAY(20);
if(S4==0)
{break;}
}
}
}
}
//*********LCD模块*******
voidLCD_CSH()
{LCD_WRITE_COM(0x38);//设置液晶工作模式16*2行显示,5*7点阵,8位数据
DELAY
(1);
LCD_WRITE_COM(0x0c);//开显示
DELAY
(1);
LCD_WRITE_COM(0x06);//光标移动
DELAY
(1);
LCD_WRITE_COM(0x01);//清屏
DELAY
(1);
}
voidLCD_WRITE_COM(ucharcom)
{
RW=0;//写
RS=0;//寄存器模式选择,写命令
P0=com;//写命令
LCDEN=0;
DELAY
(1);
LCDEN=1;//使能,0到1
DELAY
(1);
LCDEN=0;//数据送入有效
}
voidLCD_WRITE_DAT(uchardat)
{
RW=0;
RS=1;//寄存器选择,写数据
P0=dat;//写数据
LCDEN=0;
DELAY
(1);
LCDEN=1;//使能0到1
DELAY
(1);
LCDEN=0;//数据送入有效
}
voidLCD_WORD(unsignedchar*p)
{while(*p>0)
{LCD_WRITE_DAT(*p);
p++;
}
}
//固定显示
voidLCD_GD()
{
chari;
LCD_WRITE_COM(0x80);//"20年月日"
for(i=0;i<15;i++)
{
LCD_WRITE_DAT(table[i]);
DELAY
(1);
}
LCD_WRITE_COM(0x90);//":
:
"
for(i=0;i<11;i++)
{
LCD_WRITE_DAT(table1[i]);
}
LCD_WRITE_COM(0x99);
LCD_WRITE_DAT(0x03);
LCD_WRITE_DAT(0x03);
LCD_WRITE_COM(0x9A);
LCD_WORD("萍水缘");
LCD_WRITE_DAT(0x03);
LCD_WRITE_DAT(0x03);
}
//清屏
voidLCD_CLR()
{
LCD_WRITE_COM(0x01);
DELAY
(2);
}
//上电欢迎界面
voidDISL1()
{LCD_WRITE_COM(0x80);
LCD_WORD("基于51单片机的万年历,欢迎使用!
");
}
voidDISL3()//闹钟时间到的显示界面
{
chari;
LCD_WRITE_COM(0x80);
for(i=0;i<15;i++)
{
LCD_WRITE_DAT(table5[i]);
DELAY
(1);
}
LCD_WRITE_COM(0x90);
for(i=0;i<15;i++)
{
LCD_WRITE_DAT(table5[i]);
DELAY
(1);
}
}
//********DS1302模块**********
voidDS1302_CSH()//(写程序要对照DS1302的各个写地址)
{
RST=0;
SCLK=0;
DS1302_WRITE(0x8e,0x00);//允许写
DS1302_WRITE(0x80,0x00);//初始秒0
DS1302_WRITE(0x82,0x00);//初始分0
DS1302_WRITE(0x84,0x15);//初始时0
DS1302_WRITE(0x8a,0x01);//初始星期6
DS1302_WRITE(0x86,0x04);//初始日1
DS1302_WRITE(0x88,0x06);//初始月1
DS1302_WRITE(0x8c,0x12);//初始年11
DS1302_WRITE(0x8e,0x80);//写保护关
}
ucharDS1302_READ(ucharaddr)
{
uchardat;
RST=0;//初始CE为0
SCLK=0;//初始时钟线为0
RST=1;//传输开始
WRITE_BTY(addr);//传送读取时间的地址
dat=READ_BTY();//读取时间
SCLK=1;//时钟线拉高
RST=0;//传输结束
returndat;//返回时间
}
voidDS1302_WRITE(ucharaddr,uchardat)
{
RST=0;//初始CE为0
SCLK=0;//初始时钟线为0
RST=1;//传输开始
DELAY
(1);
WRITE_BTY(addr);//传送读取时间的地址
WRITE_BTY(dat);//写入修改的时间
SCLK=1;//时钟线拉高
RST=0;//传输结束
}
ucharREAD_BTY()
{
uchari,dat=0;
SCLK=0;
DELAY
(1);
for(i=0;i<8;i++)
{
dat=dat>>1;
DELAY
(1);
if(IO==1)//如果读出数据是1(当前数据线为高时,证明该位数据为1)
dat|=0x80;//要传输数据的当前位置为1,不是,则为0
SCLK=1;//拉高时钟线
DELAY
(1);
SCLK=0;//制造下降沿
DELAY
(1);
}
returndat;
}
voidWRITE_BTY(uchardat)
{
uchari;
SCLK=0;//当前时钟线为0
DELAY
(1);
for(i=0;i<8;i++)//开始传输8为数据
{
IO=dat&0x01;//取最低位
DELAY
(1);
SCLK=0;//拉低时钟线
DELAY
(1);
SCLK=1;//拉高时钟线
dat=dat>>1;//数据右移一位,准备传输下一个数据
}
}
//显示时间
voidDISP_TIME()
{
LCD_WRITE_COM(0x81);//显示年,DS1302的读地址8d为年位置,LCD显示在0x81位置
shi=DS1302_READ(0x8d)/16;
ge=DS1302_READ(0x8d)%16;
LCD_WRITE_DAT(0x30+shi);
LCD_WRITE_DAT(0x30+ge);
LCD_WRITE_COM(0x83);//显示月,DS1302的读地址83为年位置
shi=DS1302_READ(0x89)/16;
ge=DS1302_READ(0x89)%16;
LCD_WRITE_DAT(shi+0x30);
LCD_WRITE_DAT(ge+0x30);
LCD_WRITE_COM(0x85);//显示日
shi=DS1302_READ(0x87)/16;
ge=DS1302_READ(0x87)%16;
LCD_WRITE_DAT(shi+0x30);
LCD_WRITE_DAT(ge+0x30);
LCD_WRITE_COM(0x90);//显示小时
shi=DS1302_READ(0x85)/16;
ge=DS1302_READ(0x85)%16;
LCD_WRITE_DAT(shi+0x30);
LCD_WRITE_DAT(ge+0x30);
LCD_WRITE_COM(0x92);//显示分钟
shi=DS1302_READ(0x83)/16;
ge=DS1302_READ(0x83)%16;
LCD_WRITE_DAT(shi+0x30);
LCD_WRITE_DAT(ge+0x30);
LCD_WRITE_COM(0x94);//显示秒
shi=DS1302_READ(0x81)/16;
ge=DS1302_READ(0x81)%16;
LCD_WRITE_DAT(0x30+shi);
LCD_WRITE_DAT(0x30+ge);
DSweek(DS1302_READ(0x8b));//显示星期
if(A==1)//显示闹钟
{
LCD_WRITE_COM(0x87);
LCD_WRITE_DAT(0x20);
LCD_WRITE_DAT(0x0e);
}
if(A!
=1)
{
LCD_WRITE_COM(0x87);
LCD_WRITE_DAT('');
}
}
//显示时间的星期模块
voidDSweek(ucharnum)
{
LCD_WRITE_COM(0x95);//95位置清空,96.97显示周一,二,三,四,五,六,日
LCD_WRITE_DAT(0x20);
LCD_WRITE_DAT(0x20);
LCD_WRITE_COM(0x96);
switch(num)
{
case1:
LCD_WRITE_DAT(0xD6);
LCD_WRITE_DAT(0xDC);
LCD_WRITE_DAT(0xD2);
LCD_WRITE_DAT(0xBB);
break;
case2:
LCD_WRITE_DAT(0xD6);
LCD_WRITE_DAT(0xDC);
LCD_WRITE_DAT(0xB6);
LCD_WRITE_DAT(0xFE);
break;
case3:
LCD_WRITE_DAT(0xD6);
LCD_WRITE_DAT(0xDC);
LCD_WRITE_DAT(0xC8);
LCD_WRITE_DAT(0xFD);
break;
case4:
LCD_WRITE_DAT(0xD6);
LCD_WRITE_DAT(0xDC);
LCD_WRITE_DAT(0xCB);
LCD_WRITE_DAT(0xC4);
break;
case5:
LCD_WRITE_DAT(0xD6);
LCD_WRITE_DAT(0xDC);
LCD_WRITE_DAT(0xCE);
LCD_WRITE_DAT(0xE5);
break;
case6:
LCD_WRITE_DAT(0xD6);
LCD_WRITE_DAT(0xDC);
LCD_WRITE_DAT(0xC1);
LCD_WRITE_DAT(0xF9);
break;
case7:
LCD_WRITE_DAT(0xD6);
LCD_WRITE_DAT(0xDC);
LCD_WRITE_DAT(0xC8);
LCD_WRITE_DAT(0xD5);
break;
}
}
//**********温度模块*******
voidDS1820RST()//DS18b20的初始化函数
{ucharx=0;
DQ=1;//DQ复位
DELAY_US(4);//延时
DQ=0;//DQ拉低
DELAY_US(100);//精确延时大于480us
DQ=1;//拉高
DELAY_US(40);
x=DQ;
}
ucharDS1820RD()//读一个字节
{
uchari=0,dat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat=dat>>1;
DQ=1;//给脉冲信号
if(DQ==1)
dat|=0x80;
DELAY_US(10);
}
returndat;//写一个字节
}
voidDS1820WR(uchardat)
{
chari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
DELAY_US(10);
DQ=1;
dat=dat>>1;
}
}
ucharREAD_T()
{
uchara,b;
DS1820RST();
DS1820WR(0xcc);//跳过读序列号(固定)
DS1820WR(0x44);//启动温度转换
DS1820RST();
DS1820WR(0xcc);//跳过读序列号
DS1820WR(0xbe);//读取温度
a=DS1820RD();
b=DS1820RD();
b<<=4;
b+=(a&0xf0)>>4;
t=b;
returnt;
}
//显示温度
voidDISP_T()
{ucharR1;
R1=READ_T();
LCD_WRITE_COM(0xc8);
LCD_WRITE_DAT(0xCE);
LCD_WRITE_DAT(0xC2);
LCD_WRITE_DAT(0xB6);
LCD_WRITE_DAT(0xC8);
LCD_WRITE_DAT(':
');
if(R1<0x81)
{LCD_WRITE_DAT(0x30+R1/100);}
else
{
R1=~(R1)+1;
LCD_WRITE_DAT('-');
}
LCD_WRITE_DAT(0x30+R1%100/10);
LCD_WRITE_DAT(0x30+R1%10);
LCD_WRITE_DAT(0xA1);
LCD_WRITE_DAT(0xE6);
}
//*******键盘******
//读暂停时的时间
voidTIME()
{
if(flag==0)
{
m=DS1302_READ(0x81);//分别读出秒,分,时,星期,日,月,年(DS1302的读地址应用)
f=DS1302_READ(0x83);
s=DS1302_READ(0x85);
x=DS1302_READ(0x8b);
r=DS1302_READ(0x87);
y=DS1302_READ(0x89);
n=DS1302_READ(0x8d);
}
}
//时间更新
voidTIME_UPDATE()
{
DS1302_WRITE(0x8e,0x00);//写允许
DS1302_WRITE(0x80,m);//分别写出秒,分,时,星期,日,月,年(DS1302的写地址应用)
DS1302_WRITE(0x82,f);
DS1302_WRITE(0x84,s);
DS1302_WRITE(0x8a,x);
DS1302_WRITE(0x86,r);
DS1302_WRITE(0x88,y);
DS1302_WRITE(0x8c,n);
DS1302_WRITE(0x8e,0x80);//禁止写
}
//闹钟
voidALARM_CLOCK()
{
LCD_CLR();
DELAY(10);
DISL3();//显示起床
DELAY_A(100);
FMQ=0;//蜂鸣器响
flag_A=0;
LCD_CLR();
LCD_GD();//固定显示
}
//闹钟开关显示
voidALARM_KG()
{
if(x!
=1)
{
A=0;
LCD_WRITE_COM(0x85);
LCD_WRITE_DAT(0xb9);
LCD_WRITE_DAT(0xd8);
x=0;
}
if(x==1)
{
A=1;
LCD_WRITE_COM(0x85);
LCD_WRITE_DAT(0xbf);
LCD_WRITE_DAT(0xaa);
}
}
//*******秒表******
voidCSH()
{
EA=1;
ET0=1;
TMOD=0x01;
TH0=(65535-4900)/256;
TL0=(65535-4900)%256;
TR0=0;
ss=0;
M_a=M_b=M_c=M_d=0;
}
//秒表的键盘扫描
voidKEYSCAN_M()
{S=0;
if(S2==0)
{
DELAY(100);
if(S2==0)
{
while(S2==0);
ss=~ss;
TR0=1;
if(ss==0)//S2可以暂停或者继续
TR0=0;
}
}
if(S3==0)
{
DELAY(100);
if(S3==0)
{
while(S3==0)
{M_a=M_b=M_c=M_d=0;}
}
}
}
voidTIME_M()interrupt1
{
TH0=(65535-4900)/256;
TL0=(65535-4900)%256;
temp++;
if(temp==2)
{
temp=0;
M_c++;
if(M_c==10)
{
M_c=0;
M_b++;
if(M_b==10)
{
M_b=0;
M_a++;
if(M_a==10)
{
M_a=0;
M_d++;
if(M_d==6)
{
M_d=0;
M_e++;
if(M_e==0)
{
M_e=0;
M_f++;
}
}
}
}
}
}
}
//显示秒表,fe:
da:
bc
voidDISP_M()
{LCD_WRITE_COM(0x83);//显示秒表
LCD_WRITE_DAT(0xc3);
LCD_WRITE_DAT(0xeb);
LCD_WRITE_DAT(0xb1);
LCD