基于单片机的智能密码锁

发布者:sjjawx831最新更新时间:2019-02-19 来源: eefocus关键字:单片机  智能密码锁 手机看文章 扫描二维码
随时随地手机看文章

该密码锁控制器 ,键盘上有0-9个数字按键,功能键:确认和取消等,可设置复合键。密码的位数及密码可以任意设定,,当输入数字和设置的密码相同的时候,锁打开,否则无法打开。采用IIC通信方式,密码锁的密码掉电不丢失。


#include

#include

#define uint unsigned int

#define uchar unsigned char


uchar old1,old2,old3,old4,old5,old6; //原始密码000000

uchar 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;  //各个状态位,默认初始值为0


sbit 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

}


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); //实时显示

    }

}



关键字:单片机  智能密码锁 引用地址:基于单片机的智能密码锁

上一篇:89c51 CPU时序
下一篇:基于51单片机—多功能秒表

推荐阅读最新更新时间:2024-03-16 16:24

聊聊单片机8051的发展史
我敢保证,我们当中的大多数人,在读书的时候,玩的第一个芯片,基本上都是8051的。利用它来编各种跑马灯,七段数码管,这是平常到不能再平常的事情了。相信大家对“MOV”应该不陌生吧? 可能现在很多人已经不玩51了,改行玩DSP,玩ARM,玩FPGA了,但毫无疑问8051才是我们的初恋。 今天我们聊聊8051的发展史,还有顺便说一下国内一个做51芯片的“奇葩”公司——宏晶科技(STC)。 8051是Intel的发明 谈8051,就不得不说一下单片机,单片机诞生于1971年,经历了SCM、MCU、SoC三大阶段,早期的SCM单片机都是8位或4位的。其中最成功的是INTEL的8051,此后在8051上发展出了MCS51系列MCU系
[单片机]
聊聊<font color='red'>单片机</font>8051的发展史
关于单片机外部中断的扩展
单片机外部中断有限,仅有两个,在某些系统设计中可能会不够用。这里给大家推荐一个比较简单的扩展外部中断的方法。灵感来至于单片机键盘设计! 在有些键盘设计中,如果在程序中采用轮询的方法在检测按键,会花费大量的cpu资源,特别是还要进行大量的数据处理的情况下。所以很多按键设计都加入了中断,上一篇博文里的按键设计其实都可以加入中断,这样可以更好的利用cpu资源。 一般在按键设计中只会用一个中断,但是却可以控制n多的按键。每一个按键的按下都相当于产生了一个中断,所以利用这个原理,我们也可以 无限 的扩展外部中断。一个简单的电路图如下: 这样当外部送来一个低电平的信号时,通过与非门后将产生一个中断信号,这个信号可以送到单片机的外部中断
[单片机]
单片机STM32时钟图文理解
其中,高速时钟(HSE和HSI)提供给芯片主体的主时钟.低速时钟(LSE和LSI)只是提供给芯片中的RTC(实时时钟)及独立看门狗使用,图中可以看出高速时钟也可以提供给RTC。内部时钟是在芯片内部RC振荡器产生的,起振较快,所以时钟在芯片刚上电的时候,默认使用内部高速时钟。而外部时钟信号是由外部的晶振输入的,在精度和稳定性上都有很大优势,所以上电之后我们再通过软件配置,转而采用外部时钟信号. 高速外部时钟(HSE):以外部晶振作时钟源,晶振频率可取范围为4~16MHz,我们一般采用8MHz的晶振。 高速内部时钟(HSI): 由内部RC振荡器产生,频率为8MHz,但不稳定。 低速外部时钟(LSE):以外部晶振作时钟源,主
[单片机]
<font color='red'>单片机</font>STM32时钟图文理解
车规MCU的功能安全库是什么
功能安全库(Safety Library) 车规MCU的功能安全库(Safety Library)是为了满足汽车电子系统的功能安全要求而设计的软件模块集合。它提供了一系列的功能安全功能和算法,用于监测和控制系统的运行,以确保系统在发生故障时能够安全地进入故障状态或安全地恢复正常工作。 车规MCU的功能安全库的核心功能包括: 故障检测和诊断:功能安全库可以监测系统的各个部分是否正常工作,并在发现故障时进行诊断和报警。它可以检测硬件故障、软件错误和通信故障等,并提供相应的故障诊断信息。 故障容错和恢复:功能安全库可以通过冗余设计和错误处理算法来提高系统的容错性。它可以检测和纠正错误,或者在发生故障时切换到备用模式,以确保系统的可靠
[嵌入式]
车规<font color='red'>MCU</font>的功能安全库是什么
AVR单片机教程——点亮第一个LED
做了这么多准备,我们终于可以开始用开发板做点事了。 单片机编程与计算机编程有一些不同点。程序都要有零个或多个输入、一个或多个输出,这是两者都有的,但是计算机编程的输入输出主要靠控制台,而单片机没有。 单片机的英文是microcontroller,主要作控制用途,它对设备的控制就是它的输出,从设备读取的信息就是它的输入。计算机编程中,提供了scanf、printf等函数来做输入输出,单片机虽然也有这一些函数,但它们往往是在串口上收发数据,最终还是在电脑上显示的。单片机对它连接的设备的控制,主要通过对寄存器(register)的操作实现。对寄存器的直接操作涉及到许多底层知识,我已经用一些函数把这些底层的东西封装好了,你只需要调
[单片机]
AVR<font color='red'>单片机</font>教程——点亮第一个LED
一个简单的51单片机操作系统的实现
复习到操作系统这本书,在看到进程管理的时候,想起以前费了相当大的时间去做一个属于自己的操作系统,结果什么都没弄出来。 趁着看到这个章节,又一次地萌生了这个想法,于是网上各种寻找资料。发现现在的大多数操作系统都已经比较完善,换而言之,就是太庞大。无法去理解,无法自己照搬原文去弄一个属于自己的操作系统出来。 机缘偶得之下,发现了一篇关于在单片机下面实现一个实时操作系统的文章, 即《建立一个属于自己的AVR的RTOS》,这篇文章比起讲什么操作系统原理、unix内核分析、linux内核分析、xx内核分析等等来说,简单明了了很多(有兴趣的同学们可以去研究一下这篇文章)。在参考这篇文章以及在51单片机下面使用汇编语言编程,以及众多网上资
[单片机]
一个简单的51<font color='red'>单片机</font>操作系统的实现
PIC单片机人机接口模块独立式按键的元器件选型
独立式键盘就是一个按键对应着一个端口输入,每一个按键都有一个按键电路来区分其是否按下。下面将首先介绍按键的结构,然后再介绍按键的外扩电路,以便于读者对独立式键盘有一个清晰和完整的认识。   按键分为单路和多路,在实际的应用中,按键和开关的功能是基本相同的,现在将基本的按键及开关汇总,如图所示。   图 基本按键和开关   下面的按键及开关中不仅有单路的、双路的,还有多路的。有些开关是选择开关,一般选择开关只有两路,不是第一路就是第二路;另外,还有一选二的开关,即有两路开关,可以选择两路同时开或关。   这些例子基本上涵盖了实用的按键和开关,另外还需注意,尽管按键或者开关的电路相同,但是其形状和指标都不同。例如,平时
[嵌入式]
采用二维模糊控制器和C8051单片机实现室内自然采光系统的设计
1、 引言 从远古的篝火、油灯到蜡烛、白炽灯,再到今天千家万户的荧光灯,人类已经基本适应了人工光源的室内照明环境。但是由于千万年来的环境影响,自然光仍然是人类最习惯、感觉最舒适的光源,自然采光一直受到建筑师和照明设计师的高度重视。当今社会建筑的节能环保需求更对自然采光照明提出了进一步的要求。《建筑采光设计标准》 中的国家技术经济政策指出: 建筑设计要充分利用天然光,创造良好的光环境。 对室内照明自然采光的研究具有重要的意义: (1) 资料表明,照明用电占整个商业建筑能耗的25 - 40% ,而自然采光在特定的情况下可以节省52% 的照明用电,大大节约了能源。 (2) 相关研究表明,人在自然光条件下工作,可以增加满意度和提高工作
[单片机]
采用二维模糊控制器和C8051<font color='red'>单片机</font>实现室内自然采光系统的设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved