/*********************************************************/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
sbit IRIN=P1^0; //红外接收器数据线
sbit jdq=P1^7; //继电器驱动线
uchar IRCOM[7];
/**********************************************************/
void delay(unsigned char x){ //x*0.14MS
unsigned char i;
while(x--){
for(i=0;i<13;i++);
}
}
/***************************按键驱动*****************************/
sbit row0=P3^7;sbit row1=P3^6;sbit row2=P3^5;sbit row3=P3^4;
sbit col0=P3^0;sbit col1=P3^1;sbit col2=P3^2;sbit col3=P3^3;
uchar key_get(){
uchar k=16;
row0=row1=row2=row3=col0=col1=col2=col3=1;
row0=0;k=col0==0?12 :col1==0?0 :col2==0?10:col3==0?11:k; row0=1;
row1=0;k=col0==0?13 :col1==0?1 :col2==0?2 :col3==0?3 :k; row1=1;
row2=0;k=col0==0?14 :col1==0?4 :col2==0?5 :col3==0?6 :k; row2=1;
row3=0;k=col0==0?15 :col1==0?7 :col2==0?8 :col3==0?9 :k; row3=1;
return k;
}
/**********************按键处理程序********************************/
uchar k=16,m=0; //k 键值缓存 m 1602显示
ulong pws1=1234,pws2,pws3; //pws1初始密码 pws2输入密码 pws3修改密码
bit keyFlag,pwsflag,pws3flag; //keyFlag按键释放标志 pwsflag密码正误标志 pws3flag密码修改确认标志
void keyget(){ //按键应用
if(((key_get()!=16)||(IRCOM[5]!='F'&&IRCOM[6]!='F'))&&keyFlag==0){ //判断右键按下或红外接收不为FF
delay(20); //延时消抖
keyFlag=1; //按键标志至1
if((key_get()!=16)||(IRCOM[5]!='F'&&IRCOM[6]!='F')){ //确认有键按下或红外有接收信号
k=key_get(); //将按键的值赋给K
if(IRCOM[6]=='1'&&IRCOM[5]=='6')k=0; //红外接收对应的编码
else if(IRCOM[6]=='0'&&IRCOM[5]=='C')k=1;
else if(IRCOM[6]=='1'&&IRCOM[5]=='8')k=2;
else if(IRCOM[6]=='5'&&IRCOM[5]=='E')k=3;
else if(IRCOM[6]=='0'&&IRCOM[5]=='8')k=4;
else if(IRCOM[6]=='1'&&IRCOM[5]=='C')k=5;
else if(IRCOM[6]=='5'&&IRCOM[5]=='A')k=6;
else if(IRCOM[6]=='4'&&IRCOM[5]=='2')k=7;
else if(IRCOM[6]=='5'&&IRCOM[5]=='2')k=8;
else if(IRCOM[6]=='4'&&IRCOM[5]=='A')k=9;
else if(IRCOM[6]=='1'&&IRCOM[5]=='9')k=10;
else if(IRCOM[6]=='0'&&IRCOM[5]=='D')k=11;
else if(IRCOM[6]=='0'&&IRCOM[5]=='7')k=12;
if(k<=9&&pws3flag==0){ //密码输入
pws2=pws2*10+k;
m++;
if(m>4)m=6;
}
if(k<=9&&pws3flag==1){ //密码修改输入
pws3=pws3*10+k;
m++;
if(m>4)m=6;
}
if(k==10){ //确定
if(pws3flag==1){ //修改后的密码保存
m=0;
pws1=pws3;
pws3=pws3flag=0;
}
else { //确认输入的密码是否正确
if(pws1==pws2){pwsflag=1;m=5;}
else {pwsflag=0;m=6;}
pws2=0;
}
}
if(k==11){pwsflag=pws2=pws3=m=0;jdq=1;} //清除
if(k==12){pws3flag=1;m=0;} //修改密码
}
IRCOM[5]='F'; //将红外缓存至FF
IRCOM[6]='F';
}
if(IRCOM[5]=='F'&&IRCOM[6]=='F'&&key_get()==16)keyFlag=0; //键释放
}
/**********************************************************/
sbit RS=P1^1; //1=数据;0=命令
sbit RW=P1^2; //1=读;0=写
sbit E=P1^3; //1=使能;0=禁止
#define Dat1602 P0 /** 数据端口 **/
sbit BF=Dat1602^7; /** 忙信号线 **/
/** LCM忙检测 **/
bit busy1602(){
bit busy=0; //暂存标志
Dat1602=0xff; //口线置1,防止干扰
RS=0; RW=1; //置“命令、读”模式
E=1; E=1; //使能,写两次做短延时
busy=BF;E=0; //暂存标志,关闭使能
return busy; //返回忙信号,1=忙
}
/** 写命令 参数:comDat为要发送的命令 **/
void WriteComm(uchar comDat){
while (busy1602()); //忙,则等待
RS=0;RW=0; //置“命令、写”模式
Dat1602=comDat;E=1;E=0; //送出命令,并使之有效
}
/** 写数据 参数:dat为要发送的数据 **/
void WriteData(uchar dat){
while (busy1602()); //忙,则等待
RS=1;RW=0; //置“数据、写”模式
Dat1602=dat;E=1;E=0; //送出数据,并使之有效
}
/** 1602初始化 **/
void Init1602(){
WriteComm(0x38);//8位,两行,5*7点阵
WriteComm(0x0c);//显示开,光标关
WriteComm(0x06);//默认,光标右移
WriteComm(1); //清显示
}
void sTo1602(char r,char c,uchar *s){
uchar i=0;
WriteComm(0x80+r*0x40+c);
for(;c<40&&s[i]!=0;i++,c++){WriteData(s[i]);}
}
/*******************************************************************/
void main(){
TCON=0x01; //触发方式为脉冲负边沿触发
IE=0x81; //允许总中断中断,使能 INT0 外部中断
IRIN=1; //I/O口初始化
IRCOM[5]='F'; //红外缓存初始化
IRCOM[6]='F';
jdq=1; //继电器初始化
Init1602(); //1602初始化
while(1){
keyget();
if(pwsflag==1){
jdq=0;
}
switch(m){
case 0: //1602第一屏显示
if(pws3flag==1){
sTo1602(0,0,"alter password: ");
sTo1602(1,0," ");
}
else {
sTo1602(0,0,"password: ");
sTo1602(1,0," ");
}
break;
case 1: //1602第二屏显示
if(pws3flag==1){
sTo1602(0,0,"alter password: ");
sTo1602(1,0,"* ");
}
else {
sTo1602(0,0,"password: ");
sTo1602(1,0,"* ");
}
break;
case 2: //1602第三屏显示
if(pws3flag==1){
sTo1602(0,0,"alter password: ");
sTo1602(1,0,"** ");
}
else {
sTo1602(0,0,"password: ");
sTo1602(1,0,"** ");
}
break;
case 3: //1602第四屏显示
if(pws3flag==1){
sTo1602(0,0,"alter password: ");
sTo1602(1,0,"*** ");
}
else {
sTo1602(0,0,"password: ");
sTo1602(1,0,"*** ");
}
break;
case 4: //1602第五屏显示
if(pws3flag==1){
sTo1602(0,0,"alter password: ");
sTo1602(1,0,"**** ");
}
else {
sTo1602(0,0,"password: ");
sTo1602(1,0,"**** ");
}
break;
case 5: //1602第六屏显示
sTo1602(0,0,"password correct");
sTo1602(1,0," ");
break;
case 6: //1602第七屏显示
sTo1602(0,0,"password error ");
sTo1602(1,0," ");
break;
}
}
}
/*******************红外线*****************************/
void IR_IN() interrupt 0 using 0 {
unsigned char j,k,N=0;
EX0 = 0;
delay(15);
if (IRIN==1){
EX0 =1;
return;
} //确认IR信号出现
while(!IRIN)delay(1); //等IR变为高电平,跳过9ms的前导低电平信号。
for(j=0;j<4;j++){ //收集四组数据
for(k=0;k<8;k++){ //每组数据有8位
while(IRIN)delay(1); //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
while(!IRIN)delay(1); //等 IR 变为高电平
while(IRIN){ //计算IR高电平时长
delay(1);
N++;
if (N>=30){
EX0=1;
return;
} //0.14ms计数过长自动离开。
} //高电平计数完毕
IRCOM[j]=IRCOM[j]>>1; //数据最高位补“0”
if(N>=8)IRCOM[j]=IRCOM[j]|0x80; //数据最高位补“1”
N=0;
}
}
if (IRCOM[2]!=~IRCOM[3]){
EX0=1;
return;
}
IRCOM[5]=IRCOM[2]&0x0F; //取键码的低四位
IRCOM[6]=IRCOM[2]>>4; //右移4次,高四位变为低四位
if(IRCOM[5]>9)IRCOM[5]=IRCOM[5]+0x37; //储存红外接收信号
else IRCOM[5]=IRCOM[5]+0x30;
if(IRCOM[6]>9)IRCOM[6]=IRCOM[6]+0x37;
else IRCOM[6]=IRCOM[6]+0x30;
EX0 = 1;
}
|