這個程序是為了實現基於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);
}
}
}
}
}