這是改過的程序
- #include <REG52.h>
- #include<intrins.h>
- sbit K1=P1^2;
- sbit ALAM = P2^5; //報警
- sbit open_led=P2^3; //開鎖指示燈
- /*LCD接口定義*/
- sbit LcdRS = P2^0; //lcd數據/命令選擇端 數據1命令0
- sbit LcdRW = P2^1; //lcd讀/寫選擇端 讀1寫0
- sbit LcdEn = P2^2; //lcd使能控制端 1有效
- sfr LcdIO = 0x80; //lcd數據接口 P0=0x80
- unsigned char code a[]={0xFE,0xFD,0xFB,0xF7}; //控盤掃描控制表
-
- unsigned char countt0,second; //t0中斷計數器,秒計數器
- unsigned char code start_line[] = {"password: "};
- unsigned char code name[] = {"===Coded Lock==="}; //顯示名稱
- unsigned char code Error[] = {" error "}; //輸入錯誤
- unsigned char code codepass[] = {" pass "};
- unsigned char code LockOpen[] = {" open "}; //OPEN
- char InputData[6]; //輸入密碼暫存區
- unsigned char CurrentPassword[6]={6,5,4,3,2,1}; //當前密碼值
- unsigned char N=0; //密碼輸入位數記數
- unsigned char ErrorCont; //錯誤次數計數
- unsigned char KEY_SCAN,NUM;
- /****向LCD寫入命令或數據部分****/
- #define LCD_COMMAND 0 // 輸出指令
- #define LCD_DATA 1 // 輸出數據
- #define LCD_CLEAR_SCREEN 0x01 // 清屏指令
- #define LCD_HOME 0x02 // 光標返回原點指令
- //=====================16us短延時==============================
- void Delay_short(unsigned int n)
- {
- unsigned int i;
- for(i=0;i<n;i++)
- {;}
- }
- //=====================長延時==============================
- void Delay_long(unsigned char N)
- {
- unsigned char i;
- unsigned int j;
- for(i=0;i<N;i++)
- {
- for(j=0;j<315;j++) //一個循環16us,共5ms
- {;}
- }
- }
- //=====================5ms延時==============================
- void Delay5Ms(void)
- {
- unsigned int TempCyc = 5552;
- while(TempCyc--);
- }
- //===================400ms延時==============================
- void Delay400Ms(void)
- {
- unsigned char TempCycA = 5;
- unsigned int TempCycB;
- while(TempCycA--)
- {
- TempCycB=7269;
- while(TempCycB--);
- }
- }
- /*寫LCD子程序 */
- /*入口參數:數據style=1 指令, style=0 input:寫入的內容*/
- void LCD_Write(bit style, unsigned char input)
- {
- LcdRS=style; //數據style=1 指令style=0
- LcdRW=0; //寫
- LcdIO=input; //P0口輸出
- Delay_short(10); //延時
- LcdEn=1; //lcd使能
- Delay_short(10); //延時
- LcdEn=0; //停止
- }
- /****初始化LCD程序****/
- void LCD_Initial()
- {
- Delay_long(6); //延遲5*6=30ms
- LCD_Write(LCD_COMMAND,0x38); //8位數據端口,2行顯示,5*7點陣
- LCD_Write(LCD_COMMAND,0x38);
- LCD_Write(LCD_COMMAND,0x38); //發送三遍
- Delay_short(2); //延遲大于39us
- LCD_Write(LCD_COMMAND,0x0c); //顯示模式設置:開啟顯示, 無光標 0x0c
- Delay_short(2); //延遲大于39us
- LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏 0x01
- Delay_short(100); //延遲大于1.53ms
- LCD_Write(LCD_COMMAND,0x06); //輸入模式設置:AC遞增, 畫面不動 0x06
- }
- /*液晶字符輸入的位置定位程序*/
- /*入口參數:x范圍:0-15 y范圍:1,2*/
- void GotoXY(unsigned char x, unsigned char y)
- {
- unsigned char address;
- if(y==1)
- {
- address=0x80+x; //y=1顯示在第一行
- }
- else
- {
- address=0xc0+x; //y=2顯示在第二行
- }
- LCD_Write(LCD_COMMAND, address);
- }
- /*將字符串輸出到液晶顯示函數*/
- /*入口參數:字符串指針 */
- void Print(unsigned char *str)
- {
- while(*str!='\0')
- {
- LCD_Write(LCD_DATA,*str);
- str++;
- }
- }
- //*********************************************************************
- //==============將按鍵值編碼為數值=========================
- unsigned char coding(unsigned char m)
- {
- unsigned char k;
- switch(m)
- {
- // case (0x18): k=3;break;
- // case (0x28): k=7;break;
- // case (0x48): k='#';break;
- // case (0x88): k='D';break;
- case (0x14): k=3;break;
- case (0x24): k=6;break;
- case (0x44): k=9;break;
- case (0x84): k='#';break;
- case (0x12): k=2;break;
- case (0x22): k=5;break;
- case (0x42): k=8;break;
- case (0x82): k=0;break;
- case (0x11): k=1;break;
- case (0x21): k=4;break;
- case (0x41): k=7;break;
- case (0x81): k='*';break;
- }
- return(k);
- }
- //=====================按鍵檢測并返回按鍵值===============================
- unsigned char keynum(void)
- {
- unsigned char row,col,i;
- P3=0xf0;
- if((P3&0xf0)!=0xf0)
- {
- Delay5Ms();
- Delay5Ms();
- if((P3&0xf0)!=0xf0)
- {
- row=P3^0xf0; //確定行線
- i=0;
- P3=a[i]; //精確定位
- while(i<4)
- {
- if((P3&0xf0)!=0xf0)
- {
- col=~(P3&0xff); //確定列線
- break; //已定位后提前退出
- }
- else
- {
- i++;
- P3=a[i];
- }
- }
- }
- else
- {
- return 0xff;
- }
- while((P3&0xf0)!=0xf0);
- return (row|col); //行線與列線組合后返回
- }
- else
- {
- return 0xff; //無鍵按下時返回0xff
- }
- }
- //***************************************************************************************/
- //=======================一聲提示音,表示有效輸入========================
- void OneAlam(void)
- {
- unsigned char y;
- for(y=0;y<30;y++)
- {
- ALAM=0;
- Delay_short(50);
- ALAM=1;
- Delay_short(50);
- }
- }
- //========================二聲提示音,表示操作成功========================
- void TwoAlam(void)
- {
- OneAlam();
- Delay5Ms();
- ALAM=1;
- Delay5Ms();
- OneAlam();
- Delay5Ms();
- ALAM=1;
- }
- //========================三聲提示音,表示錯誤========================
- void ThreeAlam(void)
- {
- OneAlam();
- Delay5Ms();
- ALAM=1;
- Delay5Ms();
- OneAlam();
- Delay5Ms();
- ALAM=1;
- Delay5Ms();
- OneAlam();
- Delay5Ms();
- ALAM=1;
- }
- //=======================輸入密碼錯誤超過三過,報警并鎖死鍵盤======================
- void Alam_KeyUnable(void)
- {
- P3=0x00;
- {
- OneAlam();
- Delay5Ms();
- ALAM=1;
- Delay5Ms();
- }
- }
- //=======================取消所有操作============================================
- void Cancel(void)
- {
- unsigned char i;
- GotoXY(0,2);
- Print(start_line);
- TwoAlam(); //提示音
- for(i=0;i<6;i++)
- {
- InputData[i]=0;
- }
- ALAM=1; //報警關
- ErrorCont=0; //密碼錯誤輸入次數清零
- open_led=1; //指示燈關閉
- N=0; //輸入位數計數器清零
- }
- //==========================確認鍵,并通過相應標志位執行相應功能===============================
- void Ensure(void)
- {
- unsigned char i,j;
- for(i=0;i<6;)
- {
- if(CurrentPassword[i]==InputData[i])
- {
- i++;
- }
- else
- {
- ErrorCont++;
- if(ErrorCont==3) //錯誤輸入計數達三次時,報警并鎖定鍵盤
- {
- GotoXY(0,2);
- Print(" KeypadLocked! ");
- TR0=1;
- do
- Alam_KeyUnable();
- while(TR0);
- return ;
- }
- break;
- }
- }
- if(i==6) //密碼正確輸入
- {
- GotoXY(0,2);
- Print(codepass);
- Delay400Ms();
- Delay400Ms();
- GotoXY(0,2);
- Print(LockOpen);
- TwoAlam(); //操作成功提示音
- //KEY_CLOCK=0; //開鎖
- //pass=1; //置正確標志位
- open_led=0; //開鎖指示燈亮
- for(j=0;j<6;j++) //將輸入清除
- {
- InputData[i]=0;
- }
- while(1);
- }
- else
- {
- GotoXY(0,2);
- Print(Error);
- ThreeAlam(); //錯誤提示音
- Delay400Ms();
- GotoXY(0,2);
- Print(start_line);
- for(j=0;j<6;j++) //將輸入清除
- {
- InputData[i]=0;
- }
- }
- N=0; //將輸入數據計數器清零,為下一次輸入作準備
- }
- void test_led()
- {
- while(1)
- {
- open_led=0;
- Delay400Ms();
- open_led=1;
- Delay400Ms();
- }
- }
- void test_alarm()
- {
- while(1)
- {
- ALAM=1;
- Delay_short(60);
- ALAM=0;
- Delay_short(60);
- }
- }
- void timer_init()
- {
- TMOD=0x11;
- TL0=0xB0;
- TH0=0x3C;
- EA=1;
- ET0=1;
- TR0=0;
- }
- void test_key()
- {
- unsigned char code ascii[]={"0123456789ABCDEF"};
- KEY_SCAN=keynum();
- if(KEY_SCAN!=0xff)
- {
- GotoXY(0,1);
- Print("key_code:0x");
- LCD_Write(LCD_DATA, ascii[KEY_SCAN/16]);
- LCD_Write(LCD_DATA, ascii[KEY_SCAN%16]);
- }
- }
- void keyscan() //按鍵掃描程序
- {
- static bit key_sign=0; //按鍵自鎖標志
- static bit sign=0;
- static unsigned char count=0;//計數變量
- unsigned char i;
- if(K1==0) //檢測按鍵如果為0
- {
- count++; //消抖計數
- if((count>=250)&&(key_sign==0))
- {
- key_sign=1; //按鍵自鎖標志置1
- sign=~sign;
- if(sign==1)
- {
- for(i=0;i<N;i++)
- {
- GotoXY(9+i,2);
- LCD_Write(LCD_DATA,InputData[i]+0x30);
- }
- }
- else
- {
- for(i=0;i<N;i++)
- {
- GotoXY(9+i,2);
- LCD_Write(LCD_DATA,'*');
- }
- }
- }
- }
- else //按鍵抬起
- {
- key_sign=0; //按鍵自鎖標志清0
- count=0; //消抖計數清0
- }
- }
- //==============================主函數===============================
- void main(void)
- {
-
- unsigned char j;
- // test_led();
- // test_alarm();
- Delay400Ms(); //啟動等待,等LCM講入工作狀態
- LCD_Initial(); //LCD初始化
- // while(1)
- // {
- // test_key();
- // }
- GotoXY(0,1);//日歷顯示固定符號從第一行第0個位置之后開始顯示
- Print(name);//向液晶屏寫日歷顯示的固定符號部分
- GotoXY(0,2);//時間顯示固定符號寫入位置,從第2個位置后開始顯示
- Print(start_line);//寫顯示時間固定符號,兩個冒號
- GotoXY(9,2); //設置光標位置
- LCD_Write(LCD_COMMAND,0x0f); //設置光標為閃爍
- // while(1);
- P3=0xFF;
- timer_init();
- Delay5Ms(); //延時片刻(可不要)
- N=0; //初始化數據輸入位數
- while(1)
- {
- if (!TR0)
- {
- KEY_SCAN=keynum();
- }
- else
- {
- KEY_SCAN = 0xff;
- }
- if(KEY_SCAN!=0xff)
- {
- NUM=coding(KEY_SCAN);
- switch(NUM)
- {
- case 'A': ; break;
- case 'B': ; break;
- case 'C': ; break;
- case 'D': ; break;
- case '*': Cancel(); break; //取消當前輸入
- case '#': Ensure(); break; //確認鍵,
- default:
- {
- if(N<6) //當輸入的密碼少于6位時,接受輸入并保存,大于6位時則無效。
- {
- // unsigned char temp;
- OneAlam(); //按鍵提示音
- for(j=N;j<=N;j++)
- {
- GotoXY(9+j,2);
- LCD_Write(LCD_DATA,'*');
- }
- /* if(K1==0)
- {
- GotoXY(9+N,2);
- temp=NUM+0x30 ;
- LCD_Write(LCD_DATA,temp);
-
- }*/
- InputData[N]=NUM;
- N++;
- }
- else //輸入數據位數大于6后,忽略輸入
- {
- N=6;
-
- }
- break;
- }
- }
- }
- keyscan();
- }
- }
- //*********************************中斷服務函數**************************************
- void time0_int(void) interrupt 1
- {
- TL0=0xB0;
- TH0=0x3C;
- countt0++;
- if(countt0==20)
- {
- countt0=0;
- second++;
- if(second==10)
- {
- P3=0xf0;
- TL0=0xB0;
- TH0=0x3C;
- second=0;
- ErrorCont=0; //密碼錯誤輸入次數清零
- GotoXY(0,2);
- Print(start_line);
- TR0=0; //關定時器
- }
-
- }
- }
復制代碼
|