这个程序是为了实现基于51单片机的电子密码锁,目前,程序解决了最重要之一的输入的密码和保存的正确密码相比较的问题。
通过定义了两个数组:
uchar table2[6]; //临时密码保存
uchar password[6]="123456"; //进门密码
将输入的密码写入到table2[]中
有一点需要特别注意:
因为我写到table2[]数组内的是ASCII值的0-9,而ASCII值的0-9对应的符号却是NUT,SOH...(省略)
(ASCII码参考表https://tool.oschina.net/commons?type=4)
所以在刚开始调试时,LCD1602屏幕输出的总是奇怪的字符,而不是我想要的0-9,通过查询ASCLL码表可以知道字符(0-9)对应的数值是48-57,所以我通过定义了一个新的数组,uchar smgduan[10]={48,49,50,51,52,53,54,55,56,57};
以及lcd_write_data(smgduan[table2[i]]);的方式,实现了在LCD上输出字符0-9的功能。
在最后做两个数组比较时,开始同样出现了这个情况,因为数字1和字符1对应的ASCII值不同,所以password[i]不等于table2[i],需要进行转换,我的方式的是password[i]==smgduan[table2[i]];
罗里吧嗦这个多,主要还是给未来的自己看看,当初犯得错误多么低级。
---------------------------------------------------分割线-----------------------------------------------------------------------------------
下一版改进考虑把重复按键选择数字改成矩阵按键,加进些其他的功能。
---------------------------------------------------分割线-----------------------------------------------------------------------------------
程序部分:
/*
这个方案是我写基于51单片机的电子密码锁过程中,未完成全部功能的程序。
这个程序实现了通过重复按K1选择数字,然后按K2确认。将确认的值赋给临时比较数组table2[]
当输入6位数字后,会开始比较默认密码,相同就在屏幕上输出”welecome“ ,
如果错误,输出wrong
*/
#include"reg52.h"
#define GPIO_KEY P1
sbit lcd_en=P2^7; //普中科技开发板:LCD使能管脚。根据实际情况更改
sbit lcd_rw=P2^5; //LCD数据命令选择端
sbit lcd_rs=P2^6; //lcd读写选择端
sbit k1=P3^1; //独立按键1
sbit k2=P3^0; //输入完密码后,确认键
sbit led=P2^0;
sbit beep=P1^5;
typedef unsigned char uchar;
typedef unsigned int uint;
uchar code table1[]="password:";
uchar code welecome[]="welecome!";
uchar code wrong[]="wrong!";
uchar table2[6];
uchar password[6]="123456";
uchar code shuzixuanze[]="0123456789"; //通过按键k1的选择数字
uchar a=0,c,p=0,s=0,flag=1;
/*a:按键k1判断标志,c:按键k2判断标志 p:每位数字的输入 s:密码输入好后的判断标志,flag:密码比对标志*/
uchar smgduan[10]={48,49,50,51,52,53,54,55,56,57};//0~9在ASCLL码表中对应的值
void delay1ms(uchar c) //延时1ms
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
void delay(uchar i) //延时函数
{
while(i--);
}
void keypress() //按键按下判断,
{
if(k1==0) //k1是数字选择键
{
delay(100); //消抖
if(k1==0)
{
a=1; //把a置1,给后面的函数用
}
while(!k1); //消抖
}
if(k2==0) //k2是确认键
{
delay(100);
if(k2==0)
{
c=1;
delay1ms(10);
}
while(!k2);
}
}
//通过重复按K1改变数值,然后赋值给table2[]
void lcd_write_com(uchar com) //lcd写命令 不懂了重新翻书看
{
lcd_en=0;
lcd_rw=0;
lcd_rs=0;
P0=com;
delay1ms(1);
lcd_en=1;
delay1ms(5);
lcd_en=0;
}
void lcd_write_data(uchar date) //lcd写数据
{
lcd_en=0;
lcd_rw=0;
lcd_rs=1;
P0=date;
delay1ms(1);
lcd_en=1;
delay1ms(5);
lcd_en=0;
}
void lcd_init() //LCD初始化
{
lcd_write_com(0x38);
lcd_write_com(0x0c);
lcd_write_com(0x06);
lcd_write_com(0x01); //清屏
}
void main()
{
uchar i;
lcd_init();
for(i=0;i<=8;i++) //LCD上输出一个抬头:password:
{
lcd_write_data(table1[i]);
delay1ms(1);
}
lcd_write_com(0x80+0x40); //lcd上换行
while(1)
{
uchar i;
keypress();
if(a==1) //k1按键按下,开始选择数字
{
a=0;
lcd_write_com(0x04);
lcd_write_com(0x01); //清屏了,空空的屏幕
lcd_write_data(shuzixuanze[p]); //p的初始值为0 ,屏幕上显示对应的数字
p++; //不管选没选,p都加1了,所以后面写入到临时密码保存数组时,p要减一
if(p>9) //10个数字都选了一遍,错过了就重头开始呗。
{
p=0;
}
}
if(c==1) //选定需要的数字了
{
table2[s]=p-1; //把p-1写进临时密码保存数组,为甚p-1?回去p++那行看解释。
delay1ms(10); //好像有没有延时都无所谓。
s++; //选定1为s就+1,直到选好6位密码(s==6的原因)
p=0; //选好了一位密码,下一位又重头开始选
c=0; //c不置0这个函数就跳不出来了
lcd_write_com(0x01); //清屏
}
if(s==6) //虽然初始值是0,s=5时就6位了,但是还是要用s==6,原理同p
{
for(i=0;i<=5;i++)
{
lcd_write_com(0x06);
lcd_write_data(smgduan[table2[i]]); //把输入的密码对应的字符打到屏幕看一看
}
s=0;
//下面立了个flag标志位,用于判断,每位密码是不是都一样。
for(i=0;i<=5;i++)
{
flag=flag&&(password[i]==smgduan[table2[i]]);
}
if(flag)//如果比较全部相同,标志位置1
{
delay1ms(2000); //这里延时2s,主要是能看看清前面屏幕输出的6位密码,
lcd_write_com(0x01);
for(i=0;i<=8;i++) //欢迎
{
lcd_write_data(welecome[i]);
delay1ms(1);
}
flag=0;
}
else //密码错了
{
delay1ms(2000);
lcd_write_com(0x01);
for(i=0;i<=5;i++)
{
lcd_write_data(wrong[i]);
delay1ms(1);
}
}
}
}
}