- /***************************************************************
- 此程序是在電子密碼鎖的基礎上增加的紅外遙控功能
- 采用STC89C52單片機
- 外中斷口P3.2為紅外接收頭接口
- 紅外和鍵盤兩種模式轉換用P2.3控制,0為鍵盤模式,1為紅外輸入
- 遙控器使用常用的HT6122核心的
- 液晶用1602 引腳定義在I2C_drive.h中
- 存儲器采用的24C04 引腳定義在I2C_drive.h中
- P1口接4X4矩陣按鍵
- ****************************************************************/
- #include<reg52.h>
- #include <string.h>
- #include "I2C_drive.h" //包含I2C總線驅動程序軟件包
- #include "LCD_drive.h" //包含I2C總線驅動程序軟件包
- #define uchar unsigned char
- #define uint unsigned int
- uchar code_buf[6]; //存儲器密碼緩沖區
- uchar incode_buf[6]; //輸入密碼緩沖區
- uchar IR_buf[4]={0x00,0x00,0x00,0x00};//IR_buf[0]、IR_buf[1]為用戶碼低位、用戶碼高位接收緩沖區
- // IR_buf[2]、IR_buf[3]為鍵數據碼和鍵數據碼反碼接收緩沖區
- uchar key; //鍵順序碼
- uchar temp; //暫存
- sbit BEEP=P1^5; //蜂鳴器
- sbit RELAY=P3^6; //繼電器
- sbit IRIN = P3^2; //遙控輸入腳 紅外
- sbit panduan=P2^3; //紅外,鍵盤轉換引腳,接地為鍵盤模式,懸空為紅外模式
- uchar count_5ms,sec; //5ms和1s計數器
- bit flag_2s=0; //2s標志位,2s時間到,該位置1
- bit flag_comp=0; //比較對錯標志位,比較正確,該標志位置1
- bit biaozhi=0;
- bit hongwai=1;
- bit jianpan=1;
- /******************************************************************************/
- void Delay(int num){//延時函數
- while(num--) ;
- }
- void beep(){//-揚聲器--按鍵音
- unsigned char a;//定義變量用于發聲的長度設置
- for(a=100;a>0;a--){//聲音的長度
- BEEP = ~BEEP;
- Delay(50);//音調設置延時
- }
- BEEP = 1;//音樂結束后揚聲器拉高關閉
- }
- /********以下是0.14ms的x倍延時函數********/
- void delayy(uchar x) //延時x*0.14ms
- {
- uchar i;
- while(x--)
- for (i = 0; i<13; i++);
- }
- /********以下是矩陣按鍵掃描函數********/
- void MatrixKey()
- {
- P1=0xff;
- P1=0xef; //置第1行P1.4為低電平,開始掃描第1行
- temp=P1; //讀P1口按鍵
- temp=temp & 0x0f; //判斷低4位是否有0,即判斷列線(P1.0~P1.3)是否有0
- if (temp!=0x0f) //若temp不等于0x0f,說明有鍵按下
- {
- Delay_ms(20); //延時10ms去抖
- temp=P1; //再讀取P1口按鍵
- temp=temp & 0x0f; //再判斷列線(P1.0~P1.3)是否有0
- if (temp!=0x0f) //若temp不等于0x0f,說明確實有鍵按下
- {
- temp=P1; //讀取P1口按鍵,開始判斷鍵值
- biaozhi=1;
- hongwai=1;
- jianpan=0;
- switch(temp)
- {
- case 0xee:key=15;break;
- case 0xed:key=14;break;
- case 0xeb:key=13;break;
- case 0xe7:key=12;break;
- }
- temp=P1; //將讀取的鍵值送temp
- beep(); //蜂鳴器響一聲
- temp=temp & 0x0f; //取出列線值(P1.0~P1.3)
- while(temp!=0x0f) //若temp不等于0x0f,說明按鍵還沒有釋放,繼續等待
- {
- biaozhi=0;
- jianpan=1;
- temp=P1; //若按鍵釋放,再讀取P1口
- temp=temp & 0x0f;// 判斷列線(P1.0~P1.3)是否有0
- }
- }
- }
- P1=0xff;
- P1=0xdf; //置第2行P1.5為低電平,開始掃描第2行
- temp=P1;
- temp=temp & 0x0f;
- if (temp!=0x0f)
- {
- Delay_ms(20);
- temp=P1;
- temp=temp & 0x0f;
- if (temp!=0x0f)
- {
- temp=P1;
- biaozhi=1;
- hongwai=1;
- jianpan=0;
- switch(temp)
- {
- case 0xde:key=11;break;
- case 0xdd:key=10;break;
- case 0xdb:key=9;break;
- case 0xd7:key=8;break;
- }
- temp=P1;
- beep();
- temp=temp & 0x0f;
- while(temp!=0x0f)
- {
- biaozhi=0;
- jianpan=1;
- temp=P1;
- temp=temp & 0x0f;
- }
- }
- }
- P1=0xff;
- P1=0xbf; //置第3行P1.6為低電平,開始掃描第3行
- temp=P1;
- temp=temp & 0x0f;
- if (temp!=0x0f)
- {
- Delay_ms(20);
- temp=P1;
- temp=temp & 0x0f;
- if (temp!=0x0f)
- {
- temp=P1;
- biaozhi=1;
- hongwai=1;
- jianpan=0;
- switch(temp)
- {
- case 0xbe:key=7;break;
- case 0xbd:key=6;break;
- case 0xbb:key=5;break;
- case 0xb7:key=4;break;
- }
- temp=P1;
- beep();
- temp=temp & 0x0f;
- while(temp!=0x0f)
- {
- biaozhi=0;
- jianpan=1;
- temp=P1;
- temp=temp & 0x0f;
- }
- }
- }
- P1=0xff;
- P1=0x7f; //置第4行P1.7為低電平,開始掃描第4行
- temp=P1;
- temp=temp & 0x0f;
- if (temp!=0x0f)
- {
- Delay_ms(20);
- temp=P1;
- temp=temp & 0x0f;
- if (temp!=0x0f)
- {
- temp=P1;
- biaozhi=1;
- hongwai=1;
- jianpan=0;
- switch(temp)
- {
- case 0x7e:key=3;break;
- case 0x7d:key=2;break;
- case 0x7b:key=1;break;
- case 0x77:key=0;break;
- }
- temp=P1;
- beep();
- temp=temp & 0x0f;
- while(temp!=0x0f)
- {
- biaozhi=0;
- jianpan=1;
- temp=P1;
- temp=temp & 0x0f;
- }
- }
- }
- }
- /*********************紅外按鍵矩陣函數*************************************************************************************************/
- void hongwaijvzhen ()
- {
- if(hongwai==0)
- {
- switch (IR_buf[2]){
- case 0x16: key = 0 ;break; //POWER //ON
- case 0x0c: key = 1 ;break; //MUTE //OFF
- case 0x18: key = 2 ;break; //0-9鍵控制
- case 0x5e: key = 3 ;break; //
- case 0x08: key = 4 ;break;
- case 0x1c: key = 5 ;break;
- case 0x5a: key = 6 ;break;
- case 0x11: key = 7 ;break;
- case 0x52: key = 8 ;break;
- case 0x4a: key = 9 ;break;
- case 0x45: key = 10;break; //A
- case 0x46: key = 11;break; //B
- case 0x47: key = 12;break;
- case 0x44: key = 13;break; //D
- case 0x40: key = 14;break; //#
- case 0x43: key = 15;break;
- }
- biaozhi=0;
- hongwai=1;
- }
- }
- /********以下是開機畫面信息********/
- uchar code jianpan1_data[] = {" << KEY >> "}; //定義第1行顯示的字符
- uchar code jianpan2_data[] = {" PATTERN(1) "}; //定義第2行顯示的字符
- uchar code hongwai1_data[] = {" << REMOTE >> "}; //定義第1行顯示的字符
- uchar code hongwai2_data[] = {" PATTERN(2) "}; //定義第2行顯示的字符
- /***************************************/
- uchar code line1_data[] = {" KEY LOCK "}; //定義第1行顯示的字符
- uchar code line2_data[] = {" MADE IN CHINA "}; //定義第2行顯示的字符
- /********以下是輸入密碼畫面信息********/
- uchar code in_line1[] = {" PLEASE INPUT "}; //定義第1行顯示的字符
- uchar code in_line2[] = {"PASSWORD:------ "}; //定義第2行顯示的字符
- /********以下是密碼輸入正確信息********/
- uchar code inok_line1[] = {"INPUT PASSWORD "}; //定義第1行顯示的字符
- uchar code inok_line2[] = {" INOPUT OK "}; //定義第2行顯示的字符
- /********以下是密碼輸入錯誤信息********/
- uchar code inerr_line1[] = {"INPUT PASSWORD "}; //定義第1行顯示的字符
- uchar code inerr_line2[] = {" INPUT ERR "}; //定義第2行顯示的字符
- /********以下是密碼設置畫面信息********/
- uchar code modify_line1[] = {"MODIFY PASSWORD "}; //定義第1行顯示的字符
- uchar code modify_line2[] = {"PASSWORD:------ "}; //定義第2行顯示的字符
- /********以下是密碼設置正確信息********/
- uchar code setok_line1[] = {"MODIFY PASSWORD "}; //定義第1行顯示的字符
- uchar code setok_line2[] = {" MODIFY OK "}; //定義第2行顯示的字符
- /********以下是開機畫面顯示函數********/
- void StartDisp()
- {
- uchar i;
- lcd_clr(); //調清屏函數
- lcd_wcmd(0x00|0x80); //設置顯示位置為第1行第0列
- i = 0;
- while(line1_data[i] != '\0') //若沒有到達第1行字符串尾部
- {
- lcd_wdat(line1_data[i]); //顯示第1行字符
- i++; //指向下一字符
- }
- lcd_wcmd(0x40|0x80); //設置顯示位置為第2行第0列
- i = 0;
- while(line2_data[i] != '\0') //若沒有到達第2行字符串尾部
- {
- lcd_wdat(line2_data[i]); //顯示第2行字符
- i++; //指向下一字符
- }
- }
- /********以下是密碼輸入畫面顯示函數********/
- void CodeInDisp()
- {
- uchar i;
- lcd_clr(); //調清屏函數
- lcd_wcmd(0x00|0x80); //設置顯示位置為第1行第0列
- i = 0;
- while(in_line1[i] != '\0') //若沒有到達第1行字符串尾部
- {
- lcd_wdat(in_line1[i]); //顯示第1行字符
- i++; //指向下一字符
- }
- lcd_wcmd(0x40|0x80); //設置顯示位置為第2行第0列
- i = 0;
- while(in_line2[i] != '\0') //若沒有到達第2行字符串尾部
- {
- lcd_wdat(in_line2[i]); //顯示第2行字符
- i++; //指向下一字符
- }
- }
- /********以下是密碼輸入錯誤顯示函數********/
- void CodeInErr()
- {
- uchar i;
- lcd_clr(); //調清屏函數
- lcd_wcmd(0x00|0x80); //設置顯示位置為第1行第0列
- i = 0;
- while(inerr_line1[i] != '\0') //若沒有到達第1行字符串尾部
- {
- lcd_wdat(inerr_line1[i]); //顯示第1行字符
- i++; //指向下一字符
- }
- lcd_wcmd(0x40|0x80); //設置顯示位置為第2行第0列
- i = 0;
- while(inerr_line2[i] != '\0') //若沒有到達第2行字符串尾部
- {
- lcd_wdat(inerr_line2[i]); //顯示第2行字符
- i++; //指向下一字符
- }
- }
- /********以下是密碼輸入正確顯示函數********/
- void CodeInOk()
- {
- uchar i;
- lcd_clr(); //調清屏函數
- lcd_wcmd(0x00|0x80); //設置顯示位置為第1行第0列
- i = 0;
- while(inok_line1[i] != '\0') //若沒有到達第1行字符串尾部
- {
- lcd_wdat(inok_line1[i]); //顯示第1行字符
- i++; //指向下一字符
- }
- lcd_wcmd(0x40|0x80); //設置顯示位置為第2行第0列
- i = 0;
- while(inok_line2[i] != '\0') //若沒有到達第2行字符串尾部
- {
- lcd_wdat(inok_line2[i]); //顯示第2行字符
- i++; //指向下一字符
- }
- }
- /********以下是密碼設置畫面顯示函數********/
- void CodeSetDisp()
- {
- uchar i;
- lcd_clr(); //調清屏函數
- lcd_wcmd(0x00|0x80); //設置顯示位置為第1行第0列
- i = 0;
- while(modify_line1[i] != '\0') //若沒有到達第1行字符串尾部
- {
- lcd_wdat(modify_line1[i]); //顯示第1行字符
- i++; //指向下一字符
- }
- lcd_wcmd(0x40|0x80); //設置顯示位置為第2行第0列
- i = 0;
- while(modify_line2[i] != '\0') //若沒有到達第2行字符串尾部
- {
- lcd_wdat(modify_line2[i]); //顯示第2行字符
- i++; //指向下一字符
- }
- }
- /********以下是密碼設置正確顯示函數********/
- void CodeSetOk()
- {
- uchar i;
- lcd_clr(); //調清屏函數
- lcd_wcmd(0x00|0x80); //設置顯示位置為第1行第0列
- i = 0;
- while(setok_line1[i] != '\0') //若沒有到達第1行字符串尾部
- {
- lcd_wdat(setok_line1[i]); //顯示第1行字符
- i++; //指向下一字符
- }
- lcd_wcmd(0x40|0x80); //設置顯示位置為第2行第0列
- i = 0;
- while(setok_line2[i] != '\0') //若沒有到達第2行字符串尾部
- {
- lcd_wdat(setok_line2[i]); //顯示第2行字符
- i++; //指向下一字符
- }
- }
- /********以下是密碼輸入函數********/
- void PassIn()
- {
- static uchar lcd_x=0; //顯示指針,注意是靜態局部變量
- static uchar count=0; //密碼計數器 ,注意是靜態局部變量
- static uchar code_n=0; //密碼次數
- PASSWORD:
- lcd_clr(); //調清屏函數
- CodeInDisp();//密碼輸入畫面函數
- do{
- /**********修改1***********/
- P1=0xf0;
- if(P1!=0xf0) //若有按鍵按下
- {
- MatrixKey(); //調矩陣按鍵掃描函數
- P1=0xf0;
- while(P1!=0xf0);//等待按鍵松開
- /***************************/
- if((key>=0)&&(key<=9)) //若按下是的0~9鍵(即密碼只能是數字,字母鍵A~F無效)
- {
- incode_buf[count]=key; //將鍵值存入數組
- lcd_wcmd((0x49+lcd_x)|0x80); //設置顯示位置為第2行第9+lcd_x列
- lcd_wdat(0x2a); //顯示為"*",0x2a是"*"的LCD顯示碼
- count++; //輸入下一位密碼
- lcd_x++; //指向LCD的下一位置
- }
- }
- }while(count<6); //密碼設置為6位
- if(count>=6){count=0;lcd_x=0;}
- if(memcmp(incode_buf,code_buf,6)==0) //若兩個數組相等,則返回值為0,注意這里不能用strcmp函數進行比較
- {
- CodeInOk(); //若輸入的密碼正確,則顯示輸入正確的信息
- beep();beep();beep(); //輸入正確后,蜂鳴器響三聲
- flag_comp=1; //密碼比較標志位置1
- code_n=0; //密碼計數器清0
- RELAY=0; //打開繼電器,開鎖
- }
- else if(memcmp(incode_buf,code_buf,6)!=0)//若輸入的密碼不正確
- {
- code_n++; //密碼計數器加1
- if(code_n>=3) //有三次輸入的機會
- {
- CodeInErr(); //若三次輸入均錯誤,顯示密碼錯誤信息
- flag_comp=0; //密碼比較標志位清0
- code_n=0; //密碼計數器清0
- }
- else goto PASSWORD; //若還有機會輸入密碼,則跳轉到標號PASSWORD處繼續輸入
- }
- }
- /********以下是紅外線密碼輸入函數**********************************************************************************/
- void PassInhongwai()
- {
- static uchar lcd_x=0; //顯示指針,注意是靜態局部變量
- static uchar count=0; //密碼計數器 ,注意是靜態局部變量
- static uchar code_n=0; //密碼次數
- PASSWORD: lcd_clr(); //調清屏函數
- CodeInDisp();//密碼輸入畫面函數
- do{
- /**********修改1***********/
- if(hongwai==0) //若有按鍵按下
- {
- hongwaijvzhen(); //調矩陣按鍵掃描函數
- while(!hongwai);//等待按鍵松開
- /***************************/
- if((key>=0)&&(key<=9)) //若按下是的0~9鍵(即密碼只能是數字,字母鍵A~F無效)
- {
- incode_buf[count]=key; //將鍵值存入數組
- lcd_wcmd((0x49+lcd_x)|0x80); //設置顯示位置為第2行第9+lcd_x列
- lcd_wdat(0x2a); //顯示為"*",0x2a是"*"的LCD顯示碼
- count++; //輸入下一位密碼
- lcd_x++; //指向LCD的下一位置
- beep();
- }
- }
- }while(count<6); //密碼設置為6位
- if(count>=6){count=0;lcd_x=0;}
- if(memcmp(incode_buf,code_buf,6)==0) //若兩個數組相等,則返回值為0,注意這里不能用strcmp函數進行比較
- {
- CodeInOk(); //若輸入的密碼正確,則顯示輸入正確的信息
- beep();beep();beep(); //輸入正確后,蜂鳴器響三聲
- flag_comp=1; //密碼比較標志位置1
- code_n=0; //密碼計數器清0
- RELAY=0; //打開繼電器,開鎖
- }
- else if(memcmp(incode_buf,code_buf,6)!=0)//若輸入的密碼不正確
- {
- code_n++; //密碼計數器加1
- if(code_n>=3) //有三次輸入的機會
- {
- CodeInErr(); //若三次輸入均錯誤,顯示密碼錯誤信息
- flag_comp=0; //密碼比較標志位清0
- code_n=0; //密碼計數器清0
- }
- else goto PASSWORD; //若還有機會輸入密碼,則跳轉到標號PASSWORD處繼續輸入
- }
- }
- /********以下是密碼設置函數*******************************************************************************************************/
- void PassSet()
- {
- static uchar lcd_x=0; //顯示指針,注意是靜態局部變量
- static uchar count=0; //密碼計數器 ,注意是靜態局部變量
- lcd_clr(); //調清屏函數
- CodeSetDisp(); //密碼設置畫面函數
- do{
- /********修改2**************/
- P1=0xf0;
- if(P1!=0xf0) //若有按鍵按下
- {
- MatrixKey(); //調矩陣按鍵掃描函數
- P1=0xf0;
- while(P1!=0xf0);//等待按鍵松開
- /**********************/
- if((key>=0)&&(key<=9)) //若按下是的0~9鍵(即密碼只能是數字,字母鍵A~F無效)
- {
- code_buf[count]=key; //將鍵值存入數組code_buf[]中
- lcd_wcmd((0x49+lcd_x)|0x80); //設置顯示位置為第2行第9+lcd_x列
- lcd_wdat(code_buf[count]+0x30); //將輸入的密碼通過LCD顯示出來
- count++; //輸入下一位密碼
- lcd_x++; //指向LCD的下一位置
- }
- }
- }while(count<6); //密碼設置為6位
- if(count>=6){count=0;lcd_x=0;}
- beep();beep();beep(); //輸入完畢后,蜂鳴器響三聲
- write_nbyte(0xa0,0x00,code_buf,6); //將數組code_buf[]中的6位密碼寫入24cxx從00開始的單元中
- lcd_clr(); //調清屏函數
- CodeSetOk(); //密碼設置正確畫面函數
- }
- /********************************************紅外密碼設置函數****************************************************************/
- void PassSethongwai()
- {
- static uchar lcd_x=0; //顯示指針,注意是靜態局部變量
- static uchar count=0; //密碼計數器 ,注意是靜態局部變量
- lcd_clr(); //調清屏函數
- CodeSetDisp(); //密碼設置畫面函數
- do{
- /********修改2**************/
- if(hongwai==0) //若有按鍵按下
- {
- hongwaijvzhen(); //調矩陣按鍵掃描函數
- while(!hongwai);//等待按鍵松開
- /**********************/
- if((key>=0)&&(key<=9)) //若按下是的0~9鍵(即密碼只能是數字,字母鍵A~F無效)
- {
- code_buf[count]=key; //將鍵值存入數組code_buf[]中
- lcd_wcmd((0x49+lcd_x)|0x80); //設置顯示位置為第2行第9+lcd_x列
- lcd_wdat(code_buf[count]+0x30); //將輸入的密碼通過LCD顯示出來
- count++; //輸入下一位密碼
- lcd_x++; //指向LCD的下一位置
- beep();
- }
- }
- }while(count<6); //密碼設置為6位
- if(count>=6){count=0;lcd_x=0;}
- beep();beep();beep(); //輸入完畢后,蜂鳴器響三聲
- write_nbyte(0xa0,0x00,code_buf,6); //將數組code_buf[]中的6位密碼寫入24cxx從00開始的單元中
- lcd_clr(); //調清屏函數
- CodeSetOk(); //密碼設置正確畫面函數
- }
- /****************開機初始模式顯示函數******************************************/
- void kaijimoshi()
- {
- if(panduan==0) //如果P2.3腳接地顯示《KEY》
- { // PATTERN(1)
- uchar i;
- lcd_clr(); //調清屏函數
- lcd_wcmd(0x00|0x80); //設置顯示位置為第1行第0列
- i = 0;
- while(jianpan1_data[i] != '\0') //若沒有到達第1行字符串尾部
- {
- lcd_wdat(jianpan1_data[i]); //顯示第1行字符
- i++; //指向下一字符
- }
- lcd_wcmd(0x40|0x80); //設置顯示位置為第2行第0列
- i = 0;
- while(jianpan2_data[i] != '\0') //若沒有到達第2行字符串尾部
- {
- lcd_wdat(jianpan2_data[i]); //顯示第2行字符
- i++; //指向下一字符
- }
- Delay_ms(3000); //延時3秒
- lcd_clr();
- }
- if(panduan==1) //如果P2.3腳懸空顯示《REMOTE》
- { // PATTERN(2)
- uchar i;
- lcd_clr(); //調清屏函數
- lcd_wcmd(0x00|0x80); //設置顯示位置為第1行第0列
- i = 0;
- while(hongwai1_data[i] != '\0') //若沒有到達第1行字符串尾部
- {
- lcd_wdat(hongwai1_data[i]); //顯示第1行字符
- i++; //指向下一字符
- }
- lcd_wcmd(0x40|0x80); //設置顯示位置為第2行第0列
- i = 0;
- while(hongwai2_data[i] != '\0') //若沒有到達第2行字符串尾部
- {
- lcd_wdat(hongwai2_data[i]); //顯示第2行字符
- i++; //指向下一字符
- }
- Delay_ms(3000); //延時3秒
- lcd_clr();
- }
- }
- /********以下是主函數********/
- void main()
- {
- EA=1;EX0=1; //允許總中斷中斷,使能 INT0 外部中斷
- IT0 = 1; //觸發方式為脈沖負邊沿觸發
- IRIN=1; //遙控輸入腳置1
- TMOD=0x01; //定時器T0方式1
- TH0=0xee;
- TL0=0x00; //5ms定時初值
- ET0=1; //開總中斷,開定時器T0中斷
- Delay_ms(10);
- lcd_init(); //調LCD初始化函數
- I2C_init(); //調I2C總線初始化函數(在I2C總線驅動程序軟件包中)
- kaijimoshi();
- START: RELAY=1; //繼電器關斷
- lcd_clr();
- StartDisp(); //開機畫面顯示函數
- read_nbyte (0xa0,0x00,code_buf,6);//從24Cxx的0x00開始的單元中讀出6個密碼存入code_buf[]數組中
- P1=0xf0;
- while((P1==0xf0)&&(hongwai==0)); //如果紅外和鍵盤不是同時按下,就進入到下一步,否則等待
- MatrixKey();
- /*******************************執行紅外模式密碼鎖方式****************************************************************************/
- if(panduan==1)
- {
- SCAN: hongwaijvzhen (); //調矩陣按鍵掃描函數
- if(key!=0x0a)goto SCAN; //若按下的不是A鍵,跳轉到標號SCAN處繼續掃描
- TR0=1; //啟動定時器T0
- Delay_ms(500); //延時500ms
- beep(); //蜂鳴器響一聲
- if(flag_2s==1)flag_2s=0; //若2s到,則將 2s標志位清0
- else goto SCAN; //若2s未到,則跳轉到標號SCAN處繼續掃描
- PassInhongwai(); //調紅外密碼輸入函數
- while(1)
- {
- if(flag_comp==1) //若輸入的密碼正確
- {
- hongwaijvzhen ();
- if(key==0x0b) //在密碼正確的情況下若按下了B鍵
- {
- PassSethongwai(); // 調紅外密碼設置函數
- hongwaijvzhen ();
- if(key==0x0e)goto START;//若按下了E鍵,則跳轉到標志START處重新開始
- }
- if(key==0x0e)goto START; //若按下了E鍵,則跳轉到標志START處重新開始
- }
- if(flag_comp==0) //若輸入的密碼不正確
- {
- hongwaijvzhen ();
- if(key==0x0e)goto START;//若按下的是E鍵,跳轉到標號START處重新開始
- }
- }
- }
- /************************執行鍵盤輸入密碼鎖模式**********************************************************************************************/
- if(panduan==0)
- {
- DSCAN: MatrixKey(); //調矩陣按鍵掃描函數
- if(key!=0x0a)goto DSCAN; //若按下的不是A鍵,跳轉到標號SCAN處繼續掃描
- TR0=1; //啟動定時器T0
- Delay_ms(500); //延時500ms
- beep(); //蜂鳴器響一聲
- if(flag_2s==1)flag_2s=0; //若2s到,則將 2s標志位清0
- else goto DSCAN; //若2s未到,則跳轉到標號SCAN處繼續掃描
- PassIn(); //調密碼輸入函數
- /******************************************/
- while(1)
- {
- if(flag_comp==1) //若輸入的密碼正確
- {
- MatrixKey(); //掃描按鍵
- if(key==0x0b) //在密碼正確的情況下若按下了B鍵
- {
- PassSet(); //若按下的是B鍵,調密碼設置函數
- MatrixKey(); //掃描按鍵
- if(key==0x0e)goto START;//若按下了E鍵,則跳轉到標志START處重新開始
- }
- if(key==0x0e)goto START; //若按下了E鍵,則跳轉到標志START處重新開始
- }
- if(flag_comp==0) //若輸入的密碼不正確
- {
- MatrixKey(); //掃描按鍵
- if(key==0x0e)goto START;//若按下的是E鍵,跳轉到標號START處重新開始
- }
- }
- }
- }
- /********以下是定時器T0中斷函數********/
- void timer0() interrupt 1
- {
- TH0=0xee;TL0=0x00; //重裝5ms定時初值
- count_5ms++; //5ms 計數值加1
- if(count_5ms==200) //若count_5ms為200,說明1s到(200×0ms=1000ms)
- {
- count_5ms=0; // count_5ms清0
- sec++; //秒計數器加1
- }
- if(sec==2)
- {
- flag_2s=1; //若2s到,將2s標志位置1
- TR0=0; //關斷定時器T0
- }
- }
- /********以下是外中斷0函數********/
- void IR_decode() interrupt 0
- {
- uchar j,k,count=0;
- EX0 = 0; //暫時關閉外中斷0中斷請求
- delayy(20); //延時20*0.14=2.8ms
- if (IRIN==1) //等待 IRIN低電平出現
- {
- EX0 =1; //開外中斷0
- return; //中斷返回
- }
- while (!IRIN) delayy(1); //等待IRIN變為高電平,跳過9ms的低電平引導碼
- for (j=0;j<4;j++) //收集四組數據,即用戶碼低位、用戶碼高位、鍵值數據碼和鍵值數碼反碼
- {
- for (k=0;k<8;k++) //每組數據有8位
- {
- while (IRIN) //等待IRIN變為低電平,跳過4.5ms的高電平引導碼信號。
- delayy(1);
- while (!IRIN) //等待IRIN變為高電平
- delayy(1);
- while (IRIN) //對IRIN高電平時間進行計數
- {
- delayy(1); //延時0.14ms
- count++; //對0.14ms延時時間進行計數
- if (count>=30)
- {
- EX0=1; //開外中斷0
- return; //0.14ms計數過長則返回
- }
- }
- IR_buf[j]=IR_buf[j] >> 1; //若計數小于6,數據最高位補"0",說明收到的是"0"
- if (count>=6) {IR_buf[j] = IR_buf[j] | 0x80;} //若計數大于等于6,數據最高位補"1",說明收到的是"1"
- count=0; //計數器清0
- }
- }
- if (IR_buf[2]!=~IR_buf[3]) //將鍵數據反碼取反后與鍵數據碼碼比較,若不等,表示接收數據錯誤,放棄
- {
- EX0 = 1; //開外中斷0
- return;
- }
- /******************************************************************/
- hongwai=0;
- beep(); //蜂鳴器響一聲
- EX0 = 1; //開外中斷0
- biaozhi=1;
- jianpan=1;
- }
復制代碼 |