SCH圖正在繪制中。。。
#include <REGX51.H>//51單片機的頭文件
typedef unsigned char uchar; //類型定義,定義uchar類型
typedef unsigned int uint; //類型定義,定義uint 類型
//鍵盤子程序相關說明。
#define BLANKCHAR 10 //定義空白常量
#define PCHAR 11 //定義字符P常量
#define OPENCHAR 12 //定義開鎖字符常量
#define ALARMCHAR 13 //定義字符A常量
#define LINECHAR 14 //定義字符-常量
#define BACKKEY 0X0D //定義退格鍵常量
#define ENTERKEY 0X0F //定義確認鍵常量
#define LOCKKEY 0X0E //定義閉鎖鍵常量
#define NO_KEY 20 //定義無按鍵返回值
#define KEYPORT P2 //定義鍵盤端口
//Delay1Ms
void Delay1Ms()
{
uint i;
for (i=0;i<1000;i++);
}
//定義按鍵掃描碼表 按鍵掃描時,4位列線和4位行線組成字節數據表
uchar code KEYCODE[]=
{0XEE,0XED,0XEB,0XE7,
0XDE,0XDD,0XDB,0XD7,
0XBE,0XBD,0XBB,0XB7,
0X7E,0X7D,0X7B,0X77};
uchar KeyPre; //保存上次掃描按鍵的鍵值
uchar KeyUp;
//用於控制按鍵去抖動操作。1:掃描時去抖動 2:等待釋放 3:釋放時去抖動。
#define LEDPORT P0 //定義顯示器段碼輸出端口
#define LEDCON P1 //定義顯示器位控制端口
uchar code SEGCODE[]=
{0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,// 0~9的***陽極代碼
0xff,//不顯示的***陽極段碼
0X8C,//字符P的***陽極段碼
0X8F,//┝的***陽極段碼
0X88,//字符A的***陽極段碼
0XBF,//字符-的***陽極段碼
};
//定義LED位碼控制碼
uchar code BITCODE[]={0Xfe,0Xfd,0Xfb,0Xf7,0Xef,0Xdf,0Xbf,0X7f};
uchar DispBuf[6]; //保存顯示的字符
bit DispNormal; //控制顯示時,是正常顯示還是閃爍顯示。
uchar DispCnt; //控制閃爍顯示時的頻率。
#define SHORT_TIME 10 //蜂鳴器響200ms
#define LONG_TIME 100 //蜂鳴器響2s
#define LONGER_TIME 9000 //蜂鳴器響3 minutes
sbit ALARMCON=P3^4; //定義報警控制引腳
bit AlarmEnable; //是否報警或聲音提示
uint AlarmTime; //控制報警時間長度
sbit LOCKCON=P3^3; //定義電子鎖控制引腳
uchar code PassWord[]={1,2,3,4,5}; //定義初時密碼表
uchar PassInBuf[6]; //保存輸入的密碼字符
uchar PassPosi; //用戶輸入密碼字符存放在PassInBuf[]的位置。
bit TimerBit; //20ms定時時間到
uchar SysMode; //系統所處模式 0:輸入密碼模式 1:報警模式 2:開鎖模式
uchar ErrorCnt; //用戶連續輸入密碼出錯次數。
/*
入口參數:
FillChar:寫入緩沖區的字符
出口參數:無
*/
void Fill_Buf(uchar FillChar)
{
uchar i;
for(i=0;i<6;i++)
{
DispBuf[i]=FillChar;//用字符FillChar填充DispBuf[i]
PassInBuf[i]=FillChar; //用字符FillChar填充PassInBuf [i]
}
}
void Fill_Buf_P()
{
Fill_Buf(BLANKCHAR); // DispBuf[1..5]= ' '
DispBuf[0]=PCHAR;// DispBuf[0]='P'
}
void Fill_Buf_O()
{
Fill_Buf(BLANKCHAR); // DispBuf[1..5]= ' '
DispBuf[0]=OPENCHAR; // DispBuf[0]='┝'
}
void Fill_Buf_A()
{
Fill_Buf(LINECHAR); // DispBuf[1..5]= ' -----'
DispBuf[0]=ALARMCHAR; // DispBuf[0]='A'
}
/*
入口參數:
DispPosi:要顯示數據的LED號。
DispChar:要顯示的內容。
出口參數:無
*/
void Disp_Led_Sin(uchar DispChar,uchar DispPosi)
{
LEDPORT=SEGCODE[DispChar];//輸出顯示段碼
LEDCON&=BITCODE[DispPosi];//輸出顯示位碼
Delay1Ms(); //延時1MS
LEDCON|=0X3F;//關閉顯示器
}
/*(2)關閉顯示函數Disp_Led_OFF。
函數Disp_Led_OFF在顯示器上顯示空白字符,主要用在閃爍顯示。函數通過6次調用Disp_Led_Sin實現所需功能。代碼如下:*/
void Disp_Led_OFF()
{
uchar i;
LEDCON|=0X3F;// 關閉顯示器
for(i=0;i<6;i++)
{
Disp_Led_Sin(BLANKCHAR,i);//逐個顯示空白字符
}
}
void Disp_Led_All()
{
uchar i;
LEDCON|=0X3F; // 關閉顯示器
for(i=0;i<6;i++)
{
Disp_Led_Sin(DispBuf[i],i); //顯示DispBuf[]中的數值
}
}
void Disp_LED()
{
DispCnt++;
DispCnt%=10;
if(DispCnt==0)
{
DispNormal=~DispNormal;//200ms將閃爍顯示控制位取反
}
if(SysMode==1)
{//報警模式,閃爍顯示
if(!DispNormal)
{
Disp_Led_OFF();//顯示空白字符
return;
}
}
Disp_Led_All();//顯示DispBuf[]中的數值
}
/*
入口參數:
stime:蜂鳴器鳴叫時間。
出口參數:無
*/
void Sys_Speaker(uint stime)
{
AlarmEnable=1;//允許報警
AlarmTime=stime;//報警時間長短
}
void Sys_Alarm()
{
if(AlarmEnable==1)
{//允許報警
ALARMCON=0;//報警
AlarmTime--;
if(AlarmTime==0)
{//停止報警時間到
AlarmEnable=0;
ALARMCON=1;//禁止報警
if(SysMode==1)
{//報警發生在模式1時,要返回模式0
SysMode=0;
Fill_Buf_P();//顯示P
}
}
}
}
/*
入口參數:無
出口參數:按鍵值或無按鍵
*/
uchar Find_Key()
{
uchar KeyTemp,i;
KEYPORT=0xf0;//行線輸出0,列線輸出全1
KeyTemp=KEYPORT;//讀按鍵端口值
if(KeyTemp==0xf0)
return NO_KEY;//無鍵按下,返回
KEYPORT=KeyTemp|0x0f;//列線輸出,行線輸入
KeyTemp=KEYPORT;//讀取按鍵端口值
for(i=0;i<16;i++)
{
if(KeyTemp==KEYCODE[i])//根據按鍵端口掃描值,查找按鍵值
return i;//返回按鍵值
}
return NO_KEY;
}
/*
入口參數:無
出口參數:按鍵值或無按鍵
*/
uchar Scan_Key()
{
uchar KeyTemp;
KeyTemp=Find_Key();//掃描鍵盤,獲得按鍵值
if(KeyTemp==NO_KEY)
{
if(KeyUp<2)
{//無按鍵按下,返回
KeyUp=0;
return NO_KEY;
}
if(KeyUp==2)
{//按鍵要釋放,延時去抖動
KeyUp=3;
return NO_KEY;
}
if(KeyUp==3)
{//按鍵釋放,返回鍵值
KeyUp=0;
return KeyPre;
}
}
else
{
if(KeyUp==0)
{//有鍵按下,保存鍵值
KeyUp=1;
KeyPre=KeyTemp;
}
else if(KeyUp==1)
{//去抖動後,再次測到有按鍵按下
if( KeyPre==KeyTemp)
KeyUp=2;
else
KeyPre=KeyTemp;
} else if(KeyUp==3)
{//等待按鍵釋放
KeyUp=2;
}
}
return NO_KEY;
}
/*
入口參數:
Key:按鍵值
出口參數:無
*/
void Key_Process(uchar Key)
{
uchar i;
if(Key==NO_KEY)
return ;//無按鍵,不處理
switch(SysMode)
{
case 0://輸入密碼
switch(Key)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
DispBuf[PassPosi]=LINECHAR;//顯示'-'
PassInBuf[PassPosi]=Key;//保存用戶輸入的密碼
if(PassPosi<5)
PassPosi++;//調整密碼輸入位置
Sys_Speaker(SHORT_TIME);//發按鍵提示音
break;
case BACKKEY://退格鍵
DispBuf[PassPosi]=BLANKCHAR;//顯示' '
PassInBuf[PassPosi]=BLANKCHAR;//清除當前位置的密碼
if(PassPosi>1)
PassPosi--;//調整顯示位置
Sys_Speaker(SHORT_TIME);//發按鍵提示音
break;
case ENTERKEY://確定按鍵
for(i=0;i<5;i++)
{//比較用戶輸入密碼與系統預設密碼是否壹致
if(PassInBuf[i+1]!=PassWord[i])
break;
}
if(i>=5)
{//輸入密碼正確
Fill_Buf_O();//顯示開鎖狀態
PassPosi=1;
LOCKCON=1;//開鎖
ErrorCnt=0;
Sys_Speaker(LONG_TIME);//發長提示音
SysMode=2;//轉模式2
}
else
{
ErrorCnt++;//出錯次數加壹
if(ErrorCnt>2)
{//次數超過3次
ErrorCnt=0;
Fill_Buf_A();//顯示報警狀態
PassPosi=1;
Sys_Speaker(LONGER_TIME);//發報警音
SysMode=1;
}
else
{//出錯次數少於3次,用戶重新輸入
Fill_Buf_P();
PassPosi=1;
Sys_Speaker(LONG_TIME);
}
}
break;
case LOCKKEY://閉鎖鍵
Fill_Buf_P();//顯示P
PassPosi=1;
Sys_Speaker(SHORT_TIME);
break;
}
break;
case 2://開鎖狀態
if(Key==LOCKKEY)
{//用戶按動閉鎖按鍵
Fill_Buf_P();
SysMode=0;
LOCKCON=0;//閉鎖
Sys_Speaker(SHORT_TIME);
}
break;
}
}
void Ini_Timer0()
{
TMOD&=0XF0;
TMOD|=0X01;// 初始化T0,模式1
TR0=0;
TH0=(65536-20000)/256;//T0 賦計數初值
TL0=(65536-20000)%256;
TR0=1;//啟動T0
ET0=1;//允許T0中斷
}
void Timer0() interrupt 1
{
TR0=0;
TH0=(65536-20000)/256; //T0 賦計數初值
TL0=(65536-20000)%256;
TR0=1;
TimerBit=1;//定時時間到
}
void Ini_System()
{
PassPosi=1;
LOCKCON=0;//閉鎖
Ini_Timer0();//初始化T0
Fill_Buf_P();
EA=1;//允許系統中斷
}
void main()
{
uchar KeyTemp;
Ini_System();
while(1)
{
if (TimerBit==1)
{//定時時間到
Disp_LED();//刷新顯示器
Sys_Alarm();//報警處理
KeyTemp=Scan_Key();//掃描按鍵
Key_Process(KeyTemp);//按鍵處理
TimerBit=0;
}
}
}