基于单片机闹钟设计程序.docx
《基于单片机闹钟设计程序.docx》由会员分享,可在线阅读,更多相关《基于单片机闹钟设计程序.docx(28页珍藏版)》请在冰豆网上搜索。
基于单片机闹钟设计程序
#include
#include//_nop_();
#defineucharunsignedchar
#defineuintunsignedint
ucharcodetable[]="9999-12-31MON";
ucharcodetable1[]="23:
59:
55C";
ucharcodetable2[]="0123456789abcdef";
ucharcodetable3[]="CLOCKTIME";
ucharcodetable4[]="--";//日期
ucharcodetable5[]=":
:
";//时间
ucharday[]={31,28,31,30,31,30,31,31,30,31,30,31};//月份天数
ucharxq[][3]={"Sun","Mon","Tue","Web","Thu","Fri","Sat"};//星期字符串数组
ucharshiji,nian,yue,week,ri,shi,fen,miao,count,snum_1,snum_2,ns=0,nf=0,nm=0;//,t1,t2;
bitnz=0,sz=0,n_key=1,K_n=1;//nz闹钟显示界面开关sz:
设置界面开关
sbitLCD_RS=P2^0;
sbitLCD_EN=P2^2;
sbitLCD_RW=P2^1;
sbitKey_ce=P1^3;
sbitDig_ce=P1^1;
sbitSeg_ce=P1^0;
sbitSOUND=P2^3;
voiddelay();//延时
voidw_com(ucharcom);//写指令
voidw_date1(uchardate);//写数据1
voidw_date(uchari,ucharadd,uchardate);//在特定的位置显示数字i:
显示行数add:
显示的位置date:
所要显示的值!
voidstart();//初始化LCD显示屏,在LCD上显示“0123456789abcdef”X2
voidchushiahua();//初始化
voidtime();
intkeyscan(inti);//年月日、时分秒以及星期的正常显示!
voidset();//时间设置
voiddelay(uinti)//延时
{
uintj;
for(i;i>0;i--)
for(j=124;j>0;j--);
}
voidw_com(ucharcom)//写指令
{
LCD_RS=0;
LCD_EN=1;
LCD_RW=0;
P0=com;
delay(5);
LCD_EN=0;
}
voidw_date1(uchardat)//写数据子程序1
{
LCD_RS=1;
LCD_EN=1;
LCD_RW=0;
P0=dat;
delay(5);
LCD_EN=0;
}
voidw_date(uchari,ucharadd,uchardate)//在特定的位置显示数字i:
显示行数add:
显示的位置date:
所要显示的值!
{
ucharshi,ge;
shi=date/10;
ge=date%10;
if(i==1)
{
w_com(0x80+add);
w_date1(0x30+shi);
w_date1(0x30+ge);
}
if(i==2)
{
w_com(0x80+0x40+add);
w_date1(0x30+shi);
w_date1(0x30+ge);
}
}
voidstart(ucharj)//初始化LCD显示屏,在LCD上显示“0123456789abcdef”X2
{
ucharnum;
uchari;
w_com(0x38);//显示001110008为数据接口两行显示7bde
w_com(0x0c);//光标不显示00001100显示开关控制显示开光标关闪烁关
w_com(0x06);//指针加1,整屏不移动00000110读写操作后AC+1画面不动
w_com(0x80);//指针指向0x8010000000~10101111指向第一行起点
if(j==1)//测试LCD
{
for(i=0;i<3;i++)
{
for(num=0;num<16;num++)
{
w_date1(table2[num]);
delay(20);
}
w_com(0x80+0x40);
for(num=0;num<16;num++)
{
w_date1(table2[num]);
delay(20);
}
}
}
if(j==2)//显示时钟
{
for(num=0;num<16;num++)
{
w_date1(table4[num]);//ucharcodetable4[]="--";//日期
delay(20);
}
w_com(0x80+0x40);
for(num=0;num<16;num++)
{
w_date1(table5[num]);//ucharcodetable5[]=":
:
";//时间
delay(20);
}
w_date(1,1,shiji);
w_date(1,3,nian);
w_date(1,6,yue);
w_date(1,9,ri);
week=week%7;//防止week太大
w_com(0x80+12);
for(i=0;i<3;i++)
w_date1(xq[week%10][i]);
w_date(2,2,shi);
w_date(2,5,fen);
w_date(2,8,miao);
w_com(0x80+0x40+13);
if(n_key==1)//闹钟开
w_date1(table1[13]);
if(n_key==0)//闹钟关
w_date1(table[0]);
}
if(j==3)//显示闹钟
{
for(num=0;num<16;num++)
{
w_date1(table3[num]);//ucharcodetable3[]="CLOCKTIME";
delay(20);
}
w_com(0x80+0x40);
for(num=0;num<16;num++)
{
w_date1(table5[num]);//ucharcodetable5[]=":
:
";//时间
delay(20);
}
w_date(2,2,ns);
w_date(2,5,nf);
w_date(2,8,nm);
}
}
voidchushihua()//初始化
{
ucharnum;
LCD_EN=0;
w_com(0x38);//显示001110008为数据接口两行显示7bde
w_com(0x0c);//光标不显示00001100显示开关控制显示开光标关闪烁关
w_com(0x06);//指针加1,整屏不移动00000110读写操作后AC+1画面不动
w_com(0x01);//清屏00000001全部清零
w_com(0x80);
for(num=0;num<16;num++)
{
w_date1(table[num]);
delay(20);
}
w_com(0x80+0x40);//第二行首地址11000000~11100111共16X2=32位
for(num=0;num<16;num++)
{
w_date1(table1[num]);
delay(20);
}
TMOD=0X01;//T0方式1
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;//开启总中断
ET0=1;//关全局中断
TR0=1;//启动定时器
shi=23;//装初值
fen=59;
miao=55;
nian=99;
shiji=99;
yue=12;
ri=31;
week=1;
}
voidtime()//年月日、时分秒以及星期的正常显示!
{
uchari;
if(count==20)
{
count=0;
miao++;
if(shi==ns&&fen==nf&&n_key==1)
{
if(K_n==1)
{
SOUND=~SOUND;
}
else_nop_();
}
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
ri++;
week++;
week=week%7;//防止week太大
w_com(0x80+12);
for(i=0;i<3;i++)
w_date1(xq[week%10][i]);
if(ri==day[yue-1]+1)
{
ri=1;
yue++;
if(yue==13)
{
yue=1;
nian++;
if(nian==100)
{
nian=0;
shiji++;
if(shiji%4==0)day[1]=29;//判断闰年还是
elseday[1]=28;
if(shiji==100)
{
shiji=20;
}
w_date(1,1,shiji);
}
elseif(nian%4==0)day[1]=29;
elseday[1]=28;
w_date(1,3,nian);
}
w_date(1,6,yue);
}
w_date(1,9,ri);
}
w_date(2,2,shi);
}
w_date(2,5,fen);
}
w_date(2,8,miao);
}
}
intkeyscan(inti)
{
ucharTemp1,Temp2,Keynum=0;
P0=0;Seg_ce=1;Seg_ce=0;
switch(i)
{
case0:
P0=0xfe;break;
case1:
P0=0xfd;break;
case2:
P0=0xfb;break;
case3:
P0=0xf7;break;
}
Dig_ce=1;Dig_ce=0;Key_ce=0;
Temp1=P0;
Temp1=Temp1&0x0f;
if(Temp1!
=0x0f)
{
delay(100);
Temp2=P0;Temp2=Temp2&0x0f;
if(Temp1==Temp2)
{
switch(Temp2)
{
case0x0e:
Keynum=1;break;//0x0e=>00001110
case0x0d:
Keynum=2;break;//0x0d=>00001101
case0x0b:
Keynum=3;break;//0x0b=>00001011
case0x07:
Keynum=4;break;//0x07=>00000111
default:
break;
}
while(Temp2!
=0x0f)
{
Temp2=P0;
Temp2=Temp2&0x0f;
}
}
}
Key_ce=1;
returnKeynum;
}
voidset()//调时间和闹钟
{
uchari,key;
key=keyscan(0);
if(shi==ns&&fen==nf&&K_n==1&&n_key==1)
{
if(key!
=0)
{
K_n=0;
SOUND=1;
}
}
else{
if(key==1)
{SOUND=0;delay(100);SOUND=1;
if(nz==0)//在时间显示界面按下S1
{
sz=1;
snum_1++;
if(snum_1==1)//第一次按下S1进入设置界面
{
TR0=0;//进入调节先关断TO定时器
w_com(0x0f);//光标显示00001111显示开关控制显示开光标开闪烁开
w_com(0x80+0x40+13);//上一句打开光标命令后面设置光标位置在闹钟开关位置!
}
if(snum_1==2)//在设置界面按下S1退出设置界面
{
snum_1=0;
TR0=1;//开中断
w_com(0x0c);//同上光标不显示00001100显示开关控制显示开光标关闪烁关继续计时
}
}
elseif(nz==1)
{
snum_1++;//因为能够进入这个IF语句是,snum_1必定=0,所以依旧使用snum_1这个变量
if(snum_1==1)//第一次按下S1进入设置界面
{
TR0=0;//调节闹钟设置时间,没必要中断定时器
w_com(0x0f);//光标显示00001111显示开关控制显示开光标开闪烁开
w_com(0x80+0x40+9);//上一句打开光标命令后面设置光标位置在秒的位置!
}
if(snum_1==2)//在设置界面按下S1退出设置界面
{
snum_1=0;
sz=0;
TR0=1;
w_com(0x0c);//同上光标不显示00001100显示开关控制显示开光标关闪烁关继续计时
}
}
}
if(key==2)
{SOUND=0;delay(100);SOUND=1;
if(snum_1==0)_nop_();
if(snum_1==1)
{
if(nz==0)//时间的设置界面按下S2的操作
{
if(snum_2==0)//闹钟开关位按s2取反
{
n_key=~n_key;K_n=1;
w_com(0x80+0x40+13);
if(n_key==1)w_date1(table1[13]);
if(n_key==0)w_date1(table[0]);
w_com(0x80+0x40+13);
}
if(snum_2==1)//秒位+
{
miao++;
if(miao==60)miao=0;
w_date(2,8,miao);
w_com(0x80+0x40+9);
}
if(snum_2==2)//分位+
{
fen++;
if(fen==60)fen=0;
w_date(2,5,fen);
w_com(0x80+0x40+6);
}
if(snum_2==3)//时位+
{
shi++;
if(shi==24)shi=0;
w_date(2,2,shi);
w_com(0x80+0x40+3);
}
if(snum_2==4)//日位+星期
{
ri++;
week++;
if(ri>day[yue-1])ri=1;
w_date(1,9,ri);
week=week%7;//防止week太大
w_com(0x80+12);
for(i=0;i<3;i++)
w_date1(xq[week%10][i]);
w_com(0x80+10);
}
if(snum_2==5)//月位+
{
yue++;
if(yue==13)yue=1;
if(day[yue-1]{
week=week+day[yue-1]+day[yue-1]-ri+1;//1.31变2.30时多的天数是30+30-31+1=30
ri=day[yue-1];
}
else
{
week=week+day[yue-1]+1;
}
w_date(1,9,ri);
week=week%7;//防止week太大
w_com(0x80+12);
for(i=0;i<3;i++)
w_date1(xq[week%10][i]);
w_date(1,6,yue);
w_com(0x80+7);
}
if(snum_2==6)//年+
{
nian++;
if(nian==100)
{
nian=0;
shiji++;
if(shiji%4==0)
{
day[1]=29;
week=week+366;
week=week%7;
}//判断闰年还是
else
{
day[1]=28;
week=week+565;
week=week%7;
}
if(shiji==100)
{
shiji=20;
}
w_date(1,1,shiji);
}
elseif(nian%4==0)
{
day[1]=29;
week=week+366;
week=week%7;
}
else
{
day[1]=28;
week=week+565;
week=week%7;
}
w_date(1,3,nian);
if(yue==2&&ri>day[1])
{
ri=day[1];
w_date(1,9,ri);
week=week-1;
}
w_com(0x80+12);
for(i=0;i<3;i++)
w_date1(xq[week%10][i]);
w_com(0x80+4);
}
}
if(nz==1)//闹钟的设置界面
{
K_n=1;
if(snum_2==1)//秒位+
{
nm++;
if(nm==60)nm=0;
w_date(2,8,nm);
w_com(0x80+0x40+9);
}
if(snum_2==2)//分位+
{
nf++;
if(nf==60)nf=0;
w_date(2,5,nf);
w_com(0x80+0x40+6);
}
if(snum_2==0)//时位+
{
ns++;
if(ns==24)ns=0;
w_date(2,2,ns);
w_com(0x80+0x40+3);
}
}
}
}
if(key==3)
{SOUND=0;delay(100);SOUND=1;
if(snum_1==0)_nop_();
if(snum_1==