定时中断法实现1ms定时扫描,主程序执行按键识别矩阵键盘接在P0口,八位一体数显的位控由P2口完成经过三极管方向驱动共阳级,P1口通过245驱动段码,在仿真图里面用反相器4069替代三极管驱动
单片机源程序如下:
- #include<reg51.h>
- sbit SPEAK=P3^7;
- sbit LED_RED=P3^6; // 红色LED点亮表示密码错误
- sbit LED_GREEN=P3^5;// 绿色LED点亮表示密码正确
- bit flag=0; // 标志位
- unsigned char data buffer[8]={0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF}; //缓存器存放输入的密码,初始"-"
- unsigned char data keycode[8]={1,2,3,4,5,6,7,8}; // 原始密码
- unsigned char code led[]={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
- 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E };//共阳数显段码
- void delay(unsigned int i) // 延时
- {
- unsigned int k;
- for(k=0;k<i;k++);
- }
- // 1毫秒中断,8位一体数显扫描输出显示函数
- unsigned char wei=0x01,j=0;
- void timer_0 ()interrupt 1
- {
- TH0=(65536-1000)/256;
- TL0=(65536-1000)%256;
- P1=0XFF;
- if(buffer[j]==0xBF)P1=0XBF; // 若显示"-",则直接输出不查表
- else if(buffer[j]==0xff)P1=0Xff; // 此处为密码输入时设置的消隐信号
- else P1=led[buffer[j]]; // 若显示数字,则根据号码查表
- P2=~(wei<<j);
- j++;
- if(j==8){j=0; wei=0x01;}
- }
- //键盘扫描函数 具有返回值
- char key_scan()
- {
- unsigned char i,temp,m,n;
- bit find=0;
- P0=0x0f; // 向所有列线输出高电平
- i=P0;
- i&=0x0f; // 屏蔽高四位,取行信号
- if(i!=0x0f) //判断是否有按键按下
- {
- delay(120);
- i=P0;
- i&=0x0f;
- if(i!=0x0f)
- {
- for(i=0;i<4;i++) //逐列判断
- {
- P0=~(0x10<<i); // 列输出低电位,如果有按键按下则对应读入的数据为低电平
- temp=~P0;
- temp=temp&0x0f; // 屏蔽高四位读行值,若有按键按下,则取反后出现高电平
- if(temp!=0)
- {
- m=i;
- find=1;
- switch(temp)
- {
- case 0x01:n=0;break;
- case 0x02:n=1;break;
- case 0x04:n=2;break;
- case 0x08:n=3;break;
- default:break;
- }
- break;
- }
- }
- }
- }
- if(find==0)return -1;
- else return(n*4+m);
- }
- // 8位密码输入函数
- void key_num()
- {
- unsigned char key,i,m,n=0;
- while(1) // 此方法可以检测排除非0-9号按键
- {
- key=key_scan();
- if(key==-1)continue;
- else if(key>=0&&key<=9)
- {
- for(m=8;m>0;m--)
- buffer[m]=buffer[m-1]; // 为了达到号码移位输入的效果,采用后一个写入前一个地址的方法
- buffer[0]=key; // 新输入的号码永远放在第0个位置
- P0=0X0F;
- while(P0!=0X0F); // 按键弹起检测
- n++;
- }
-
- if(n==8){n=0;break;}
- }
-
- for(i=0;i<8;i++) // 8位密码与原始密码进行比对,完全一致的时候标志位置1
- {
- if(buffer[i]!=keycode[7-i]) // 此处由于输入密码移位,所以逆取
- {
- flag=0; // 一旦出现密码比对不正确,立刻终止比对,并标志位置0
- break;
- }
- else flag=1;
- }
- }
- // 重设密码函数
- void key_reset()
- {
- unsigned char key,i,n=0;
- LED_GREEN=0; // 红绿均点亮,表示重设密码
- LED_RED=0;
- while(1)
- {
- key=key_scan();
- if(key==-1)continue;
- else if(key!=-1)
- {
- if(key>=0&&key<=9)
- {
- keycode[n]=key;
- buffer[n]=0xff; // 密码输入的时候,显示器消隐
- P0=0X0F; // 键盘重新读入行数据
- while(P0!=0x0f); // 如果行数据未出现低电平,表明按键全部弹起,此处一定要做按键弹起检测,否则多次加载数据
- n++;
- }
- }
- if(n==8){n=0;break;}
- }
- while(1)
- {
- key=key_scan();
- P0=0X0F; // 键盘重新读入行数据
- while(P0!=0x0f);
- if(key==11)break; // 11按键按下退出
- }
- LED_GREEN=1; // 红绿均灭,表示重设密码结束,可以输入密码打开密码锁
- LED_RED=1;
- for(i=0;i<8;i++) // 缓存区域数据全部清除,用"-"替代
- {
- buffer[i]=0xBF;
- }
- }
- // 输入密码结果函数
- unsigned char k=0;
- void key_result() // 密码输入结果显示,正确时蜂鸣器响绿色LED点亮,密码错误,红色LED点亮
- {
- unsigned char key,i;
- if(flag==0)
- {
- k++;
- if(k!=3) //密码输入未达到三次,可继续输入
- { LED_RED=0;
- LED_GREEN=1;
- delay(50000);
- for(i=0;i<8;i++) // 缓存区域数据全部清除,用"-"替代
- {
- buffer[i]=0xBF;
- }
- }
- else // 密码错误为三次,锁定,11号按键解锁
- {
- k=0;
- while(1)
- {
- key=key_scan();
- P0=0X0F; // 键盘重新读入行数据
- while(P0!=0x0f);
- LED_RED=~LED_RED; //红绿LED闪烁蜂鸣器鸣响报警
- LED_GREEN=~LED_GREEN;
- SPEAK=~SPEAK;
- delay(1000);
- if(key==11)
- {
- LED_GREEN=1;
- LED_RED=1;
- SPEAK=1;
- break; // 11按键按下退出
- }
- }
- for(i=0;i<8;i++) // 缓存区域数据全部清除,用"-"替代
- {
- buffer[i]=0xBF;
- }
- }
- }
-
- else // 密码输入正确可重置密码或直接退出
- {
- LED_GREEN=0;
- LED_RED=1;
- SPEAK=0;
- delay(50000);
- SPEAK=1;
- k=0; // 密码错误次数也要清零,否则会出现密码正确但不重设退出后两次密码错误就报警
- flag=0;// 标志位清零
- for(i=0;i<8;i++) // 缓存区域数据全部清除,用"-"替代
- {
- buffer[i]=0xBF;
- }
-
- while(1)
- {
- key=key_scan();
- P0=0X0F; // 键盘重新读入行数据
- while(P0!=0x0f); // 等待按键弹起
- if(key==10) {key_reset();break;} // 按下10号键,重设密码
- else if(key==11){LED_RED=1;LED_GREEN=1;break;} // 11号按键按下退出,其他按键无效
- continue; //此处为了防止其他按键的按下而设置
- }
- }
- }
- void main()
- {
- TMOD=0X01;// 初始化,开启1毫秒定时器中断
- ET0=1;
- EA=1;
- TH0=(65536-1000)/256;
- TL0=(65536-1000)%256;
- TR0=1;
- LED_RED=1;
- LED_GREEN=1;
- SPEAK=1;
-
- while(1)
- {
- key_num();
- key_result();
- }
- }
复制代码
下载:
八位数码管密码锁.zip
(83.68 KB, 下载次数: 90)
|