標題: 51單片機1602顯示按鍵密碼鎖 [打印本頁]
作者: weiwei315 時間: 2018-6-22 14:31
標題: 51單片機1602顯示按鍵密碼鎖
我按照這個程序做出來的,總是輸入密碼錯誤,不知道是啥問題,麻煩大神幫看看是啥問題。
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char // 以后unsigned char就可以用uchar代替
#define uint unsigned int // 以后unsigned int 就可以用uint 代
sbit SDA_P = P2^1; // 定義了AT24C02的SCL引腳
sbit SCL_P = P2^0; // 定義了AT24C02的SDA引腳
sbit LcdEn_P = P2^5; // 1602液晶的EN管腳
sbit LcdRw_P = P2^6; // 1602液晶的RW管腳
sbit LcdRs_P = P2^7; // 1602液晶的RS管腳
sbit Beep_P = P3^3; // 蜂鳴器引腳
sbit Relay_P = P3^2; // 繼電器引腳
uchar ArrCodeBuff[6]; // 密碼輸入緩沖區
uchar ArrCodeUnlock[6]; // 解鎖密碼
uchar ArrCodeTemp[6]; // 臨時數組(修改密碼時會用到)
uchar ArrCodeAdmin[6]={1,2,3,1,2,3}; // 管理員密碼
uchar row,column; // 液晶的當前行列坐標
uchar inputNum=0; // 輸入的密碼位數
uchar inputMode=1; // =1輸入解鎖密碼,=2輸入修改密碼1,=3輸入解鎖密碼2
uchar errTime=0; // 密碼輸入錯誤的次數
/*********************************************************/
// 毫秒級的延時函數,time是要延時的毫秒數
/*********************************************************/
void DelayMs(uint time)
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<112;j++);
}
/*********************************************************/
// 延時6微秒
/*********************************************************/
void Delay6us()
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
/*********************************************************/
// 1602液晶寫命令函數,cmd就是要寫入的命令
/*********************************************************/
void LcdWriteCmd(uchar cmd)
{
LcdRs_P = 0;
LcdRw_P = 0;
LcdEn_P = 0;
P0=cmd;
DelayMs(2);
LcdEn_P = 1;
DelayMs(2);
LcdEn_P = 0;
}
/*********************************************************/
// 1602液晶寫數據函數,dat就是要寫入的數據
/*********************************************************/
void LcdWriteData(uchar dat)
{
LcdRs_P = 1;
LcdRw_P = 0;
LcdEn_P = 0;
P0=dat;
DelayMs(2);
LcdEn_P = 1;
DelayMs(2);
LcdEn_P = 0;
}
/*********************************************************/
// 1602液晶初始化函數
/*********************************************************/
void LcdInit()
{
LcdWriteCmd(0x38); // 16*2顯示,5*7點陣,8位數據口
LcdWriteCmd(0x0C); // 開顯示,不顯示光標
LcdWriteCmd(0x06); // 地址加1,當寫入數據后光標右移
LcdWriteCmd(0x01); // 清屏
}
/*********************************************************/
// 液晶光標定位函數
/*********************************************************/
void LcdGotoXY(uchar y, uchar x)
{
// 第一行
if(y==0)
LcdWriteCmd(0x80+x);
// 第二行
if(y==1)
LcdWriteCmd(0x80+0x40+x);
row=y;
column=x;
}
/*********************************************************/
// 液晶輸出字符串函數
/*********************************************************/
void LcdPrintStr(uchar *str)
{
while(*str!='\0')
LcdWriteData(*str++);
}
/*********************************************************/
// IIC起始函數
/*********************************************************/
void IIcStart()
{
SDA_P=1;
Delay6us();
SCL_P=1;
Delay6us();
SDA_P=0;
Delay6us();
}
/*********************************************************/
// IIC終止函數
/*********************************************************/
void IIcStop()
{
SDA_P=0;
Delay6us();
SCL_P=1;
Delay6us();
SDA_P=1;
Delay6us();
}
/*********************************************************/
// IIC寫一個字節
/*********************************************************/
void IIcWriteByte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
dat=dat<<1;
SCL_P=0;
Delay6us();
SDA_P=CY;
Delay6us();
SCL_P=1;
Delay6us();
}
SCL_P=0;
Delay6us();
SDA_P=1;
Delay6us();
}
/*********************************************************/
// IIC讀一個字節
/*********************************************************/
uchar IIcReadByte()
{
uchar i,temp,dat=0;
SCL_P=0;
Delay6us();
SDA_P=1;
Delay6us();
for (i=0;i<8;i++)
{
SCL_P=1;
Delay6us();
temp=SDA_P;
Delay6us();
dat=(dat<<1)|temp;
SCL_P=0;
Delay6us();
}
return(dat);
}
/*********************************************************/
// IIC總線響應
/*********************************************************/
void IIcRespons()
{
uchar i=0;
SCL_P=1;
Delay6us();
while((SDA_P==1)&&(i<250))
{
i++;
}
SCL_P=0;
Delay6us();
}
/*********************************************************/
// IIC讀出數據
/*********************************************************/
uchar IIcReadDat(uchar addr)
{
uchar dat;
IIcStart(); // 開始信號
IIcWriteByte(0xa0); // 寫芯片地址(寫)
IIcRespons(); // 等待應答
IIcWriteByte(addr); // 寫內存地址(0-255)
IIcRespons(); // 等待應答
IIcStart(); // 開始信號
IIcWriteByte(0xa1); // 寫芯片地址(讀)
IIcRespons(); // 等待應答
dat=IIcReadByte(); // 讀取一個字節數據
IIcRespons(); // 等待應答
IIcStop(); // 結束信號
DelayMs(2); // 簡短延時
return dat; // 返回讀取到的數據
}
/*********************************************************/
// IIC寫入數據
/*********************************************************/
void IIcWriteDat(uchar addr,uchar dat)
{
IIcStart(); // 開始信號
IIcWriteByte(0xa0); // 寫芯片地址(寫)
IIcRespons(); // 等待應答
IIcWriteByte(addr); // 寫內存地址(0-255)
IIcRespons(); // 等待應答
IIcWriteByte(dat); // 寫入數據
IIcRespons(); // 等待應答
IIcStop(); // 結束信號
DelayMs(2); // 簡短延時
}
/**********************************************************
矩陣鍵盤掃描程序.
如果掃描到有按鍵按下,則返回按鍵值,返回值情況如下所示:
-------------------------------------------------------------
| 第1列 第2列 第3列 第4列 |
|第1行 1 2 3 12 |
|第2行 4 5 6 13 |
|第3行 7 8 9 14 |
|第4行 10 0 11 15 |
------------------------------------------------------------
如果掃描不到有按鍵按下,則返回99
**********************************************************/
uchar KeyScanf()
{
uchar ret,temp1,temp2;
P1=0x0f;
if(P1!=0x0f)
{
DelayMs(15);
if(P1!=0x0f)
{
temp1=P1; // 判斷出是哪一行按鍵按下
P1=0xf0;
DelayMs(5);
temp2=P1; // 判斷出是哪一列按鍵被按下
ret=temp1|temp2; // 通過行和列的值,確定是哪個按鍵被按下
switch(ret)
{
case 0xe7: return 1;
case 0xd7: return 2;
case 0xb7: return 3;
case 0x77: return 12;
case 0xeb: return 4;
case 0xdb: return 5;
case 0xbb: return 6;
case 0x7b: return 13;
case 0xed: return 7;
case 0xdd: return 8;
case 0xbd: return 9;
case 0x7d: return 14;
case 0xee: return 10;
case 0xde: return 0;
case 0xbe: return 11;
case 0x7e: return 15;
}
return ret;
}
}
return 99;
}
/*********************************************************/
// 液晶顯示密碼
/*********************************************************/
void LcdPrintCode(uchar num)
{
LcdGotoXY(row,column); // 液晶顯示定位
LcdWriteData(num+0x30); // 顯示輸入的密碼
DelayMs(150); // 等待150毫秒
LcdGotoXY(row,column); // 重新回到剛剛的顯示位置
LcdWriteData('*'); // 顯示“*”替換剛剛顯示的數字
column++; // 液晶顯示光標的縱坐標加1
}
/********************************************************/
// 蜂鳴器鳴叫
/*********************************************************/
void MingJiao(uint time)
{
Beep_P=0; // 蜂鳴器開始鳴叫
DelayMs(time); // 延時
Beep_P=1; // 蜂鳴器停止鳴叫
}
/*********************************************************/
// 清除密碼輸入緩沖區的內容
/*********************************************************/
void ClearCodeBuff()
{
uchar i;
for(i=0;i<6;i++) // 循環執行6次
{
ArrCodeBuff=' '; // 每次清除一位密碼緩沖區
}
inputNum=0; // 輸入的密碼位數為0
}
/*********************************************************/
// 密碼輸入初始化
/*********************************************************/
void inputInit()
{
LcdGotoXY(0,0); // 光標定位
LcdPrintStr(" State:lock "); // 液晶第0行顯示" State:lock "
LcdGotoXY(1,0); // 光標定位
LcdPrintStr("Password: ");
LcdGotoXY(1,9); // 液晶第1行顯示"Password: "
ClearCodeBuff(); // 清除密碼緩沖區
}
/*********************************************************/
// 密碼初始化
/*********************************************************/
void CodeInit()
{
uchar dat,i;
dat=IIcReadDat(10);
if(dat!=88) // 如果是第一次使用AT24C02芯片
{
IIcWriteDat(0,1); // 給AT24C02第0個內存寫入第一個密碼“1”
IIcWriteDat(1,2); // 給AT24C02第1個內存寫入第二個密碼“2”
IIcWriteDat(2,3); // 給AT24C02第2個內存寫入第三個密碼“3”
IIcWriteDat(3,4); // 給AT24C02第3個內存寫入第四個密碼“4”
IIcWriteDat(4,5); // 給AT24C02第4個內存寫入第五個密碼“5”
IIcWriteDat(5,6); // 給AT24C02第5個內存寫入第六個密碼“6”
IIcWriteDat(10,88); // 第10個內存寫入數字“88”,代表密碼初始化好了
}
for(i=0;i<6;i++) // 從AT24C02讀取6個密碼,賦值給密碼數組ArrCode
{
ArrCodeUnlock=IIcReadDat(i);
}
}
/*********************************************************/
// 主函數,程序從這里開始執行
/*********************************************************/
void main()
{
uchar i; // 臨時變量
uchar keyVal; // 按鍵掃描的返回值
uchar ArrCodeTemp[6]; // 臨時數組
LcdInit(); // 液晶初始化
inputInit(); // 密碼輸入初始化
CodeInit(); // 密碼初始化
while(1)
{
if(inputNum==6) // 如果輸入了6位密碼了
LcdWriteCmd(0x0c); // 關閉光標閃爍
else // 如果輸入不夠6位密碼
LcdWriteCmd(0x0f); // 開啟光標閃爍
keyVal=KeyScanf(); // 掃描按鍵是否有按鍵
if(keyVal!=99) // 如果有按鍵被按下了
{
MingJiao(50); // 那么蜂鳴器鳴叫50毫秒
}
/* 0-9 數字 */
if(keyVal<10) // 如果數字鍵被按下
{
if(inputNum<6) // 如果輸入的密碼不到6位
{
ArrCodeBuff[inputNum]=keyVal; // 給緩沖區加入一個新的密碼記錄
inputNum++; // inputNum加1,代表當前的密碼輸入多了一位
LcdPrintCode(keyVal); // 將輸入的密碼顯示出來
}
while(KeyScanf()!=99); // 等待按鍵釋放
}
/* 刪除一個密碼 */
if(keyVal==10) // 如果刪除鍵被按下
{
if(inputNum>0) // 如果當前已經有輸入密碼了
{
column--; // 光標退回上一個位置
LcdGotoXY(row,column);
LcdWriteData(' '); // 顯示空格
LcdGotoXY(row,column); // 光標退回上一個位置
inputNum--; // inputNum減1,代表當前的密碼刪掉了一位
ArrCodeBuff[inputNum]=' '; // 清除一位密碼緩沖區
}
while(KeyScanf()!=99); // 等待按鍵釋放
}
/* 清除全部密碼 */
if(keyVal==11) // 如果取消鍵被按下
{
ClearCodeBuff(); // 清除密碼緩沖區
if(inputMode==1) // 如果當前正在輸入解鎖密碼
{
LcdGotoXY(1,0); // 光標定位
LcdPrintStr("Password: "); // 液晶第1行顯示“Password: ”
LcdGotoXY(1,9); // 光標定位
}
if(inputMode==2) // 如果當前正在輸入修改密碼1
{
LcdGotoXY(0,0); // 光標定位
LcdPrintStr(" input1: "); // 液晶第0行顯示“input1: ”
LcdGotoXY(0,8); // 光標定位
}
if(inputMode==3) // 如果當前正在輸入修改密碼2
{
LcdGotoXY(1,0); // 光標定位
LcdPrintStr(" input2: "); // 液晶第1行顯示“input1: ”
LcdGotoXY(1,8); // 光標定位
}
while(KeyScanf()!=99); // 等待按鍵釋放
}
/* 手動關鎖 */
if(keyVal==12)
{
while(KeyScanf()!=99); // 等待按鍵釋放
}
/* 取消密碼修改 */
if(keyVal==13) // 如果修改密碼按鍵被按下
{
if((inputMode==2)||(inputMode==3)) // 如果當前正在輸入修改密碼
{
inputInit(); // 輸入初始化(退出修改)
Relay_P=1; // 繼電器閉合
inputMode=1; // 改為輸入解鎖密碼模式
}
while(KeyScanf()!=99);
}
/* 管理員密碼 */
if(keyVal==14)
{
for(i=0;i<6;i++)
{
if(ArrCodeBuff!=ArrCodeAdmin)
break;
}
if(i<6)
{
LcdGotoXY(1,0);
LcdPrintStr(" ERROR ");
MingJiao(5000);
}
else
{
LcdGotoXY(1,0);
LcdPrintStr("Password Init OK");
MingJiao(3000);
IIcWriteDat(10,' ');
CodeInit();
}
inputInit();
}
/* 確認按鍵 */
if(keyVal==15) // 如果確定鍵被按下
{
/*解鎖密碼*/
if(inputMode==1) // 如果當前正在輸入解鎖密碼
{
for(i=0;i<6;i++) // 把密碼緩沖區的內容和解鎖密碼進行6次比較
{
if(ArrCodeBuff!=ArrCodeUnlock)
break;
}
if(i<6) // 如果密碼錯誤
{
errTime++; // 錯誤次數加1
LcdGotoXY(1,0); // 光標定位
LcdPrintStr(" ERROR "); // 第1行顯示" ERROR "
LcdGotoXY(1,11); // 光標定位
LcdWriteData(errTime+0x30); // 顯示錯誤的次數
LcdWriteCmd(0x0c); // 關閉光標閃爍
MingJiao(3000); // 蜂鳴器鳴叫3秒
if(errTime==3) // 如果錯誤了3次
{
LcdGotoXY(1,0); // 光標定位
LcdPrintStr("Password:lock "); // 第1行顯示"Password:locd
errTime=0; // 密碼錯誤次數清零
DelayMs(60000); // 延時60秒
}
}
else // 如果密碼正確
{
errTime=0; // 密碼錯誤次數清零
Relay_P=0; // 打開繼電器
LcdGotoXY(0,0); // 光標定位
LcdPrintStr(" State:open "); // 第0行顯示" State:open "
LcdGotoXY(1,0); // 光標定位
LcdPrintStr(" "); // 第1行顯示" "
for(i=0;i<100;i++) // 進行10秒等待,執行100次循環
{
keyVal=KeyScanf(); // 掃描按鍵
DelayMs(100); // 等待100毫秒
if(keyVal==12) // 如果手動關鎖按鍵被按下
break; // 退出for循環,結束開始等待
if(keyVal==13) // 如果按下修改密碼鍵
{
LcdGotoXY(0,0); // 光標定位
LcdPrintStr(" input1: ");// 第0行顯示" input1: "
LcdGotoXY(1,0); // 光標定位
LcdPrintStr(" input2: ");// 第1行顯示" input2: "
LcdGotoXY(0,8); // 光標定位
inputMode=2; // 切換密碼輸入模式
ClearCodeBuff(); // 清除密碼緩沖區
while(KeyScanf()!=99); // 等待按鍵釋放
break; // 退出for循環,進入密碼修改
}
}
}
if(inputMode==1) // 如果當前處于輸入解鎖密碼狀態
{
Relay_P=1; // 閉合繼電器
inputInit(); // 密碼輸入初始化
}
}
/*修改密碼1*/
else if(inputMode==2) // 如果當前正在輸入修改密碼1
{
for(i=0;i<6;i++) // 將輸入的密碼暫時存入ArrCodeTemp數組
{
ArrCodeTemp=ArrCodeBuff;
}
LcdGotoXY(1,8); // 光標定位
inputMode=3; // 改為輸入 修改密碼2
ClearCodeBuff(); // 清除密碼緩沖區
while(KeyScanf()!=99); // 等待按鍵釋放
}
/*修改密碼2*/
else
{
for(i=0;i<6;i++) // 將2次輸入的密碼進行比較
{
if(ArrCodeBuff!=ArrCodeTemp)
break;
}
if(i<6) // 密碼修改錯誤
{
LcdGotoXY(0,0); // 光標定位
LcdPrintStr("Password Modify "); // 第0行顯示"Password Modify "
LcdGotoXY(1,0); // 光標定位
LcdPrintStr("-----failed-----"); // 第1行顯示"-----failed-----"
MingJiao(3000); // 蜂鳴器鳴叫3秒
}
else // 密碼修改成功
{
LcdGotoXY(0,0); // 光標定位
LcdPrintStr("Password Modify "); // 第0行顯示"Password Modify "
LcdGotoXY(1,0); // 光標定位
LcdPrintStr("---Successful---"); // 第1行顯示"---Successful---"
MingJiao(2000); // 蜂鳴器鳴叫2秒
for(i=0;i<6;i++)
{
IIcWriteDat(i,ArrCodeTemp);// 將新的密碼存入EEPROM芯片
ArrCodeUnlock=ArrCodeTemp;// 將新的密碼存入密碼數組
}
}
Relay_P=1; // 繼電器閉合
inputMode=1; // 改為輸入解鎖密碼模式
for(i=0;i<6;i++) // 清空修改密碼緩沖區
{
ArrCodeTemp=' ';
}
inputInit(); // 輸入初始化
while(KeyScanf()!=99); // 等待按鍵釋放
}
}
}
}
-
01、未上電.jpg
(211.09 KB, 下載次數: 35)
下載附件
2018-6-22 14:26 上傳
-
2、輸入密碼狀態.jpg
(214.99 KB, 下載次數: 32)
下載附件
2018-6-22 14:26 上傳
-
03、密碼輸入錯誤.jpg
(215.74 KB, 下載次數: 30)
下載附件
2018-6-22 14:26 上傳
-
04、修改密碼.jpg
(215.47 KB, 下載次數: 39)
下載附件
2018-6-22 14:26 上傳
-
-
1602顯示的密碼鎖.rar
2018-6-22 14:25 上傳
點擊文件名下載附件
1.27 MB, 閱讀權限: 10, 下載次數: 55
作者: 110101 時間: 2019-6-14 11:35
請問問題解決了嗎?
歡迎光臨 (http://www.zg4o1577.cn/bbs/) |
Powered by Discuz! X3.1 |
主站蜘蛛池模板:
手机av免费在线
|
蜜桃av鲁一鲁一鲁一鲁
|
在线观看黄免费
|
91精品国产综合久久婷婷香蕉
|
日韩欧美在线一区
|
国产 日韩 欧美 中文 在线播放
|
成人国产精品色哟哟
|
国产剧情一区
|
午夜视频在线免费观看
|
免费国产视频
|
久久久久久免费毛片精品
|
日本不卡一区二区三区
|
欧美日韩视频网站
|
日韩不卡一区二区
|
久久99视频这里只有精品
|
精品99久久
|
美女黄视频网站
|
日韩精品免费视频
|
中文在线一区二区
|
男女午夜免费视频
|
99精品一区二区三区
|
九九精品在线
|
亚洲一区
|
久久久久久久国产
|
成人免费小视频
|
成人水多啪啪片
|
国产成人99久久亚洲综合精品
|
色婷婷激情
|
日韩欧美一区二区三区免费观看
|
精品一区二区久久久久久久网站
|
亚洲视频在线看
|
在线观看中文字幕亚洲
|
www.黄色网
|
99久久久国产精品
|
一区二区在线
|
亚洲伊人久久综合
|
免费激情
|
国产久
|
日本又色又爽又黄又高潮
|
国产精品久久久久无码av
|
日韩精品一区二区三区中文字幕
|