基于单片机的智能密码锁

来源:互联网 发布:java教育平台源码下载 编辑:程序博客网 时间:2024/04/30 17:52
该密码锁控制器 ,键盘上有0-9个数字按键,功能键:确认和取消等,可设置复合键。密码的位数及密码可以任意设定,,当输入数字和设置的密码相同的时候,锁打开,否则无法打开。采用IIC通信方式,密码锁的密码掉电不丢失。
#include<reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned charuchar old1,old2,old3,old4,old5,old6; //原始密码000000uchar new1,new2,new3,new4,new5,new6;  //每次MCU采集到的密码输入uchar a=10,b=10,c=10,d=10,e=10,f=10; //送入数码管显示的变量uchar wei,key,temp;bit allow,genggai,ok,wanbi,retry,close;  //各个状态位,默认初始值为0sbit dula=P2^6;sbit wela=P2^7;sbit beep=P2^3;sbit led=P1^0;                           //加一个流水灯,把蜂鸣器换掉sbit sda=P2^0;                          //IO口定义sbit scl=P2^1;unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x08};    //数码管显示0-9的段码/*****************i2c芯片24C02存储器驱动程序************************************/ /*驱动延时程序*/void nop()                //10us延时,保证书写i2c驱动时满足大于4us{    _nop_();    _nop_();}/*24C02读写驱动程序*/void delay1(unsigned int m){   unsigned int n;    for(n=0;n<m;n++);}void init()  //24c02初始化子程序{    scl=1;    nop();    sda=1;    nop();}void start()        //启动I2C总线{    sda=1;    nop();    scl=1;    nop();    sda=0;    nop();    scl=0;    nop();}void stop()         //停止I2C总线{    sda=0;    nop();    scl=1;    nop();    sda=1;    nop();}void writebyte(unsigned char j)  //写一个字节{    unsigned char i,temp;    temp=j;    for (i=0;i<8;i++)   {       temp=temp<<1;       scl=0;       nop();       sda=CY;      //temp左移时,移出的值放入了CY中       nop();       scl=1;       //待sda线上的数据稳定后,将scl拉高       nop();   }   scl=0;   nop();   sda=1;   nop();}unsigned char readbyte()   //读一个字节{   unsigned char i,j,k=0;   scl=0; nop(); sda=1;   for (i=0;i<8;i++)   {          nop(); scl=1; nop();        if(sda==1)         j=1;        else        j=0;        k=(k<<1)|j;        scl=0;    }    nop();    return(k);}void clock()         //I2C总线时钟{   unsigned char i=0;   scl=1;   nop();   while((sda==1)&&(i<255))      i++;   scl=0;   nop();}////////从24c02的地址address中读取一个字节数据/////unsigned char read24c02(unsigned char address){   unsigned char i;   start();   writebyte(0xa0);   clock();   writebyte(address);   clock();   start();   writebyte(0xa1);   clock();   i=readbyte();   stop();   delay1(100);   return(i);}//////向24c02的address地址中写入一字节数据info/////void write24c02(unsigned char address,unsigned char info){   start();   writebyte(0xa0);   clock();   writebyte(address);   clock();   writebyte(info);   clock();   stop();   delay1(5000); //这个延时一定要足够长,否则会出错。因为24c02在从sda上取得数据后,还需要一定时间的烧录过程。}/****************************密码锁程序模块********************************************************//*密码锁的延时*/void delay(unsigned char i)        //1ms延时{    uchar j,k;  for(j=i;j>0;j--)    for(k=114;k>0;k--);} /*数码管驱动显示函数*/void display(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f){   dula=0;                     //第一位显示   P0=table[a];   dula=1;   dula=0;   wela=0;   P0=0xfe;   wela=1;   wela=0;   delay(5);   P0=table[b];                // 第2位显示   dula=1;   dula=0;   P0=0xfd;   wela=1;   wela=0;   delay(5);   P0=table[c];                 // 第3位显示   dula=1;   dula=0;   P0=0xfb;   wela=1;   wela=0;   delay(5);   P0=table[d];                   // 第4位显示   dula=1;   dula=0;   P0=0xf7;   wela=1;   wela=0;   delay(5);   P0=table[e];                       // 第5位显示   dula=1;   dula=0;   P0=0xef;   wela=1;   wela=0;   delay(5);   P0=table[f];                        // 第6位显示   dula=1;   dula=0;   P0=0xdf;   wela=1;   wela=0;   delay(5);}void keyscan(){  {     P3=0xfe;    temp=P3;    temp=temp&0xf0;              if(temp!=0xf0)               //判断有无按键按下    {      delay(10);      if(temp!=0xf0)              //再次判断,消抖      {         temp=P3;        switch(temp)                  //扫描第一行        {          case 0xee:key=0;wei++;break;         //代表按键值          case 0xde:key=1;wei++;break;          case 0xbe:key=2;wei++;break;          case 0x7e:key=3;wei++;break;         }         while(temp!=0xf0)         {           temp=P3;           temp=temp&0xf0;           led=0;                           //每按一次亮一次灯         }         led=1;      }    }    P3=0xfd;                       //第二行    temp=P3;    temp=temp&0xf0;    if(temp!=0xf0)    {      delay(10);      if(temp!=0xf0)      {        temp=P3;        switch(temp)        {          case 0xed:key=4;wei++;break;          case 0xdd:key=5;wei++;break;          case 0xbd:key=6;wei++;break;          case 0x7d:key=7;wei++;break;         }         while(temp!=0xf0)         {           temp=P3;           temp=temp&0xf0;           led=0;         }         led=1;      }      }    P3=0xfb;    temp=P3;    temp=temp&0xf0;    if(temp!=0xf0)    {      delay(10);      if(temp!=0xf0)      {        temp=P3;        switch(temp)        {          case 0xeb:key=8;wei++;break;          case 0xdb:key=9;wei++;break;                       case 0xbb:genggai=1;wei=0;break;          case 0x7b:if(allow)ok=1;break;         }        while(temp!=0xf0)         {           temp=P3;           temp=temp&0xf0;           led=0;         }        led=1;      }      }      P3=0xf7;    temp=P3;    temp=temp&0xf0;    if(temp!=0xf0)    {      delay(10);      if(temp!=0xf0)      {        temp=P3;        switch(temp)        {          case 0xe7:retry=1;break;          case 0xd7:close=1;break;         }        while(temp!=0xf0)         {           temp=P3;           temp=temp&0xf0;          led=0;                                 }         led=1;      }      }}}void shumima()      //对按键采集来的数据进行分配{    if(!wanbi)    {    switch(wei)    {        case 1:new1=key;                 if(!allow)  a=11;     //输入时显示下划线               else a=key;  break;    //改密码期间显示当前所改的密码的值        case 2:new2=key;                if(a==11) b=11;                else b=key; break;        case 3:new3=key;                 if(a==11) c=11;                else c=key; break;        case 4:new4=key;                if(a==11) d=11;                else d=key; break;        case 5:new5=key;                 if(a==11) e=11;                else e=key; break;        case 6:new6=key;                 if(a==11) f=11;                else f=key;                wanbi=1;    break;    }    }}void yanzheng()      //验证密码是否正确{    if(wanbi)       //只有当六位密码均输入完毕后方进行验证    {    if((new1==old1)&(new2==old2)&(new3==old3)&(new4==old4)&(new5==old5)&(new6==old6))        allow=1;    //当输入的密码正确,会得到allowe置一    }}void main(){    init();             //初始化24C02/*格式化程序*///  write24c02(110,0x00);//  write24c02(111,0x00);//24c02的第110到115地址单元作为密码存储区//  write24c02(112,0x00);//  write24c02(113,0x00);//  write24c02(114,0x00);//  write24c02(115,0x00);    old1=read24c02(110);      old2=read24c02(111);    old3=read24c02(112);    old4=read24c02(113);    old5=read24c02(114);    old6=read24c02(115);    while(1)    {        keyscan();        shumima();        yanzheng();        if(allow)    //验证完后,若allow为1,则开锁        {            P1=0x00;            if(!genggai)                wanbi=0;                                    }        if(genggai)   //当更改密码键被按下会被置一        {            if(allow)    //若已经把锁打开,才有更改密码的权限            {                while(!wanbi)   //当新的六位密码没有设定完,则一直在这里循环                {                    keyscan();                    shumima();                    if(retry|close)  //而当探测到重试键或者关闭密码锁键被按下时,则跳出                    {   wanbi=1;                        break;                    }                    display(a,b,c,d,e,f);                }            }        }        if(ok)    //更改密码时,当所有六位新密码均被按下时,可以按下此键,结束密码更改,  其他时间按下此键无效        {                     ok=0;             wei=0;            genggai=0;            old1=new1;old2=new2;old3=new3;      //此时,旧的密码将被代替            old4=new4;old5=new5;old6=new6;            write24c02(110,old1);                //新密码写入存储区。            write24c02(111,old2);            write24c02(112,old3);            write24c02(113,old4);            write24c02(114,old5);            write24c02(115,old6);            a=10;b=10;c=10;d=10;e=10;f=10;        }        if(retry)                               //当重试按键被按下,retry会被置位        {        retry=0;         wei=0;        wanbi=0;        a=10;b=10;c=10;d=10;e=10;f=10;        new1=0;new2=0;new3=0;new4=0;new5=0;new6=0;              }        if(close)                               //当关闭密码锁按键被按下,close会被置位        {            close=0;            genggai=0;                          //所有变量均被清零。            wei=0;              wanbi=0;            allow=0;            P1=0xff;            a=10;b=10;c=10;d=10;e=10;f=10;            new1=0;new2=0;new3=0;new4=0;new5=0;new6=0;        }        display(a,b,c,d,e,f); //实时显示    }}
原创粉丝点击