单片机时钟程序.docx
《单片机时钟程序.docx》由会员分享,可在线阅读,更多相关《单片机时钟程序.docx(16页珍藏版)》请在冰点文库上搜索。
单片机时钟程序
首先要掌握lcd1602编程,红外遥控原理,当然,单片机基本的要懂得
此程序是用stc89c52单片机,所用的IO口程序有说明。
#include
#defineucharunsignedchar
#defineuintunsignedint
#definett46080//设置时间间隔,对应11.0592MHZ的晶振
sbiten=P3^4;
sbitrs=P3^5;//用于控制1602
sbitrw=P3^6;
sbitdula=P2^6;
sbitwela=P2^7;//用于控制晶体管
sbitIRIN=P3^2;//红外接收器数据线IO口
bitL=1;
uchart,key=0,hh=0,mm=0,ss=0;
ucharIRCOM[4]=0;
//定义数组IRCOM,分别装解码后得到的数据
//IRCOM[0]低8位地址码
//IRCOM[1]高8位地址码
//IRCOM[2]8位数据码
//IRCOM[3]8位数据码的反码
ucharcodetable[]="Inputpassword";
ucharcodetable1[]="Welcometouse!
";
ucharcodetable2[]="Passworderror!
";
ucharcodewish[]="Happyeveryday!
";
ucharcodetime[]="00:
00:
00";
ucharcodeloading[]="Loading...";
/////////////////////////////////////////////////////
voiddelay(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=112;y>0;y--);//大约是1ms,因为单片机的时钟周期为11.0592mhz。
}
voidwrite_com(ucharcom)
{
rs=0;//指令
P0=com;//写指令函数
delay(5);
en=1;
delay(5);
en=0;
}
voidwrite_data(uchardat)
{
rs=1;//数据
P0=dat;//写指令函数
delay(5);
en=1;
delay(5);
en=0;
}
voidLCD_init()
{
wela=0;
dula=0;//用于关闭晶体管,因为都是用P0
en=0;//初始时使能为0
rw=0;
write_com(0x38);//显示屏模式设置为1602方案
write_com(0x0f);//显示开关/光标设置
write_com(0x06);
write_com(0x01);//清屏
write_com(0x80);//指针置零
}
/////////////////////////////////////////////////
/////////////////////////////////////////////////
voiddelay014ms(ucharx)//x*0.14MSSTC10F04延时约0.15MS
{
uchari;
while(x--)
{
for(i=0;i<15;i++)//13
;
}
}
//////////////初始化////////////
voidIR_init(void)
{
EA=1;
EX0=1;//允许总中断中断,使能INT0外部中断
IT0=1;//触发方式为脉冲负边沿触发
IRIN=1;//I/O口初始化
}
////////////解码过程//////////////
voidIR_CODE(void)interrupt0//在外部中断子程序中解码
{
voidshuanxin(ucharadd,uchardate);
ucharj,k,N=0,h,m,n;
EX0=0;//防止干扰
delay014ms(15);//延时2.1ms
if(IRIN==1)//2.1ms能够检测出各种错误信号
{
EX0=1;
return;
}//确认IR信号出现
while(!
IRIN);//等IR变为高电平,跳过9ms的前导低电平信号。
//////高电平后开始检测高电平持续的时间以确定是0还是1/////
for(j=0;j<4;j++)//收集四组数据
{
for(k=0;k<8;k++)//每组数据有8位
{
while(IRIN);//等IR变为低电平,跳过4.5ms的前导高电平信号。
//引导码检验结束
while(!
IRIN);//等IR变为高电平开始检测
while(IRIN)//计算IR高电平时长
{
delay014ms
(1);
N++;
if(N>=30)
{
EX0=1;
return;
}//0.14ms计数过长自动离开?
}//高电平计数完毕
IRCOM[j]=IRCOM[j]>>1;//数据最高位补"0"
if(N>=8)//6*0.14=0.84ms(6/7均可)
{
IRCOM[j]=IRCOM[j]|0x80;
}//数据最高位补"1"
N=0;
}
}
if(IRCOM[2]!
=~IRCOM[3])//不等的话表示解码失败
{
IRCOM[4]=0;
EX0=1;
return;
}
/////////////////////嵌入加密程序////////////////////
if(L)
{
switch(IRCOM[2])//判断第三个数码值
{
case0x16:
n=0;write_data(num[0]);break;//0
case0x0c:
n=1;write_data(num[1]);break;//1
case0x18:
n=2;write_data(num[2]);break;//2
case0x5e:
n=3;write_data(num[3]);break;//3
case0x08:
n=4;write_data(num[4]);break;//4
case0x1c:
n=5;write_data(num[5]);break;//5
case0x5a:
n=6;write_data(num[6]);break;//6
case0x42:
n=7;write_data(num[7]);break;//7
case0x52:
n=8;write_data(num[8]);break;//8
case0x4a:
n=9;write_data(num[9]);break;//9
case0x43:
n=10;gotoloop;break;//play
default:
break;
}
if(h>=7)
h++;//超过范围判断为错
if(mima[m]==num[n])
h++;
m++;
loop:
//确认时跳过上面的判断,防止意外
if(n==10)
{
write_com(0x01);
write_com(0x80);
write_com(0x0c);
if(h==7)
{
P1=0x00;
for(j=0;j<15;j++)
write_data(table1[j]);
L=0;//跳过此程序
}
else
{
for(j=0;j<15;j++)
write_data(table2[j]);
EA=0;//关闭遥控
}
}
}
///////////////////////////////////////////////////////
////////////////////嵌入时间调节程序///////////////////
if(!
L)
{
if(IRCOM[2]==0x44)
{
TR0=0;//时钟停止运行
write_com(0x0f);//光标闪烁
key++;
if(key==7)//保证不超出范围
key=1;
}
if(IRCOM[2]==0x40)
{
TR0=0;//时钟停止运行
write_com(0x0f);//光标闪烁
if(key==1)
key=7;
if(key==0)//保证不出现负数
key=2;
key--;
}
if(IRCOM[2]==0x43)
{
key=0;
TR0=~TR0;//不直接置1,目的是增加暂停功能
write_com(0x0c);//取消闪烁
}
/////////////////判断参数/////////////////
if(key)
{
switch(IRCOM[2])
{
case0x16:
n=0;break;//0
case0x0c:
n=1;break;//1
case0x18:
n=2;break;//2
case0x5e:
n=3;break;//3
case0x08:
n=4;break;//4
case0x1c:
n=5;break;//5
case0x5a:
n=6;break;//6
case0x42:
n=7;break;//7
case0x52:
n=8;break;//8
case0x4a:
n=9;break;//9
default:
n=10;break;
}
}
/////////////////指针定位、时间调节//////////////////
if(key==1)
{
write_com(0xcb);//指针指向ss
if(n!
=10)
{
write_data(num[n]);
write_com(0xcb);
ss=10*(ss/10)+n;
}
}
if(key==2)
{
write_com(0xca);
if(n!
=10)
{
if(n<6)
{
write_data(num[n]);
write_com(0xca);
ss=10*n+ss%10;
}
}
}
if(key==3)
{
write_com(0xc8);//指针指向mm
if(n!
=10)
{
write_data(num[n]);
write_com(0xc8);
mm=10*(mm/10)+n;
}
}
if(key==4)
{
write_com(0xc7);
if(n!
=10)
{
if(n<6)
{
write_data(num[n]);
write_com(0xc7);
mm=10*n+mm%10;
}
}
}
if(key==5)
{
write_com(0xc5);//指针指向hh
if(n!
=10)
{
if((hh/10)<2)
{
write_data(num[n]);
write_com(0xc5);
hh=10*(hh/10)+n;
}
else
{
if(n<4)
{
write_data(num[n]);
write_com(0xc5);
hh=20+n;
}
}
}
}
if(key==6)
{
write_com(0xc4);
if(n!
=10)
{
if(n<3)
{
if(n<2)
{
write_data(num[n]);
write_com(0xc4);
hh=10*n+hh%10;
}
else
{
if((hh%10)<4)
{
write_data(num[n]);
write_com(0xc4);
hh=10*n+hh%10;
}
}
}
}
}
}
///////////////////////////////////////////////////////
EX0=1;
return;
}
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
///////////////时钟程序///////////////
voiddingshi()
{
TMOD=0x01;//确定定时器工作模式(定时模式)
TH0=(65536-tt)/256;//赋初值为tt微秒
TL0=(65536-tt)%256;//不赋值时默认其值是0
EA=1;//开总中断
ET0=1;//开定时器0中断
//IE=0x82;//总线写法
TR0=1;//启动定时器0总线TCON=0x10;
}
voidshuanxin(ucharadd,uchardate)
{
ucharshi,ge;
write_com(0xc4+add);//指针指向
shi=date/10;
ge=date%10;
write_data(num[shi]);
write_data(num[ge]);//指针自动后移,故不必再写指针位置
}
voidzoudong()
{
if(t==20)
{
t=0;
ss++;
if(ss==60)
{
ss=0;
mm++;
if(mm==60)
{
mm=0;
hh++;
if(hh==24)
{
hh=0;
}
shuanxin(0,hh);
}
shuanxin(3,mm);
}
shuanxin(6,ss);
}
}
////////////////////////////////////////////////////////
voidmain()
{
uchari;
IR_init();
LCD_init();
for(i=0;i<14;i++)
write_data(table[i]);
write_com(0xc0);
while(L);
write_com(0xc0);
for(i=0;i<10;i++)
write_data(loading[i]);
delay(2500);
P1=0xff;
/////////////执行时钟程序///////////////////
dingshi();
write_com(0x01);//清屏
write_com(0x80);//指针置零
write_com(0x0c);//显示开关/光标设置
for(i=0;i<16;i++)
write_data(wish[i]);
write_com(0xc4);
for(i=0;i<8;i++)
write_data(time[i]);
while
(1)
{
zoudong();
if(IRCOM[2]==0x09)
break;//用遥控控制重启
}
}
voidtime0()interrupt1
{
TH0=(65536-tt)/256;//不赋值时默认其值是0
TL0=(65536-tt)%256;
t++;
}