要求:用单片机实现一个电子密码锁的功能,一开始设置密码,设置从0-f,任意多少位密码(只要不超过十位),设置成功,蜂鸣器响一下;接着是验证密码,如果输入错误三次,则暂停一段时间,不允许使用,如果输入成功(F键确认),则密码解锁,步进电机转动,如果按下E键,则停止转动。

连线:P0键盘,P2倒着接数码管,P3.0接蜂鸣器,P1接步进电机


/*****************************键盘码的顺序**********************************/
/*                        0xee,0xde,0xbe,0x7e    0-3                     */
/*                        0xed,0xdd,0xbd,0x7d    4-7                     */
/*                        0xeb,0xdb,0xbb,0x7b    8-b                     */
/*                        0xe7,0xd7,0xb7,0x77    c-f                     */
/*                  密码输入0-d;e,f 作为保留,f暂时用作确认                 */
/*                  连线:P0接键盘, P2接数码管(p2.7接H)                    */
/*************************************************************************/


#include<reg51.h>
#define uchar unsigned char
#define uint  unsigned int




sbit P30=P3^0;
uint a;
uint fre;//控制频率
uint flag;
uint time=0;  //控制中断时间
uchar count=0;//控制多少秒
uint t;
uint ff=0; //判断是否验证成功
uint fff=3;//判断用户输入次数
uint kaiguan=0;//判断电机是否开关的


/***********************步进电机****************************/
void delay(unsigned int t);
unsigned char code RUN[8]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9};  //步进电机相序表
//步进电机驱动
void  motor_ffw()
 {
     if(kaiguan==1)
    { 
       unsigned char i;
      
          for (i=0; i<8; i++)       //一个周期转3.75*8=30度
            {
              P1 = RUN[i]&0x1f;     //取数据
              delay(15);             //调节转速
            }
        }
 }
/***********************************************************/


