电子密码锁完整代码.docx
《电子密码锁完整代码.docx》由会员分享,可在线阅读,更多相关《电子密码锁完整代码.docx(23页珍藏版)》请在冰豆网上搜索。
电子密码锁完整代码
#include
#include
#include
#include"VIIC_C51.h"
#defineucharunsignedchar
#defineuintunsignedint
#defineCSI24WC020XA0
#defineucharunsignedchar
sbitlcdrs=P2^0;
sbitlcdrw=P2^1;
sbitlcden=P2^2;
sbitalarm=P2^3;
sbitred=P2^7;
sbitgreen=P2^6;
sbitKEY_INT=P3^2;
//ledtest
sbitLED1=P3^5;
sbitLED2=P3^1;
ucharhour,min,sec,us;
ucharflag=1,canscan=0,lock=0;
ucharpassword[8]={0,0,0,0,0,0,0,0};
ucharinput[8]={0,1,2,3,4,5,6,7};
ucharcodea[]={0xF7,0xFB,0xFD,0xFE};
unsignedcharDelayNS(unsignedcharno)
{
unsignedchari,j;
for(;no>0;no--)
{
for(i=0;i<100;i++)
for(j=0;j<100;j++);
}
return0;
}
unsignedchardelay_eep(unsignedcharj)
{
unsignedchark,l;
for(l=0;l<=j;l++)
for(k=0;k<=250;k++);
return0;
}
voidt0_init()
{
TMOD=0x01;
TL0=0xb0;
TH0=0x3c;
TR0=0;
EA=1;
ET0=1;
}
voiddelay(ucharn)
{
uchari;
while(n--)
for(i=125;i>0;i--);
}
//lcd写命令
voidwrite_com(ucharcom)
{
lcdrs=0;
lcdrw=0;
P0=com;
delay
(2);
lcden=1;
delay
(2);
lcden=0;
}
//lcd写数据
voidwrite_data(uchardate)
{
lcdrs=1;
lcdrw=0;
P0=date;
delay
(2);
lcden=1;
delay
(2);
lcden=0;
}
//lcd的初始化
voidinit_lcd()
{
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
//lcd清屏
voidclearscn()
{
write_com(0x06);
write_com(0x01);
}
//lcd显示坐标
voidgotoxy(ucharx,uchary)
{
if(x==1)
write_com(0x80+y);
if(x==2)
write_com(0xc0+y);
}
//写lcd字符串
voidwrite_str(uchar*str)
{
while(*str!
='\0')
{
write_data(*str);
delay
(2);
str++;
}
}
//写一位数字
voidwrite_num(ucharnum)
{
write_data(0x30+num);
}
//写两位数
voidwrite_num2(ucharnum)
{
ucharx,y;
x=num/10;
y=num%10;
write_num(x);
write_num(y);
}
//矩阵键盘扫描函数
ucharscan(void)
{
ucharrow,col;
ucharj,m;
P1=0xF0;
if((P1&0xF0)!
=0xF0)
{
delay
(1);
if((P1&0xF0)!
=0xF0)
col=~(P1|0x0F);
j=0;
P1=a[j];
while(j<=3)
{
if((P1&0xF0)!
=0xF0)
{
row=~a[j];
break;
}
else
{j++;P1=a[j];}
}
m=row+col;
return(m);
}
else
return(0);
}
ucharcoding(ucharm)
{
uchark;
switch(m)
{
case(0x08+0x80):
k=0;break;
case(0x08+0x40):
k=1;break;
case(0x08+0x20):
k=2;break;
case(0x08+0x10):
k=3;break;
case(0x04+0x80):
k=4;break;
case(0x04+0x40):
k=5;break;
case(0x04+0x20):
k=6;break;
case(0x04+0x10):
k=7;break;
case(0x02+0x80):
k=8;break;
case(0x02+0x40):
k=9;break;
case(0x02+0x20):
k=10;break;
case(0x02+0x10):
k=11;break;
case(0x01+0x80):
k=12;break;
case(0x01+0x40):
k=13;break;
case(0x01+0x20):
k=14;break;
case(0x01+0x10):
k=15;break;
}
return(k);
}
//c重新设置密码
voidsetpassword()
{
uchartmp,key,i=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
gotoxy(1,0);
write_str("");
gotoxy(1,10);
write_str("SET");
while
(1)
{
tmp=scan();
if(tmp!
=0)
{
key=coding(tmp);
if(key<=9&&i<8)
{
if(i<8){password[i]=key;gotoxy(1,i);write_data(0x2a);}
i++;
alarm=0;
delay(250);
alarm=1;
}
if(i>=8&&(key==11)){
gotoxy(1,10);
write_str("SETOK");
gotoxy(1,0);
write_str("");
break;
}
delay(250);
}
}
}
//蜂鸣器报警
voidbuzzeralarm()
{
alarm=0;
delay(250);
alarm=1;
delay(250);
alarm=0;
delay(250);
alarm=1;
delay(250);
alarm=0;
delay(250);
alarm=1;
delay(250);
}
//定时器0中断服务函数
//作用给输入三次错误倒计时用
voidtime0()interrupt1
{
TL0=0xb0;
TH0=0x3c;
if(++us==20)
{
us=0;
gotoxy(1,6);
write_num2(sec);
gotoxy(1,3);
write_num2(min);
gotoxy(1,0);
write_num2(hour);
if(++sec==60)
{
sec=0;
if(++min==60)
{
min=0;
if(++hour==1)
{
hour=0;TR0=0;lock=0;
gotoxy(2,10);
write_str("UNLOCKED");
}
}
}
}
}
//主函数
voidmain(void)
{
uchartmp,key,i=0,j,scannum=0;
uchartd[8]={0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1};//eepromsendbuff
ucharrd[8]={0x00,0x01,0x02,0x03,0x04};//eepromreadbuff
green=0;
red=0;
t0_init();
init_lcd();
LED1=0;
LED2=0;
while
(1)
{
tmp=scan();//读入键值
if(tmp!
=0)
{
key=coding(tmp);
if((key<=9)&&(i<8)&&(lock==0)&&(green!
=1))//判断输入次数(i),和锁定情况(lock)和有效输入(key)
{
red=0;
gotoxy(1,10);
write_str("");
gotoxy(1,i);
input[i]=key;
i++;
alarm=0;
write_data(0x2a);
delay(250);
alarm=1;
}
if(key==10)//
{
gotoxy(1,i-1);
write_data(0x20);
if(i>0)i--;
delay(250);
}
if(i==8&&key==11)//确认键
{
i=0;
#if1
IRcvStr(CSI24WC02,0,rd,0x8);//?
EEPROM
delay_eep(200);
for(i=0;i<8;i++)//?
password
{
password[i]=rd[i];
}i=0;
#endif
for(j=0;j<=7;j++)
{
if(input[j]!
=password[j])
flag=1;
elseflag=0;
}
if(lock==0)
{
if(flag)
{
flag=0;
scannum++;
gotoxy(2,10);
write_str("ERR!
");
write_num(scannum);
red=1;
buzzeralarm();
if(scannum==3){lock=1;TR0=1;}
else{
clearscn();
gotoxy(2,10);
write_str("again");
continue;
}
}
else
{
gotoxy(2,10);
write_str("OK!
");
green=1;
}
}
if(lock)
{
gotoxy(2,10);
write_str("LOCKED");
}
gotoxy(1,0);
write_str("");
canscan=0;
delay(250);
}
if((green==1)&&(key==13))
{
LED1=1;
green=0;
delay(200);
LED1=0;
}
if((key==12)&&(green==1))//
{
setpassword();
ISendStr(CSI24WC02,0,password,0x8);//
}
}
}
}
/********************************************************************
VIIC_C51.C
此程序是I2C操作平台(主方式的软件平台)的底层的C子程序,如发送数据
及接收数据,应答位发送,并提供了几个直接面对器件的操作函数,它很方便的
与用户程序连接并扩展.....
注意:
函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作
一定的修改....(本例是1us机器周期,即晶振频率要小于12MHZ)
********************************************************************/
#include/*头文件的包含*/
#include
#defineucharunsignedchar/*宏定义*/
#defineuintunsignedint
#define_Nop()_nop_()/*定义空指令*/
/*常,变量定义区*/
/*端口位定义*/
sbitSDA=P3^7;/*模拟I2C数据传送位*/
sbitSCL=P3^6;/*模拟I2C时钟控制位*/
/*状态标志*/
bitack;/*应答标志位*/
/*******************************************************************
起动总线函数
函数原型:
voidStart_I2c();
功能:
启动I2C总线,即发送I2C起始条件.
********************************************************************/
voidStart_I2c()
{
SDA=1;/*发送起始条件的数据信号*/
_Nop();
SCL=1;
_Nop();/*起始条件建立时间大于4.7us,延时*/
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0;/*发送起始信号*/
_Nop();/*起始条件锁定时间大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0;/*钳住I2C总线,准备发送或接收数据*/
_Nop();
_Nop();
}
/*******************************************************************
结束总线函数
函数原型:
voidStop_I2c();
功能:
结束I2C总线,即发送I2C结束条件.
********************************************************************/
voidStop_I2c()
{
SDA=0;/*发送结束条件的数据信号*/
_Nop();/*发送结束条件的时钟信号*/
SCL=1;/*结束条件建立时间大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1;/*发送I2C总线结束信号*/
_Nop();
_Nop();
_Nop();
_Nop();
}
/*******************************************************************
字节数据传送函数
函数原型:
voidSendByte(ucharc);
功能:
将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0假)
发送数据正常,ack=1;ack=0表示被控器无应答或损坏。
********************************************************************/
voidSendByte(ucharc)
{
ucharBitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++)/*要传送的数据长度为8位*/
{
if((c<elseSDA=0;
_Nop();
SCL=1;/*置时钟线为高,通知被控器开始接收数据位*/
_Nop();
_Nop();/*保证时钟高电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0;
}
_Nop();
_Nop();
SDA=1;/*8位发送完后释放数据线,准备接收应答位*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)ack=0;
elseack=1;/*判断是否接收到应答信号*/
SCL=0;
_Nop();
_Nop();
}
/*******************************************************************
字节数据传送函数
函数原型:
ucharRcvByte();
功能:
用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数。
********************************************************************/
ucharRcvByte()
{
ucharretc;
ucharBitCnt;
retc=0;
SDA=1;/*置数据线为输入方式*/
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_Nop();
SCL=0;/*置时钟线为低,准备接收数据位*/
_Nop();
_Nop();/*时钟低电平周期大于4.7μs*/
_Nop();
_Nop();
_Nop();
SCL=1;/*置时钟线为高使数据线上数据有效*/
_Nop();
_Nop();
retc=retc<<1;
if(SDA==1)retc=retc+1;/*读数据位,接收的数据位放入retc中*/
_Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
return(retc);
}
/********************************************************************
应答子函数
原型:
voidAck_I2c(bita);
功能:
主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
voidAck_I2c(bita)
{
if(a==0)SDA=0;/*在此发出应答或非应答信号*/
elseSDA=1;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();/*时钟低电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0;/*清时钟线,钳住I2C总线以便继续接收*/
_Nop();
_Nop();
}
/*******************************************************************
向无子地址器件发送字节数据函数
函数原型:
bitISendByte(ucharsla,ucahrc);
功能:
从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
如果返回1表示操作成功,否则操作有误。
注意:
使用前必须已结束总线。
********************************************************************/
bitISendByte(ucharsla,ucharc)
{
Start_I2c();/*启动总线*/
SendByte(sla);/*发送器件地址*/
if(ack==0)return(0);
SendByte(c);/*发送数据*/
if(ack==0)return(0);
Stop_I2c();/*结束总线*/
return
(1);
}
/*******************************************************************
向有子地址器件发送多字节数据函数
函数原型:
bitISendStr(ucharsla,ucharsuba,ucahr*s,ucharno);
功能:
从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
如果返回1表示操作成功,否则操作有误。
注意:
使用前必须已结束总线。
********************************************************************/
bitISendStr(ucharsla,ucharsuba,uchar*s,ucharno)
{
uchari;
Start_I2c();/*启动总线*/
SendByte(s