?? locker_with_lcd_and_clock.txt
字號:
程序說明:
本程序用到4x4按鍵中斷掃描法,用lcd顯示,開機時候顯示一個數字鐘(時間不可設,稍后加入該功能),鐘正常走
如果按下開鎖鍵,進入以請輸入密碼界面,輸入密碼,如果密碼正確,顯示歡迎使用,密碼錯誤蜂鳴器報警
且LCD顯示密碼錯誤,請重新輸入。
注:數字時鐘用的是DS1302實現,由于本人也才學單片機一個多月,所以注釋非常詳細,初學者很容易看懂。
**************************************************************************************************************/
#include <reg52.h>
#include <intrins.h>
sbit SPK=P3^4; //SPK定義為P3口的第4位,就是驅動蜂鳴器的那個腳
sbit JDQ=P3^5; //JDQ定義為P3口的第5位,就是驅動繼電器的那個腳
sbit lcdrs = P1^0; //數據命令選擇端 (H/L)
sbit lcdrw = P1^1; //讀寫選擇端 (H/L)
sbit lcde = P1^2; //使能信號
sbit OK = P0^5; //密碼輸入確認鍵
sbit H = P0^4;//獨立按鍵定義位
sbit take = P0^6;//開鎖鍵
sbit SCL2 = P1^3; //SCL2定義為P1口的第3位腳,連接DS1302SCL和ADC0831SCL腳
sbit SDA2 = P1^4; //SDA2定義為P1口的第4位腳,連接DS1302SCL和ADC0831SDA腳
sbit RST = P1^5; // DS1302片選腳
#define LCD_Data P2
#define Busy 0x80 //用于檢測LCD狀態字中的Busy標識
#define uchar unsigned char
#define uint unsigned int
code unsigned char table[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};
//共陰數碼管 0-9 a-f 表
code unsigned char key_tab[10]={0xed,0x7e,0x7d,0x7b,
0xbe,0xbd,0xbb,0xde,
0xdd,0xdb,};//0x77,0xb7,
// 0xee,0xd7,0xeb,0xe7,0XFF};//========================此數組為鍵盤編碼,
//本人采用類式類似電話按鍵的編碼方式,方便以后設計
// 1 2 3 a 0x01 0x02 0x03 0x0a
// 4 5 6 b 對應16進制碼: 0x04 0x05 0x06 0x0b
// 7 8 9 e 0x07 0x08 0x09 0x0e
// * 0 # f 0x0c 0x00 0x0e 0x0f
//打個比方,如果你按下0鍵,P0口讀到數據為0xed
//如果你按下2鍵,P0口讀到數據為0x7d,按下9鍵為0xdb,
//我們將讀到的P0口數據經過查表法就能得到相應的16進制碼
//鍵盤的讀取,我們采用中斷法,電路用一個4與門(74HC21)接入
//中斷口(INT0),利用中斷來掃描鍵盤矩陣,讀取數據
unsigned char l_tmpdate1[4]={0,0,0,0};//定義數組變量
uchar table_password[4]={1,2,3,4}; //密碼
code uchar table_right[]="welcome use!";
code uchar table_num[]="input password:";
code uchar table_error[]="input error!";
code uchar table_error1[]="Pls try again!";
unsigned char l_key=0; //定義變量,存放鍵值
unsigned char l_keyold=0xFF; //做為按鍵松開否的憑證
uchar buzyc,flag=0,mima;
uchar funtion_flag=0,temp_num;
char shi,fen,miao,nian,yue,ri,xin;
unsigned char l_tmpdate[8]={0x00,59,12,19,2,8,2};//顯示初值
unsigned char l_tmpdisplay[8]={0x40,0x40,0x40,0x40,0x40,0x40,0x40,0};//待顯示的數
code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8c,0x8a}; //1302寫入地址
code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8d,0x8b};//1302讀出地址
//code unsigned char table[]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00};//共陰數碼管 0-9 '-' '熄滅‘表
uchar date1[]="MON";
uchar date2[]="TUE";
uchar date3[]="WED";
uchar date4[]="THU";
uchar date5[]="FRI";
uchar date6[]="SAT";
uchar date7[]="SUN";
void ReadKey(void) //讀鍵盤值
{
unsigned char i,j,key,n;
j=0xfe;
key=0xff;//設定初值
for (i=0;i<3;i++)
{
P0=j; //P0口低4位循環輸出0,掃描鍵盤
if ((P0&0xf0)!=0xf0)
{ //如果有鍵按下,P0口高4位不會為1,
key=P0; //讀取P0口,退出循環,否則循環下次
break;
}
j=_crol_(j,1); //此函數功能為左循環移位
}
if (key==0xff)
{ //如果讀取不到P0口的值,比如是干擾,我們不做鍵值處理,返回
l_keyold=0xff;
P0=0xf0; //恢復P0口,等待按鍵按下
EX0=1; //返回之前,開啟外中斷
SPK=1;
return;
}
SPK=0; //有鍵按下,我們驅動蜂鳴器響
if(l_keyold==key)
{ //檢測按鍵放開否,如果一樣表明沒放開,
TH0=0X2E; //我們繼續啟動定時器,檢測按鍵松開否
TL0=0;
TR0=1;
return;
}
TH0=0X2E;
TL0=0;
TR0=1; //我們繼續啟動定時器,檢測按鍵松開否
l_keyold=key; //獲取鍵碼做為放開的憑證
for(i=0;i<10;i++)
{ //查表獲得相應的16進制值存放l_key變量中
if (key==key_tab[i])
{
l_key=i;
l_tmpdate1[n]=l_key;//將獲得的數裝入一個新的數組
n++;
if(n==4) //裝滿四位就從新裝入
n=0;
//判斷被按下去的數字與設定密碼是否相符
if(l_tmpdate1[0]==table_password[0]&l_tmpdate1[1]==table_password[1]&l_tmpdate1[2]==table_password[2]&l_tmpdate1[3]==table_password[3])
mima=1;
break;
}
}
//程序運行到這里,就表明有鍵值被讀取存放于l_key變量中,主程序就可以檢測此變量做相應外理,
//此時我們回到主程序
}
//延時函數
void delay(uint z) //延時函數,z的取值為這個函數的延時ms數,如delay(200);大約延時200ms.
{ //delay(500);大約延時500ms.
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//讀狀態,忙檢測處理函數
unsigned char ReadStatusLCD(void)
{
LCD_Data = 0xFF;
lcdrs = 0;
lcdrw = 1;
lcde = 0;
lcde = 0;
lcde = 1;
while ((LCD_Data & Busy)==Busy); //檢測忙信號
return(LCD_Data);
}
//寫命令子函數
void write_com(uchar com,buzyc)
{
if(buzyc)
ReadStatusLCD();//忙檢測
lcdrw=0;
lcdrs=0;
P2=com;
delay(3);
lcde=1;
delay(6);
lcde=0;
}
//寫數據子函數
void write_date(uchar date)
{
ReadStatusLCD();//忙檢測
lcdrw=0;
lcdrs=1;
P2=date;
delay(3);
lcde=1;
delay(6);
lcde=0;
}
//初始化函數
void init()
{
H=0;
lcde=0;
delay(15);
write_com(0x38,0);
delay(5);
write_com(0x38,0);
delay(5);
write_com(0x38,0);
write_com(0x38,1); //設置led為16×2顯示,5×7點陣,8位數據口
write_com(0x0f,1); //開顯示,顯示光標,光標閃爍
write_com(0x06,1); //光標自動移動,整屏不動
write_com(0x01,1); //顯示清屏,數據指針和地址指針全部清零
write_com(0x80,1); //設置數據指針到屏幕的最開始端
}
/*****************************************************************************************************
字節寫入子函數:
將要寫入的數字先右移一位,是最低位溢出,然后在scl2的一個上升沿數據被寫入DS1302,注意
數據的寫入時從低位到高位
*****************************************************************************************************/
void Write_Ds1302_Byte(unsigned char date)
{
uchar j,temp;
temp=date;
for(j=0;j<8;j++)
{
temp=temp>>1; //將數據右移一位使最低位溢出
SDA2=CY; //將待寫入數據最低位寫入數據緩沖
SCL2=0;
SCL2=1; //在scl的上升延寫入數據
}
}
/*****************************************************************************************************
字節讀出子函數:
分8次讀出數據,將讀出的數據存入temp:在時鐘信號的下降沿讀出一個字節的數據
數據讀出也是從低位到高位的
*****************************************************************************************************/
uchar Read_Ds1302_Byte()
{
uchar j,temp;
for(j=0;j<8;j++)
{
temp=temp>>1; //將temp右移一位使最高位變為次高位,最高為為0
SDA2=1;
SCL2=1;
SCL2=0; //在scl2的一個下降沿數據讀出
if(SDA2==1)//如果讀出的數據為1,即在temp的最高位寫入1,為0的時候則寫入0
temp=temp|0x80;
temp=temp|0x00;
}
return temp;
}
/***************************************************************************************************************
數據寫入DS1302函數:
在指定地址寫入指定數據,在rst為低scl2為低的情況下將rst置高,即允許數據寫入
先寫入地址
然后寫入數據
最后將rst拉低結束數據寫入
****************************************************************************************************************/
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
SCL2=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
RST=1;
_nop_();_nop_();_nop_();_nop_();_nop_(); //開啟,寫入數據地址,這是本串口協議的開始,加入延時防止干擾
Write_Ds1302_Byte(address); //發送地址
Write_Ds1302_Byte(dat); //發送數據
RST=0; //恢復
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -