|
51hei.png (17.61 KB, 下載次數(shù): 20)
下載附件
2021-1-14 20:39 上傳
單片機(jī)源程序如下:
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- uchar idata password_old[6] = {1,2,3,4,5,6};//初始密碼存放數(shù)組
- uchar idata password_input[6];//密碼輸入值保存數(shù)組
- uchar idata password_input1[6];//密碼輸入顯示*字符存放數(shù)組
- uchar idata password_set[18];//修改密碼時(shí)密碼輸入值保存數(shù)組
- uchar idata password_set1[18];//修改密碼時(shí)密碼輸入顯示*字符存放數(shù)組
- sbit sound = P3^2;//報(bào)警控制輸出端口
- sbit unlock_out = P3^3;//開(kāi)鎖驅(qū)動(dòng)控制輸出端口
- bit flag_input,flag_modify,flag_unlock,flag_success,flag_error,flag_clr;
- //密碼輸入狀態(tài)標(biāo)志,修改密碼狀態(tài)標(biāo)志,是否可以開(kāi)鎖標(biāo)志,密碼修改成功標(biāo)志
- //密碼輸入錯(cuò)誤或密碼修改錯(cuò)誤標(biāo)志,調(diào)換顯示界面時(shí)清屏標(biāo)志
- uchar error_num;//密碼輸入錯(cuò)誤計(jì)數(shù)
- uchar n,m;//密碼輸入狀態(tài)下輸入個(gè)數(shù)計(jì)數(shù)n,修改密碼狀態(tài)下輸入個(gè)數(shù)計(jì)數(shù)m
- #define lcd_out P0 //LCD1602接口設(shè)置
- sbit lcden = P2^1;
- sbit lcdrs = P2^0;
- sbit LED=P3^4;
- sbit K1=P3^5;
- /*******************************************
- lcd1602功能程序需要的延時(shí)函數(shù)
- ********************************************/
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- /*******************************************
- 向lcd1602寫(xiě)一個(gè)字節(jié)命令
- ********************************************/
- void write_com(uchar com)
- {
- lcdrs=0;//寫(xiě)命令
- lcd_out = com;
- delay(5);
- lcden=1;
- delay(5);
- lcden=0;
- }
- /*******************************************
- 向lcd1602寫(xiě)一個(gè)字節(jié)數(shù)據(jù)
- ********************************************/
- void write_data(uchar date)
- {
- lcdrs=1;//寫(xiě)數(shù)據(jù)
- lcd_out = date;
- delay(5);
- lcden=1;
- delay(5);
- lcden=0;
- }
- /*******************************************
- lcd1602初始化
- ********************************************/
- void lcd1602_init()
- {
- lcden=0;
- write_com(0x38);//顯示模式設(shè)置,16*2顯示,5*7點(diǎn)陣,8位并行數(shù)據(jù)接口
- write_com(0x0c);//顯示開(kāi),不顯示光標(biāo),光標(biāo)不閃爍
- write_com(0x06);//寫(xiě)入一個(gè)字符后指針加1,寫(xiě)一個(gè)字符時(shí)整屏不移動(dòng)
- write_com(0x01);//清屏,數(shù)據(jù)指針清0,所有顯示清0
- write_com(0x80+0x01);//設(shè)置字符顯示的首地址,第0行第1列所在的位置
- }
- /*******************************************
- 將字符串*str顯示在第y行第x列,x=0~15,y=0~1
- *******************************************/
- void display_str(uchar x,uchar y,uchar *str)
- {
- if(flag_clr == 1)//調(diào)換顯示界面,先清屏一次
- {
- write_com(0x01);//清屏,數(shù)據(jù)指針清0,所有顯示清0
- flag_clr = 0;
- }
- if(y == 0)
- write_com(0x80+x);//坐標(biāo)定位在第0行
- else
- write_com(0xc0+x);//坐標(biāo)定位在第1行
- write_com(0x0c);//顯示開(kāi),不顯示光標(biāo),光標(biāo)不閃爍
- while(*str != '\0') //判斷字符串是否結(jié)束
- {
- write_data(*str);//依次顯示字符串中的每一個(gè)字符
- str ++;
- }
- }
- /*******************************************
- 密碼輸入鍵處理
- ********************************************/
- void input(void)
- {
- flag_input = 1;//進(jìn)入密碼輸入狀態(tài),置標(biāo)志
- flag_clr = 1;//進(jìn)入密碼輸入顯示界面,置清屏標(biāo)志
- flag_modify = 0;//去除密碼修改標(biāo)志
- flag_unlock = 0;//取消開(kāi)鎖標(biāo)志
- flag_error = 0;//取消錯(cuò)誤標(biāo)志
- flag_success = 0;//取消密碼修改成功標(biāo)志
- unlock_out = 1;//設(shè)置成關(guān)鎖狀態(tài)
- }
- /*******************************************
- 數(shù)字鍵輸入處理,將相應(yīng)的數(shù)字保存為密碼輸入
- 數(shù)組,并在顯示界面相應(yīng)的位置上顯示*字符
- ********************************************/
- void key_number(uchar num)
- {
- if(flag_input == 1)//密碼輸入狀態(tài)
- {
- password_input[n] = num;//密碼輸入值保存
- password_input1[n] = '*';//密碼輸入位上顯示*字符
- n ++ ; //密碼輸入個(gè)數(shù)遞增
- }
- if(flag_modify == 1)//修改密碼狀態(tài)
- {
- password_set[m] = num;//密碼輸入值保存
- password_set1[m] = '*';//密碼輸入位上顯示*字符
- m ++; //密碼輸入個(gè)數(shù)遞增
- }
- }
- /*******************************************
- 新輸入的密碼與舊密碼進(jìn)行比較,正確的返回1
- ********************************************/
- bit password_compare(uchar *p,uchar *q)
- {
- uchar i,count = 0;
- for(i=0;i<6;i++)
- {
- if(p[i] == q[i])//判斷兩組6位密碼是否一致
- count ++;
- }
- if(count == 6)
- return 1;//兩組6位密碼一致
- else
- return 0;//兩組6位密碼不一致
- }
- /*******************************************************
- 開(kāi)鎖鍵處理
- 密碼輸入后確認(rèn)是否正確,如果正確,則開(kāi)鎖,否則錯(cuò)誤的話
- 允許重新輸入,并且判斷錯(cuò)誤輸入超過(guò)三次,則報(bào)警
- *******************************************************/
- void unlock(void)
- {
- uchar i;
- flag_unlock = password_compare(password_input,password_old);
- //將輸入的密碼與原始密碼進(jìn)行比較是否一致
- if(flag_unlock)//輸入的密碼與原始密碼一致
- {
- flag_clr = 1;
- display_str(3,1,"ALL RIGHT !");//密碼輸入成功顯示
- unlock_out = 0; //開(kāi)鎖驅(qū)動(dòng)輸出低電平信號(hào)
- flag_input = 0; //清除輸入密碼狀態(tài)標(biāo)志
- flag_error = 0; //清除密碼輸入錯(cuò)誤標(biāo)志
- error_num = 0; //清除密碼輸入錯(cuò)誤計(jì)數(shù)次數(shù)
- sound = 1; //關(guān)閉報(bào)警
- }
- else //輸入的密碼與原始密碼不一致
- {
- flag_clr = 1;
- display_str(3,1,"ERROR !");//密碼輸入錯(cuò)誤顯示
- flag_error = 1;//置密碼輸入錯(cuò)誤標(biāo)志
- error_num ++;//密碼輸入錯(cuò)誤次數(shù)計(jì)數(shù)
- if(error_num > 3)
- sound = 0;LED=~LED;//如果密碼輸入錯(cuò)誤次數(shù)超過(guò)3次,則報(bào)警
- /*******************************************
- 創(chuàng)新點(diǎn):密碼輸入超過(guò)六位顯示錯(cuò)誤
- ********************************************/
- if(n>6)
- {
- flag_clr=1;
- display_str(3,1,"ERROR !");
- }
- }
- n = 0; //6位密碼輸入結(jié)束時(shí),輸入個(gè)數(shù)計(jì)數(shù)值回零
- for(i=0;i<6;i++)
- password_input1[i] = 0x20;//密碼輸入結(jié)束,退出輸入狀態(tài)時(shí)顯示值重新改為0x20
- }
- /*******************************************
- 密碼修改鍵處理
- ********************************************/
- void modify(void)
- {
- flag_modify = 1;//進(jìn)入密碼修改狀態(tài),置標(biāo)志
- flag_input = 0;//去除密碼輸入標(biāo)志
- flag_clr = 1;//進(jìn)入密碼修改顯示界面,置清屏標(biāo)志
- flag_success = 0;//取消密碼修改成功標(biāo)志
- flag_error = 0;//取消錯(cuò)誤標(biāo)志
- flag_unlock = 0;//取消開(kāi)鎖標(biāo)志
- }
- /*******************************************
- 退格鍵處理
- ********************************************/
- void back(void)
- {
- if(flag_input == 1)
- {
- n -- ; //密碼輸入個(gè)數(shù)計(jì)數(shù)值遞減
- password_input1[n] = 0x20;//清除*字符顯示
- }
- if(flag_modify == 1)
- {
- m --; //密碼輸入個(gè)數(shù)計(jì)數(shù)值遞減
- password_set1[m] = 0x20;//清除*字符顯示
- }
- }
- /*******************************************
- 清除鍵處理
- ********************************************/
- void clear(void)
- {
- uchar i;
- if(flag_input == 1)
- {
- n = 0 ;
- for(i=0;i<6;i++)
- {
- password_input[i] = 0;//清除原先輸入的所有密碼值
- password_input1[i] = 0x20;//清除*字符顯示
- }
- }
- if(flag_modify == 1)
- {
- m = 0;
- for(i=0;i<18;i++)
- {
- password_set[i] = 0;//清除原先輸入的所有密碼值
- password_set1[i] = 0x20;//清除*字符顯示
- }
- }
- }
- /*******************************************
- 密碼修改,確認(rèn)鍵處理
- ********************************************/
- void enter(void)
- {
- bit flag_set = 0,modify_success = 0;
- uchar i;
- uchar password_set2[6],password_new[6];
- for(i=0;i<6;i++)
- {
- password_set2[i] = password_set[i];//取出輸入的舊密碼
- }
- flag_set = password_compare(password_set2,password_old);//判斷輸入的舊密碼是否正確
- for(i=0;i<6;i++)
- {
- password_set2[i] = password_set[i+6];//取出第一次輸入的新密碼
- password_new[i] = password_set[i+12];//取出第二次輸入的新密碼
- }
- modify_success = password_compare(password_set2,password_new);//判斷兩次輸入的新密碼是否一致
- if(flag_set==1 && modify_success==1)
- { //密碼修改成功
- flag_input = 1;//置密碼輸入狀態(tài)標(biāo)志
- flag_modify = 0;//清除修改密碼狀態(tài)標(biāo)志
- for(i=0;i<6;i++)
- {
- password_old[i] = password_new[i];//將新修改的密碼替換舊密碼
- }
- flag_success = 1; //置密碼密碼修改成功標(biāo)志
- flag_error = 0; //清除密碼修改錯(cuò)誤標(biāo)志
- flag_clr = 1;
- display_str(0,1,"Modify success !");//密碼修改成功時(shí)的顯示界面
- }
- else
- {
- flag_success = 0; //清除密碼密碼修改成功標(biāo)志
- flag_error = 1; //置密碼修改錯(cuò)誤標(biāo)志
- flag_clr = 1;
- display_str(3,1,"Error !");//密碼修改錯(cuò)誤的顯示界面
- }
- m = 0; //密碼修改結(jié)束,確認(rèn)后,密碼輸入個(gè)數(shù)計(jì)數(shù)值回零
- for(i=0;i<18;i++)
- {
- password_set[i] = 0; //將密碼輸入值全清零
- password_set1[i] = 0x20;//將密碼輸入的顯示字符全改為0x20
- }
- }
- /*******************************************
- LCD1602顯示
- ********************************************/
- void display(void)
- {
- uchar j;
- if(flag_unlock!=1 &&flag_success!=1&&flag_error!=1)
- { //避開(kāi)密碼輸入正確時(shí)、密碼修改成功時(shí)以及密碼輸入錯(cuò)誤時(shí)的顯示界面
- write_com(0x0c);//顯示開(kāi),不顯示光標(biāo),光標(biāo)不閃爍
- if(flag_input)
- {
- display_str(0,0,"Electronic Lock ");//輸入密碼狀態(tài)時(shí)的顯示界面
- display_str(0,1,"password:");
- write_com(0xc0+0x09);
- for(j=0;j<6;j++)
- write_data(password_input1[j]);//密碼輸入當(dāng)前6個(gè)位置上的顯示字符
- write_com(0xc0+0x09+n); //當(dāng)前密碼的輸入位的坐標(biāo)定位
- write_com(0x0f); //對(duì)當(dāng)前輸入位實(shí)現(xiàn)光標(biāo)顯示而且光標(biāo)閃爍
- }
- if(flag_modify == 1)
- {
-
- delay(1000);
- if(m<6) //修改密碼狀態(tài)時(shí)的第一個(gè)顯示界面
- {
-
- display_str(0,0,"Password Modify ");
- display_str(0,1,"old_code:");
- write_com(0xc0+0x09);
- for(j=0;j<6;j++)
- write_data(password_set1[j]);//舊密碼輸入的6個(gè)位置顯示
- write_com(0xc0+0x09+m);//當(dāng)前密碼的輸入位的坐標(biāo)定位
- write_com(0x0f);//對(duì)當(dāng)前輸入位實(shí)現(xiàn)光標(biāo)顯示而且光標(biāo)閃爍
- }
- else //修改密碼狀態(tài)時(shí)的第二個(gè)顯示界面
- {
- if(m==6)
- flag_clr = 1;
- display_str(0,0,"new_code:");
- write_com(0x80+0x09);
- for(j=6;j<12;j++)
- write_data(password_set1[j]);//第一次新密碼輸入的6個(gè)位置顯示
- display_str(0,1,"re_input:");
- write_com(0xc0+0x09);
- for(j=12;j<18;j++)
- write_data(password_set1[j]);//第二次新密碼輸入的6個(gè)位置顯示
- if(m<12)
- write_com(0x80+0x09+m-6);//當(dāng)前密碼的輸入位的坐標(biāo)定位
- else
- write_com(0xc0+0x09+m-12);//當(dāng)前密碼的輸入位的坐標(biāo)定位
- write_com(0x0f);//對(duì)當(dāng)前輸入位實(shí)現(xiàn)光標(biāo)顯示而且光標(biāo)閃爍
- }
- }
- }
- }
- /*******************************************
- 延時(shí)xms函數(shù)
- ********************************************/
- void delay_ms(uint x)
- {
- uchar j;
- while(x--)
- for(j=0;j<80;j++);
- }
- /*******************************************
- 矩陣式按鍵掃描并處理
- ********************************************/
- void key_scan()//采用線反轉(zhuǎn)法掃描識(shí)別4*4矩陣式按鍵
- {
- uchar a,b;
- P1 = 0xf0; //①行輸出低電平
- if(P1 != 0xf0)//②讀取列的電平,判定有鍵按下
- {
- delay_ms(10);//③延時(shí)10ms,避開(kāi)抖動(dòng)期
- if(P1 != 0xf0);//④再次確認(rèn)有鍵按下
- {
- sound = 0;
- a = P1;//⑤讀取列的電平,通過(guò)0所在的位判斷按下的鍵所在的列
- P1 = 0x0f; //⑥列輸出低電平
- b = P1; //⑦讀取行的電平,通過(guò)0所在的位判斷按下的鍵所在的行
- while(P1 == b);//⑧等待按鍵釋放
- sound = 1;
- a = a | b; //⑨計(jì)算獲得鍵值,綜合兩個(gè)0所在的位,判斷按下的鍵在相應(yīng)的行與列的交叉點(diǎn)
- switch(a) //⑩根據(jù)鍵值得出所按下的按鍵
- {
- case 0xee: key_number(0);break;//0~9數(shù)字鍵
- case 0xde: key_number(1);break;
- case 0xbe: key_number(2);break;
- case 0x7e: key_number(3);break;
- case 0xed: key_number(4);break;
- case 0xdd: key_number(5);break;
- case 0xbd: key_number(6);break;
- case 0x7d: key_number(7);break;
- case 0xeb: key_number(8);break;
- case 0xdb: key_number(9);break;
- case 0xbb: unlock();break; //開(kāi)鎖鍵
- case 0x7b: input();break; //密碼輸入鍵
- case 0xe7: enter();break; //密碼修改確認(rèn)鍵
- case 0xd7: clear();break; //清除鍵
- case 0xb7: back();break; //退格鍵
- case 0x77: modify();break; //密碼修改鍵
- default:break;
- }
- display();//顯示
- }
- }
- }
- /*******************************************
- 主函數(shù)
- ********************************************/
- void main()
- {
- uchar i;
- for(i=0;i<6;i++)
- password_input1[i] = 0x20;//密碼輸入數(shù)組初始化為0x20,顯示為空格字符
- for(i=0;i<18;i++)
- password_set1[i] = 0x20;//修改密碼時(shí)密碼輸入數(shù)組初始化為0x20
- lcd1602_init();
- while(1)
- {
- key_scan();
- }
- }
復(fù)制代碼
全部資料51hei下載地址:
循環(huán)掃描法.zip
(116.8 KB, 下載次數(shù): 2)
2021-1-14 20:21 上傳
點(diǎn)擊文件名下載附件
|
|