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