給你一個6位數碼管顯示的密碼鎖程序參考,顯示程序雖然不能直接套用,但可以提供思路和程序框架。單片機型號STC89C52RC,實驗板TX-1C,鍵盤電路是4*4+4。有詳細注釋,希望對你有所幫助。
#include <AT89X52.H> //Keil庫頭文件
#include <intrins.h> //Keil庫頭文件
#define uint unsigned int //宏定義無符號整型數據
#define uchar unsigned char //宏定義無符號字符型數據
#define ulong unsigned long //宏定義無符號長整型數據
/****定義ISP的操作命令*****/
#define RdCommand 0x01 //讀命令
#define PrgCommand 0x02 //寫命令
#define EraseCommand 0x03 //擦除命令
#define WaitTime 0x01 //定義CPU的等待時間,寫入硬件延時
#define Error 0 //錯誤
#define OK 1 //正確
/*STC89系列EEPROM寄存器聲明*/
sfr ISP_DATA=0xe2; //0000,0000 EEPROM數據寄存器
sfr ISP_ADDRH=0xe3; //0000,0000 EEPROM地址高字節
sfr ISP_ADDRL=0xe4; //0000,0000 EEPROM地址第字節
sfr ISP_CMD=0xe5; //xxxx,xx00 EEPROM命令寄存器
sfr ISP_TRIG=0xe6; //0000,0000 EEPRPM命令觸發寄存器
sfr ISP_CONTR=0xe7; //0000,x000 EEPROM控制寄存器
/********端口定義**********/
sbit dula=P2^6; //段選
sbit wela=P2^7; //位選
sbit Q1=P1^5; //門鎖電磁開關端口定義
sbit Q2=P1^6; //門鎖電磁開關端口定義
sbit Buzzer=P2^3; //蜂鳴器端口定義
sbit LED=P1^3;
sbit key_1=P3^4; //清除鍵
sbit key_2=P3^5; //上鎖鍵
sbit key_3=P3^6; //開鎖鍵
sbit key_4=P3^7; //萬能密鑰操作鍵
/****數組及變量聲明*****/
uchar code table[]={ //共陰數碼管數組0~F
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar table1[6]; //輸入密碼緩存
uchar table2[6]; //讀取EEPROM密碼緩存
uchar key=0xff; //定義鍵值變量
uchar P_bit=0; //密碼的位次變量
uchar Buzzer_sign=0; //響鈴次數變量
uchar ERROR; //密碼錯誤
bit key_sign=0; //操鍵標志
bit second=1; //響鈴允許位
bit Set_up=0; //萬能密鑰設置標志
/***********子函數聲明**************/
void ISP_IAP_enable(); //打開 ISP,IAP 功能
void ISP_IAP_disable(); //關閉 ISP,IAP 功能
void ISPgoon(); //公用的觸發代碼
uchar byte_read(uint byte_addr); //字節讀
void SectorErase(uint sector_addr); //扇區擦除
void byte_write(uint byte_addr, uchar original_data); //字節寫
void Timer0Init(); //初始化定時器
void keyscan(); //按鍵掃描程序
void key_service(); //按鍵服務程序
void display(); //數碼管動態顯示程序
void Buzzer_second(); //蜂鳴器響鈴程序
void hdmm();
void Universal_key(); //萬能密鑰
void delayms(uint k); //軟件延時程序
void baojing(); //報警程序
/************主函數************/
void main()
{
Timer0Init(); //初始化定時器
Q1=1;Q2=0; //初始化門栓
Buzzer=1; //初始化蜂鳴器
Universal_key(); //萬能密鑰
Buzzer_sign=1; //加電響提示聲
while(1)
{
keyscan(); //矩陣按鍵掃描程序
key_service(); //按鍵服務程序
Buzzer_second(); //蜂鳴器響鈴
display(); //4位數碼管顯示程序
baojing(); //報警程序
}
}
/*********初始化定時器***********/
void Timer0Init() //50毫秒@11.0592MHz
{
TMOD= 0x01; //設置定時器模式
TL0 = 0x00; //設置定時初值
TH0 = 0x4C; //設置定時初值
TF0 = 0; //清除TF0標志
// TR0 = 1; //開定時器0
EA = 1; //開總中斷
ET0 = 1; //開T0中斷
}
/************按鍵掃描程序**************/
void keyscan()
{
static bit sign=0,sign1=0,sign2=0,sign3=0; //按鍵有效標志
static uint count=0,count1=0,count2=0,count3=0; //消抖計數變量
uchar num=0; //臨時變量
/**************矩陣按鍵部分****************/
P3=0x0f; //賦值P3 1111 0000
if(P3!=0x0f) //檢測有按鍵按下
{
count++; //消抖計數
if((count>=1000)&&(sign==0)) //100~1000,根據主循環周期調整約10~20ms
{
sign=1; //按鍵有效標志置1
num=P3; //保存P3值xxxx 0000,x為0或1
num|=0xf0; //保存num按位或0x0f值xxxx 1111
P3=num; //賦值P3 xxxx 1111
num=P3; //保存P3值xxxx xxxx
switch(num)
{
case 0xee: key= 1; break;
case 0xde: key= 2; break;
case 0xbe: key= 3; break;
case 0x7e: key= 4; break;
case 0xed: key= 5; break;
case 0xdd: key= 6; break;
case 0xbd: key= 7; break;
case 0x7d: key= 8; break;
case 0xeb: key= 9; break;
case 0xdb: key= 0; break;
// case 0xbb: key=11; break;
// case 0x7b: key=12; break;
// case 0xe7: key=13; break;
// case 0xd7: key=14; break;
// case 0xb7: key=15; break;
// case 0x77: key=16; break;
}
key_sign=1; //操鍵標志1
Buzzer_sign=1;//按鍵提示聲
}
}
else //鍵抬起
{
sign=0; //按鍵有效標志清0
count=0; //消抖計數清0
}
/**************獨立按鍵部分***************/
P3=0xff; //P3復位
if(key_1==0)
{
count1++; //消抖計數
if((count1>=1000)&&(sign1==0)) //100~1000,根據主循環周期調整約10~20ms
{
sign1=1; //按鍵有效標志置1
key=13;
key_sign=1; //操鍵標志1
Buzzer_sign=1;//按鍵提示聲
}
}
else //鍵抬起
{
sign1=0; //按鍵有效標志清0
count1=0; //消抖計數清0
}
if(key_2==0)
{
count2++; //消抖計數
if((count2>=1000)&&(sign2==0)) //100~1000,根據主循環周期調整約10~20ms
{
sign2=1; //按鍵有效標志置1
key=14;
key_sign=1; //操鍵標志1
Buzzer_sign=1;//按鍵提示聲
}
}
else //鍵抬起
{
sign2=0; //按鍵有效標志清0
count2=0; //消抖計數清0
}
if(key_3==0)
{
count3++; //消抖計數
if((count3>=1000)&&(sign3==0)) //100~1000,根據主循環周期調整約10~20ms
{
sign3=1; //按鍵有效標志置1
key=15;
key_sign=1; //操鍵標志1
Buzzer_sign=1;//按鍵提示聲
}
}
else //鍵抬起
{
sign3=0; //按鍵有效標志清0
count3=0; //消抖計數清0
}
}
/***********按鍵服務程序***************/
void key_service()
{
uchar i; //臨時變量
if(key_sign==1) //操鍵標志如果1
{
key_sign=0; //操鍵標志清0
if((P_bit<6)&&(key<11))
{
P_bit++;
switch(P_bit)
{
case 1:table1[0]=key;break;
case 2:table1[1]=key;break;
case 3:table1[2]=key;break;
case 4:table1[3]=key;break;
case 5:table1[4]=key;break;
case 6:table1[5]=key;break;
default: break;
}
}
if((key>12)&&(key<16))
{
switch(key)
{
case 13:
if(P_bit>0)
P_bit--;
switch(P_bit)
{
case 5:table1[5]=0; break;
case 4:table1[4]=0; break;
case 3:table1[3]=0; break;
case 2:table1[2]=0; break;
case 1:table1[1]=0; break;
case 0:table1[0]=0; break;
default: break;
}
break;
case 14:
//保存密碼、鎖門
if((Q1==1)&&(Q2==0)&&(P_bit==6))
{
EA = 0; //關總中斷
SectorErase(0x2000);//擦除EEPROM扇區中的數據
for(i=0;i<6;i++)
{
byte_write(0x2000+i,table1);//重新寫入密碼
}
EA = 1; //開總中斷
Q1=0; //門鎖狀態
Q2=1; //門鎖狀態
P_bit=0; //密碼的位次變量清0
}
else Buzzer_sign=2;//警示錯誤
break;
case 15:
//核對密碼、開門
if((Q1==0)&&(Q2==1)&&(P_bit==6)&&(Set_up==0))
{
EA = 0; //關總中斷
for(i=0;i<6;i++)
{
table2=byte_read(0x2000+i);//讀取EEPROM中數據保存在table2
}
EA = 1; //開總中斷
if((table1[0]==table2[0])&&(table1[1]==table2[1])&&(table1[2]==table2[2])
&&(table1[3]==table2[3])&&(table1[4]==table2[4])&&(table1[5]==table2[5])) //核對密碼
{
Q1=1; //門鎖狀態
Q2=0; //門鎖狀態
P_bit=0; //密碼的位次變量清0
}
else
{
ERROR++; //密碼錯誤計數
Buzzer_sign=2;//警示錯誤
}
}
else Buzzer_sign=2;//警示錯誤
break;
}
}
}
}
/************數碼管動態顯示程序**************/
void display()
{
static uchar num=0; //時分顯示變量
switch(num)
{
case 0:
P0=0xff; //不選擇位
wela=1;
wela=0;
if(P_bit==0)
P0=0x00; //消隱
num++;
break;
case 1:
P0=0x00; //消隱
dula=1;
dula=0;
P0=0xdf; //第1位位碼
wela=1;
wela=0;
if(P_bit<1)
P0=0x00;
else
{
if(P_bit==1)P0=table[table1[0]];//第1位段碼
if(P_bit==2)P0=table[table1[1]];
if(P_bit==3)P0=table[table1[2]];
if(P_bit==4)P0=table[table1[3]];
if(P_bit==5)P0=table[table1[4]];
if(P_bit==6)P0=table[table1[5]];
}
dula=1;
dula=0;
num++;
break;
case 2:
P0=0x00; //消隱
dula=1;
dula=0;
P0=0xef; //第2位位碼
wela=1;
wela=0;
if(P_bit<2)
P0=0x00;
else
{
if(P_bit==2)P0=table[table1[0]];//第2位段碼
if(P_bit==3)P0=table[table1[1]];
if(P_bit==4)P0=table[table1[2]];
if(P_bit==5)P0=table[table1[3]];
if(P_bit==6)P0=table[table1[4]];
}
dula=1;
dula=0;
num++;
break;
case 3:
P0=0x00; //消隱
dula=1;
dula=0;
P0=0x77; //第3位位碼
wela=1;
wela=0;
if(P_bit<3)
P0=0x00;
else
{
if(P_bit==3)P0=table[table1[0]];//第3位段碼
if(P_bit==4)P0=table[table1[1]];
if(P_bit==5)P0=table[table1[2]];
if(P_bit==6)P0=table[table1[3]];
}
dula=1;
dula=0;
num++;
break;
case 4:
P0=0x00; //消隱
dula=1;
dula=0;
P0=0x7b; //第4位位碼
wela=1;
wela=0;
if(P_bit<4)
P0=0x00;
else
{
if(P_bit==4)P0=table[table1[0]];//第4位段碼
if(P_bit==5)P0=table[table1[1]];
if(P_bit==6)P0=table[table1[2]];
}
dula=1;
dula=0;
num++;
break;
case 5:
P0=0x00; //消隱
dula=1;
dula=0;
P0=0x7d; //第5位位碼
wela=1;
wela=0;
if(P_bit<5)
P0=0x00;
else
{
if(P_bit==5)P0=table[table1[0]];//第5位段碼
if(P_bit==6)P0=table[table1[1]];
}
dula=1;
dula=0;
num++;
break;
case 6:
P0=0x00; //消隱
dula=1;
dula=0;
P0=0x7e; //第6位位碼
wela=1;
wela=0;
if(P_bit<6)
P0=0x00;
else
P0=table[table1[0]]; //第6位段碼
dula=1;
dula=0;
num=0;
break;
}
}
/*****************************
蜂鳴器間歇響鈴
*****************************/
void Buzzer_second()
{
if((second==1)&&(Buzzer_sign>0))//響鈴允許1與響鈴次數
{
second=0; //響鈴允許清0,等待下一秒
Buzzer=0; //蜂鳴器響
Buzzer_sign--; //響鈴次數減1
TR0=1; //開定時器
}
}
/*-----------------------------
定時器0中斷服務程序 50毫秒
------------------------------*/
void timer0() interrupt 1
{
static uchar count=0; //中斷計數變量
count++; //中斷計數變量count3自+1
if(count==1) //0.1秒時間到
Buzzer=1; //蜂鳴器端口復位
if(count>=2) //1秒
{
count=0; //中斷計數變量清0
second=1; //響鈴允許置1
TR0 = 0; //定時器0關閉
}
}
/* ================ 打開 ISP,IAP 功能 ================= */
void ISP_IAP_enable()
{
EA = 0; /* 關中斷 */
ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */
ISP_CONTR = ISP_CONTR | WaitTime; /* 寫入硬件延時 */
ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */
}
/* =============== 關閉 ISP,IAP 功能 ================== */
void ISP_IAP_disable()
{
ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
ISP_TRIG = 0x00;
EA = 1; /* 開中斷 */
}
/* ================ 公用的觸發代碼 ==================== */
void ISPgoon()
{
ISP_IAP_enable(); /* 打開 ISP,IAP 功能 */
ISP_TRIG = 0x46; /* 觸發ISP_IAP命令字節1 */
ISP_TRIG = 0xb9; /* 觸發ISP_IAP命令字節2 */
_nop_();
}
/* ==================== 字節讀 ======================== */
uchar byte_read(uint byte_addr)
{
ISP_ADDRH = (uchar)(byte_addr >> 8);/* 地址賦值 */
ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */
ISP_CMD = ISP_CMD | RdCommand; /* 寫入讀命令 */
ISPgoon(); /* 觸發執行 */
ISP_IAP_disable(); /* 關閉ISP,IAP功能 */
return (ISP_DATA); /* 返回讀到的數據 */
}
/* ================== 扇區擦除 ======================== */
void SectorErase(uint sector_addr)
{
uint iSectorAddr;
iSectorAddr = (sector_addr & 0xfe00); /* 取扇區地址 */
ISP_ADDRH = (uchar)(iSectorAddr >> 8);
ISP_ADDRL = 0x00;
ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位 */
ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */
ISPgoon(); /* 觸發執行 */
ISP_IAP_disable(); /* 關閉ISP,IAP功能 */
}
/* ==================== 字節寫 ======================== */
void byte_write(uint byte_addr, uchar original_data)
{
ISP_ADDRH = (uchar)(byte_addr >> 8); /* 取地址 */
ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */
ISP_CMD = ISP_CMD | PrgCommand; /* 寫命令2 */
ISP_DATA = original_data; /* 寫入數據準備 */
ISPgoon(); /* 觸發執行 */
ISP_IAP_disable(); /* 關閉IAP功能 */
}
/**********萬能密鑰***********/
void Universal_key()
{
while(!key_1&&!key_2&&!key_3)
{
delayms(5000); //延時5秒
while(!key_1&&!key_2&&!key_3)
{
Set_up=1; //萬能密鑰設置標志置1
LED=0;
while(!key_1&&!key_2&&!key_3); //等待鍵抬起
delayms(200); //延時
}
}
while(Set_up) //萬能密鑰設置標志為1
{
if(key_4==0)
{
Set_up=0; //萬能密鑰設置標志清0
LED=1;
}
keyscan(); //矩陣按鍵掃描程序
key_service(); //按鍵服務程序
Buzzer_second(); //蜂鳴器響鈴
display(); //數碼管顯示程序
}
}
/*-------------------------------
1ms延時子程序(11.0592MHz 12T)
-------------------------------*/
void delayms(uint k)
{
uint i,j;
for(i=k;i>0;i--)
for(j=114;j>0;j--);
}
/*-------------------------------
報警程序
-------------------------------*/
void baojing()
{
if(ERROR>=3) //密碼錯誤3次
{
Buzzer_sign=255; //響鈴次數
P0=0x00;
dula=1;
dula=0;
while(Buzzer_sign)
{
Buzzer_second(); //蜂鳴器響鈴
// display();
}
ERROR=0;
}
} |