给你一个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;
}
} |