//八段管显示码
code unsigned char LEDMAP[]={
    ~0x3f, ~0x06, ~0x5b, ~0x4f, ~0x66, ~0x6d, ~0x7d, ~0x07,
    ~0x7f, ~0x6f, ~0x77, ~0x7c, ~0x39, ~0x5e, ~0x79, ~0x71
};
uchar key;//键盘返回的一个码
uint i=0;//i用作数组循环
//存放初始密码
unsigned char mima[10]={0};
//存放缓冲密码
unsigned char shuru[10];
//存放×××数组
uint shuruz[10];
uint kaiguanz[10];//保存开关的
//延时函数
void delay(uint i)//延时函数
{
    uint j=0;
    while(i--)
    {
        for (j;j<100;j++){}
    }
}
//键盘扫描
uchar keyscan()//键盘扫描函数,返回一个键盘码
{
    uchar cord_h,cord_l;//行列值
    P0=0x0f;            //行线输出全为0
    cord_h=P0&0x0f;     //读入列线值
    if(cord_h!=0x0f)    //先检测有无按键按下
    {
        delay(100);        //去抖
        cord_h=P0&0x0f;    //读入列线值      
        if(cord_h!=0x0f)
        {
            P0=cord_h|0xf0;  //输出当前列线值
            cord_l=P0&0xf0;  //读入行线值
            return(cord_h+cord_l);//键盘最后组合码值
        }
    }return(0xff);     //返回该值
}
//将键盘码转化成0-f存放到缓冲区数组中
void inputBuf(uchar shuru[10])
{
    key=keyscan();//调用一次扫描键盘函数,获取返回的一个键码
    delay(500); //延时去抖动
    switch(key)
    {
        case 0xee://0
        {
            i=i%10;
            shuru[i]='0';
            shuruz[i]=0;
            P2=LEDMAP[shuruz[i]];
            delay(30000);
            i++;
            break;
        }
        case 0xde://1
        {
            i=i%10;
            shuru[i]='1';
            shuruz[i]=1;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0xbe://2
        {
            i=i%10;
            shuru[i]='2';
            shuruz[i]=2;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0x7e://3
        {
            i=i%10;
            shuru[i]='3';
            shuruz[i]=3;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0xed://4
        {
            i=i%10;
            shuru[i]='4';
            shuruz[i]=4;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0xdd://5
        {
            i=i%10;
            shuru[i]='5';
            shuruz[i]=5;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0xbd://6
        {
            i=i%10;
            shuru[i]='6';
            shuruz[i]=6;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0x7d://7
        {
            i=i%10;
            shuru[i]='7';
            shuruz[i]=7;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0xeb://8
        {
            i=i%10;
            shuru[i]='8';
            shuruz[i]=8;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0xdb://9
        {
            i=i%10;
            shuru[i]='9';
            shuruz[i]=9;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0xbb://a
        {
            i=i%10;
            shuru[i]='a';
            shuruz[i]=10;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0x7b://b
        {
            i=i%10;
            shuru[i]='b';
            shuruz[i]=11;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0xe7://c
        {
            i=i%10;
            shuru[i]='c';
            shuruz[i]=12;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0xd7://d
        {
            i=i%10;
            shuru[i]='d';
            shuruz[i]=13;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0xb7://e
        {
            i=i%10;
            shuru[i]='e';
            shuruz[i]=14;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break;
        }
        case 0x77://f
        {
            i=i%10;
            shuru[i]='f';
            shuruz[i]=15;
            P2=LEDMAP[shuruz[i]];
            delay(20000);
            i++;
            break; //密码都是以f结尾的
        }
    }
}


 //蜂鸣器响
 void beep(uint t)
 {
     time=0;
      for(time;time<t;time++)
   {
           P30=1;
        delay(100);
        P30=0;
        delay(100);
   }
 }
//密码输入错误报警
void cuowubaojin()
{
     uint k=3;
    uint i;
    while(k--)
    {
        i=50;
        while(i--)
        {
        P30=1;
        delay(200);
        P30=0;
        delay(200);
        }
        i=50;
        while(i--)
            delay(400);
    }
}


  //检查密码成功电机转动
 void chenggongzhuandong()
 {


    //j=0;
    while(1)
    {
      kaiguan=1;//打开电机
      inputBuf(kaiguanz);  //监听键盘
      if(key==0xb7)
      {
           kaiguan=0;//关闭电动机
        delay(10);
        P2=0xff;//关闭数码管显示
        delay(10);
        break;
      }
      motor_ffw(); //调用旋转处理函数
      delay(20);
     }
 }


//主函数
void main()
{
    uint j=0,n=3;     //i用于输入密码的次数
    P2=0xff;
///////////设置密码,保存在mima[10]数组中/////////////////////////////////////////
    while (1)
    {
        inputBuf(mima);
        if(key==0x77)
        {
            P2=0xff;
             break;
        }
    }
    //设置成功蜂鸣器响一下
    j=0;


    for(j;j<5;j++)
    {
       beep(8);
    }
    
////////////验证密码,保存在shuru[10]中/////////////////////////////////////////////    


    i=0;//从头开始输入
    
    //密码验证,错误不能超过三次
    while(1)
    {
         inputBuf(shuru);
        if(key==0x77&&n>0)      //fff判断输入密码的次数
        {
            P2=0xff;//关闭数码管
            j=0;
            ff=1;                  //ff判断是否验证成功
               //比较mima[]和shuru[],如果不对,则继续比较
            for(j;j<10;j++)
            {
                 if(mima[j]!=shuru[j])
                {
                    ff=0;
                    cuowubaojin();//失败蜂鸣器响
                    i=0;//从头开始输入到数组里
                    break;
                }
            }
            if(j==10)
            {
                 ff=1;//将标志位设为true;
                n=1;
            }
            n--;            
        }
        if(n==0)
        {
            break;
        }
    }


    if(ff==1)
    {
         chenggongzhuandong();  //电动机转动
    }
    P2=0xff;
    j=0;    //密码输入错误暂停使用
    if(ff==0)
    {
        for(j;j<250;j++)
        {
            
             delay(1000);
        }
    }    
}