专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

AVR单片机密码锁程序(原创)

作者:佚名   来源:本站原创   点击数:  更新时间:2012年06月02日   【字体:
这是一款用AVR单片机实现的密码锁,它分别由硬件16个矩阵键盘、数码管以及蜂鸣器组成的。系统正确的初始密码为0123。当我们按下按键次数在4次以内,系统才判断密码对与否,当输入密码正确时,蜂鸣器报响起,即表示密码是正确的,当我们按下按键的次数超过4次,即使按下的密码正确,蜂鸣器也不响,还有按下密码顺序必须是0123,如果按下0213或者是其它的,都不能正常开蜂鸣器。如果按键次数超过4次了,密码就无法正常输入了,此时只要按下第16个按键时,就可以回到初始状态,即清除我们以前按键按下的次数,(因为密码输入时必须在4次以内完成的,超过了4次你怎么输,也进入密码判断模式)此时就可以重新输入正确的密码了。另外当按下按键时,可以在数码管上显示我们按下的数,以方便我们看我们按下的数是否正确。
硬件连接:矩阵按键接PD口,数码管段接PB口,位控制端接PC4位,蜂鸣器接PA1口。
以下是完整程序下载地址:http://www.51hei.com/f/mmsavr.rar


#include<iom16v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
#define setb(val,bitn) (val|=(1<<(bitn)))//设置某IO口某位为1,即设置IO口进行位操纵
#define clr(val,bitn) (val&=~(1<<(bitn)))//设置某IO口某位为0  即设置IO口进行位操纵
#define get(val,bitn) (val&(1<<(bitn)))//读取某位状态如if(get(PORTC,7))即判断PC7口是否为1 即设置IO口进行位操纵
#pragma data:code//定义程序存在ROM里面
uchar yin,yin1,yin2,yin3;//4位密码初始变量
uchar qing,qing1,qing2,qing3;//4位密码比较变量
uchar num;//按键按下次数变量
uchar temp;//比较标志位变量,即按下后比较变量与初始密码变量比较,如果是相等,则些标志位生效,它自动变量加1
const table[]={
0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,
0x8e,0xff
};
/***********************************************/
/*******************延时子程序******************/
/***********************************************/
void delay(uint z)
{
   uint x,y;
  for(x=0;x<50;x++)
  for(y=0;y<z;y++);
}
/***********************************************/
/*****************蜂鸣器响子程序****************/
/***********************************************/
void bbt()
{
   setb(DDRA,1);
  clr(PORTA,1);
  delay(2550);
  setb(PORTA,1);
  delay(2550);
}
/***********************************************/
/*******************显示子程序******************/
/***********************************************/
void xian(uchar num)
{
  uchar i;
 PORTB=table[num];
 PORTC=0x00;//打开位选端
}
/***********************************************/
/***************按键按下处理程序***************/
/***********************************************/
uchar key_press()
{
     uchar i;
     DDRD=0XFF;//设置PD口全为输出
  PORTD=0XF0;//设置PD高四位为高电平,以便进行判断
  DDRD=0X0F;//设置高4位为输入,低4位为输出
  i=PIND;//读出IO口状态
  if(i==0XF0)//如果它等于0XF0就执返回0
  {
    DDRD=0XFF;//将IO口值读回来
    return 0;
  }
  else//否则它就执返回1
  {
    DDRD=0XFF;
    return 1;
  }
}
/***********************************************/
/***************按键键值处理程序***************/
/***********************************************/
uchar key_scan()
{
    uchar key,i=0X7F,j;//将变量I设置为01111111B
 if(key_press())//判断按键是否被按下了
 {
      delay(10);//如果被按下了,消下抖
   if(key_press())//再次判断下按键是否被按下了
   {

     do//先执行一次
  {
   i=(i<<1|i>>7);/*将变量I内容左移1位,11111110
   然后将I右移7位,11111110,即实现11111110
   11111101 11111011 11110111*/
   PORTD=i;//将移位后的值给PD口
   DDRD=0X0F;//将PD口高位设为输入,低位设为输出
   key=PIND;//将IO口高位值读一下
   j=key&0XF0;//只需要读高4位
    }
  while(j==0XF0);//如果按键没有按下,则再执行上面的do语句

  while(key_press());//如果有按下则释放一下
  num++;//计数改变变量值
  //if(num>3)
  //num=0;
  switch(key)//确定有按键按下了就判断下到底是哪个值
  {
   
          case 0xEE:qing=0;
      key=0x0;
   break;
      case 0xDE:qing1=1;
      key=0x1;
   break;
      case 0xBE:qing2=2;
      key=0x2;
   break;
      case 0x7E:qing3=3;
      key=0x3;
   break;
      case 0xED:
      key=0x4;
   break;
      case 0xDD:
      key=0x5;
   break;
      case 0xBD:
      key=0x6;
   break;
     case 0x7D:
      key=0x7;
   break;
      case 0xEB:
      key=8;
   break;
      case 0xDB:
      key=9;
   break;
      case 0xBB:
      key=0xA;
   break;
      case 0x7B:
      key=0xB;
   break;
      case 0xE7:
      key=0xC;
   break;
      case 0xD7:
      key=0xD;
   break;
            case 0xB7:
      key=0xE;
   break;
      case 0x77:
      key=0xF;
   break;
  }
  }
  }
  return key;//返回按键值
}
/******************************************************/
/*******************密码判断子程序*********************/
/******************************************************/
void mi()
{
   switch(num)
   {
     case 1://只有按键标志位为1时,说明按下的是第1次
   if(qing==yin)//此时第1位密码比较变量与初始密码变量比较,是否相等
   {
     temp++;//如果相等则将比较标志位加1,以作记号
    qing=0xff;//作完记号后,将比较变量赋值,以便它再次记数标志位变量
   }
   break;//返回
   case 2://只有按键标志位为2时,说明按下的是第2次
   if(qing1==yin1)
   {
     temp++;
    qing1=0xff;
   }
   break;
   case 3://只有按键标志位为3时,说明按下的是第3次
   if(qing2==yin2)
   {
     temp++;
    qing2=0xff;
   }
   break;
   case 4://只有按键标志位为4时,说明按下的是第4次
   if(qing3==yin3)
   {
     temp++;
    qing3=0xff;
   }
   break;
   }
   if(temp==4)//如果比较标志位变量为4,则说明以上4个密码是对的,此时蜂鸣器响起
   bbt();//调用蜂鸣器响起子程序
}
/***********************************************/
/*******************主程序*********************/
/***********************************************/
void main()
{
   uchar ik=16;//定义局部变量
  temp=0;//蜂鸣器计数变量变0
  num=0;//计数器清0
  yin=0;//密码1
  yin1=1;//密码2
  yin2=2;//密码3
  yin3=3;//密码4
  qing=qing1=qing2=qing3=0;//密码比较变量清0
   DDRB=0xff;//设置PB口为输出
  DDRC=0xff;//设置PC口为输出
  while(1)
  {
     ik=key_scan();//将按键返回值给变量IK
/*****************第15个键按下时处理的程序*****************/
   if(ik==15)//如果按下了第15个键,就将按下的次数清0,即进入初始化
   {
   num=0;//清0计数器
   temp=0;//清0计数器
   qing=qing1=qing2=qing3=0;//密码比较变量清0
   }
/*****************数码管显示部分*****************/
     if(ik<16)//如果返回值小于16就在数码
   xian(ik); //调用显示子程序
   else//如果返回值不小于16,就显示黑屏
   xian(16);
/*****************密码判断部分*****************/
                 mima();
  }
}

关闭窗口

相关文章