下面是源碼預覽
- 數碼管的A--H 引腳 接到單片機的p0 口的 p0^0--P0^7 引腳 .
- 電路圖也有點問題,AT24C02 的引腳應該是 sbit Scl=P3^4; //串行時鐘信號
- sbit Sda=P3^5; //串行數據信號
- #define uchar unsigned char //定義一下方便使用
- #include "reg52.h"
- #include "intrins.h" //調用頭文件
- #define WriteDeviceAddress 0xa0 // AT24C02的識別碼是1010,硬件的三個地址引腳接地為000,最后一位為0時表示向存儲器寫入數據
- #define ReadDviceAddress 0xa1 //最后一位為1時表示從存儲器讀出數據。0xa0=1010 000 0 ,0xa1=1010 000 1 .
- sbit Scl=P3^4; //串行時鐘信號
- sbit Sda=P3^5; //串行數據信號
- sbit xin=P2^0; //在硬件電路上驅動青色發光二極管,用與顯示當前處于密碼輸入狀態
- sbit xin_on=P3^6; // 在硬件電路上驅動繼電器,當8位密碼輸入正確時,繼電器工作
- sbit ch_pass=P2^2; // 在硬件電路上驅動紅色發光二極管,用于顯示當前處于修改密碼狀態
- sbit on=P3^7;
- static cound ; // 用于計算密碼輸入的個數,每次輸入8位密碼后,清0
- uchar code DB_dat[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; // 存放數碼管顯示字符碼
- uchar DB_password[8]; // 存放從存儲器中讀取的原始密碼
- uchar DB_inword[8]; // 存放從鍵盤輸入的密碼
-
- void DelayMs(unsigned int number) //延時函數 延時1 MS
- {
- unsigned char temp;
- for(;number!=0;number--)
- {
- for(temp=112;temp!=0;temp--) ;
- }
- }
- void Start(void) /
- {
- Sda=0;
- Scl=1;
- _nop_ (); //根據時序圖盡心延時
- _nop_ ();
- _nop_ ();
- _nop_ ();
- Sda=1;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- }
- void Ack(void)
- {
- Sda=0;
- _nop_ ();
- _nop_ (); //延時 根據時序圖
- _nop_ ();
- _nop_ ();
- Scl=1;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- Scl=0;
- }
- void NoAck(void)
- {
- Sda=1;
- _nop_ (); //根據時序圖進行延時
- _nop_ ();
- _nop_ ();
- _nop_ ();
- Scl=1;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- Scl=0;
- }
- void Send(uchar Data)
- {
- uchar BitCounter=8;
- uchar temp;
- do
- {
- temp=Data;
- Scl=0;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- if((temp&0x80)==0x80)
- Sda=1;
- else
- Sda=0; //如果最高位是0就發送0
- Scl=1;
- temp=Data<<1;
- Data=temp;
- BitCounter--; //沒發完一位數據就減一
- }while(BitCounter); //如果發送完8位后跳出循環
- Scl=0; //釋放總線
- }
- uchar Read(void)
- {
- uchar temp=0;
- uchar temp1=0;
- uchar BitCounter=8; //定義從存儲器讀出的數據位數
- Sda=1;
- do{
- Scl=0;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- Scl=1;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- if(Sda)
- temp=temp|0x01;
- else
- temp=temp&0xfe;
- if(BitCounter-1)
- { temp1=temp<<1; //逐位的讀出
- temp=temp1;
- }
- BitCounter--;
- }while(BitCounter); //讀出8位后跳出循環
- return(temp); //返回讀出的數據
- }
- void WrToROM(uchar Data,uchar Address) //向存儲器寫一字節的數據 函數
- {
- uchar i=0;
-
- Start(); //調用起始條件函數
- Send(0xa0); // 發送命令,準備寫入數據到存儲器,讓存儲器做好準備
- Ack(); // 調用應答函數
- Send(Address); // 先發送要寫入數據的的存儲器內存地址
- Ack(); // 調用應答函數
-
- Send(Data); // 開始發送要寫入到存儲器中的數據
- Ack(); // 調用應答函數
-
- Stop(); // 調用停止發送函數,表示發送完畢
- }
- uchar RdFromROM(uchar Address) // 從存儲器讀出一字節的數據
- {
- uchar i;
-
- Start(); //調用起始條件函數
- Send(0xa0); // 讓存儲器準備接受命令
- Ack();
- Send(Address); // 發送要讀出來的數據地址
- Ack();
- Start(); // 重新調用起始函數
- Send(0xa1); // 發送讀出數據的命令
- Ack();
- i=Read ( ); // 開始讀出數據
- Scl=0;
- NoAck(); // 讀出數據成功。返回信號成功信號給存儲器
- Stop();
- return (i); // 返回讀出的數據
- }
-
- uchar Key() //鍵盤掃描子程序
- { uchar KValue;
- uchar tmp;
- P1|=0xff; //將P1口的接鍵盤的位置1
- KValue=P1;
- KValue|=0x00; //將未接鍵的位置1
- if(KValue==0xff) //
- return(0); //返回
- DelayMs(20); //延時10ms,去鍵抖
- KValue=P1;
- KValue|=0x00; //將未接鍵的位置1
- if(KValue==0xff) //位均為1,無鍵按下
- return(0); //返回
- //如尚未返回,說明一定有1或更多位被按下
- for(;;)
- { tmp=P1;
- if((tmp|0x00)==0xff)
- break; //等待按鍵釋放,防止按一次鍵盤,產生多次輸入數據
- }
- return(KValue); //返回按鍵值
- }
- Keyplay(uchar key) // 按鍵值 處理函數
- { uchar password;
-
- if (( key&0x80)==0) // 按鍵值位7時的相應處理
- { password=7;
- P0=DB_dat[7]; // 顯示按鍵值,通過數碼管顯示
- }
- if (( key&0x40)==0) // 按鍵值位6時的相應處理
- { password=6;
- P0=DB_dat[6]; // 顯示按鍵值,數碼管顯示
- }
- if (( key&0x20)==0) // 按鍵值位5時的的相應處理
- {password=5;
- P0=DB_dat[5] ; // 顯示按鍵值
- }
- if (( key&0x10)==0) // 按鍵值位4時的相應處理
- {password=4;
- P0=DB_dat[4];
- }
- if (( key&0x08)==0) // 按鍵值位3時的處理
- {password=3;
- P0=DB_dat[3];
- }
- if (( key&0x04)==0) // 按鍵值位2時的處理
- {password=2;
- P0=DB_dat[2];
- }
- if (( key&0x02)==0)
- {password=1;
- P0=DB_dat[1];
- }
- if (( key&0x01)==0) // 按鍵值位0時的處理
- {password=0;
- P0=DB_dat[0];
- }
-
- return password; //返回輸入的按鍵值
-
-
- }
- void Init() //中斷初始化
- { //定時器0工作于模式2
- IT0=1; //負變跳電平有效
- EX0=1; //開外部中斷
- EA=1; //開總中斷
-
- }
- void Init0() interrupt 0 //中斷入口,中斷后的程序處理 函數
- {
- uchar k,j,key;
- EX0=0; //關閉中斷,防止重復中斷 ((重要 不可以把EX0=0;放在char k,j,key; 之前 否則將出現編譯出錯))
- ch_pass=0; //點亮紅色發光二極管,顯示當前處于密碼修改狀態 ,當輸入8位密碼后,取消密碼修改狀態
- P0=0xff; //清空-數碼管
- cound=0; //清空密碼輸入個數標致,確保修改的密碼個數從開始,直到輸入8位密碼后,再一次清0
- while (1)
- { key=Key(); //調用鍵盤掃描程序,獲取按鍵值
- if (key) //判斷按鍵值是否位非0,非0代表有按鍵輸入
- { DB_inword[cound]=Keyplay(key); //調用按鍵值處理程序,并且把按鍵輸入的數字存放到 數組中
- cound++; // 每輸入一位的密碼,COUND 自加
-
- if(cound==8) // 判斷輸入的密碼個數是否到達8個
- { cound=0;
- // 密碼輸入個數已經到達8個
- DelayMs(1000);
-
-
- ch_pass=1;
- DelayMs(700);
- ch_pass=0; // 讓紅色發光二極管閃亮一次后,熄滅,表示密碼已經成功輸入8位
- DelayMs(700);
- ch_pass=1;
- for(k=0;k<8;k++) // 把輸入的8位密碼逐位的用數碼管顯示,并且寫入到存儲器中
- { j=DB_inword[k]; // 斷電后密碼仍然保存起來,不會消失
- P0=DB_dat[j]; // 獲取數碼管字符碼,并且顯示
- DelayMs(1000);
- WrToROM(j,k); // 寫入密碼到存儲器,寫入的內存地址為0~7
- DelayMs(1000);
- }
- for(k=0;k<8;k++)
- { DB_password[k]=RdFromROM(k) ;}
-
- P0=0xff;
- break; // 密碼修改成功后,跳出中斷程序,返回主程序
- }
- }
-
- }
- EX0=1; //重新開啟中斷
- }
- void main () // 主程序
- {
- uchar i,j,key,pass=0;
- Init(); // 中斷初始化
-
-
- cound=0;
-
- for (i=0;i<8;i++) // 逐為的顯示可以輸入的密碼值0~7,只能輸入這8為有效數字
- { P0=DB_dat[ i];
- DelayMs(1000);
- P0=0xff;
- }
-
- for (i=0;i<8;i++)
- { DB_password[ i]=RdFromROM(i) ; } //從存儲器讀出密碼值,并保存起來
- while (1)
- { on=0;
- DelayMs(200); // 點亮右下腳的青色發光二極管,表明發光二極管在閃耀表明單片機在正常工作
- on=1;
- key=Key(); // 獲取按鍵值
- if (key) // 判斷是否有按鍵按下
- { DB_inword[cound]=Keyplay(key); // 調用按鍵值處理函數,把輸入的按鍵值保存起來
- cound++; // 每輸入一個值,自加1
- xin=0; // 顯示當前處于密碼輸入狀態,點亮左上腳的青色發光二極管
- if(cound==8)
- { cound=0; // 輸入的密碼個數到達8個后,進行密碼驗證
-
- DelayMs(1000);
-
-
- xin=1; // 取消當前處于密碼輸入狀態
-
- for (i=0;i<8;i++)
- { DelayMs(1000);
- j=DB_inword[ i];
- P0=DB_dat[j]; // 逐位的顯示輸入的密碼值,用送到P0口,數碼管顯示
- DelayMs(1000);
- if( DB_password[ i]==DB_inword[ i] ) // 逐位的驗證輸入的密碼值是否和原始密碼一致
- { pass++; } // 輸入的密碼和原始密碼一致是 變量PASS自加1
-
- if ( pass==8) // PASS為8時,表明輸入的密碼和原始密碼8位都一致
- { xin_on=0;
- DelayMs(10000); // 密碼完全正確,驅動繼電器工作,將聽到“嗒”的一聲
- xin_on=1;
-
- }
- }
- pass=0; // 清空驗證位
- P0=0xff; // 清空數碼管
- for (i=0;i<8;i++)
- DB_inword[ i]=9; // 清空用于存放輸入密碼的數組,由于輸入的密碼限制在0~7之間
- } // 9為無效的輸入密碼值。確保下次輸入密碼時,數組里邊為無效值
- }
- }
- }
復制代碼 |