目录
1.需要的硬件
2.EEPROM功能
因为密码存取在单片机内存中,重启后密码又返回初始化的值,数据易丢失。
因为EEPROM的数据单片机关机重启后数据不会发生改变,永远存在内存之中。
可以用来存取密码修改后存取的位置。
只有重新写入当地址的数据才会改变。
3.主要功能
用按键输入密码,密码错误蜂鸣器响1S后关闭,
密码错误超过3次就不能再输入密码数码管显示on。
密码输入正确数码管显示open。输入密码正确后按下S19可以修改密码再次按下S19确定修改的密码。
EEPROM可以对密码进行保护和修改。
4.按键功能
S19只有密码输入正确才能使用
S4 (0) | S8 (4) | S12(8) | S16(减位) |
S5 (1) | S9 (5) | S13(9) | S17(清除) |
S6 (2) | S10(6) | S14(无) | S18(无) |
S7 (3) | S11(7) | S15(无) | S19(修改密码) |
5.数码管与LED与蜂鸣器与继电器功能
1.密码输入时
数码管显示数字一步步向左移,最右位显示刚刚按下的数字。
2.密码输入正确
LED灯隔个点亮,继电器吸合,数码管显示open
3.密码输入错误 时
前两次密码错误蜂鸣器响
第三次密码再次错误数码管显示on,密码无法再次输入。
6.修改密码功能
输入密码正确后按下S19,进入修改密码再次按下S19确定修改的密码。
修改密码LED灯1亮。
7.初始化
1.初始密码为:888888。
2.蜂鸣器关闭,继电器关闭。
3.LED灯关闭。
注意事项
修改密码时候不能关机要不然无法存入密码,密码还没有初始值。导致输入什么密码都是错误的。
这样情况可以重新在EEPROM的0X08地址写入0,下载进去然后又下载原来的程序就行了。
8.代码
main
#include <STC15F2K60S2.H>
#include "iic.h"
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
while(xms--)
{
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
}
void Timer2Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x20; //设置定时初始值
T2H = 0xD1; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |=0x04;
EA=1;
}
int ms;
void Device(unsigned char p2,unsigned char p0)//配置138锁存器
{
P0=p0;
P2=P2&0x1f|p2;
P2=P2&0x1f;
}
void system()//初始化
{
Device(0x80,0xff);//关闭LED灯
Device(0xa0,0);//关闭蜂鸣器
}
// P E n k
unsigned char Nixie[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x73,0x79,0x54,0x70};
void smg(unsigned n,unsigned m)//配数码管显示函数
{
int a;
a=0x01<<n;
Device(0xc0,0);
Device(0xe0,~Nixie[m]);//显示内容
Device(0xc0,a);//显示位置
}
long int i=0;//按键的值
int s=0;//按键按下次数
int k=0;//用于修改密码的变量
int q=0;//密码正确操作的变量
int m=0;//用于数码管显示
/*
*S4 0; S5 1; S6 2;S7 3
*S8 4; S9 5; S10 6;S11 7
*S12 8; S13 9; S14 无;S15 无
*S16 减位; S17 清除; S18 无;S19 修改密码
*/
//三次密码错误后就不能输入密码了
//密码输入正确后按S19才能更改密码
void kby()//密码输入与修改
{
P3=0xff;P44=0;P42=1;//行扫描
if(P33==0) {Delay(1);if(P33==0){i=i*10+0,s++;while(P33==0){}}}//4
if(P32==0) {Delay(1);if(P32==0){i=i*10+1;s++;while(P32==0){}}}
if(P31==0) {Delay(1);if(P31==0){i=i*10+2;s++;while(P31==0){}}}
if(P30==0) {Delay(1);if(P30==0){i=i*10+3;s++;while(P30==0){}}}
P3=0xff;P42=0;P44=1;
if(P33==0) {Delay(1);if(P33==0){i=i*10+4;s++;while(P33==0){}}}//8
if(P32==0) {Delay(1);if(P32==0){i=i*10+5;s++;while(P32==0){}}}
if(P31==0) {Delay(1);if(P31==0){i=i*10+6;s++;while(P31==0){}}}
if(P30==0) {Delay(1);if(P30==0){i=i*10+7;s++;while(P30==0){}}}
P3=0xdf;P4=0xff;
if(P33==0) {Delay(1);if(P33==0){i=i*10+8;s++;while(P33==0){}}}
if(P32==0) {Delay(1);if(P32==0){i=i*10+9;s++;while(P32==0){}}}
P3=0xef;P4=0xff;
if(P33==0) {Delay(1);if(P33==0){i=i/10;s--;while(P33==0){}}}
if(P32==0) {Delay(1);if(P32==0){i=0;s=0;while(P32==0){}}}
}
void smg_correct()//显示 open
{
smg(4,0); Delay(1);
smg(5,10);Delay(1);
smg(6,11);Delay(1);
smg(7,12);Delay(1);
}
void smg_show() //显示i的值
{
//Delay(1)作用增加数码管显示亮度
smg(2,i/100000);Delay(1);
smg(3,i/10000%10);Delay(1);
smg(4,i/1000%10);Delay(1);
smg(5,i/100%10);Delay(1);
smg(6,i/10%10);Delay(1);
smg(7,i%10);Delay(1);
}
long int d,e,f,r,t,y;//用于接收EEPROM里面存取的数字
long int shong=0;
void smh()//读取EEPROM里面存取的数字
{
d=ucRead_EEPROM(0x01)*100000;
e=(long int)ucRead_EEPROM(0x02)*10000;
f=ucRead_EEPROM(0x03)*1000;
r=ucRead_EEPROM(0x04)*100;
t=ucRead_EEPROM(0x05)*10;
y=ucRead_EEPROM(0x06);
shong=d+e+f+r+t+y;
}
int kl=1;//用于判断是否修改密码变量
long int o=888888;//初始值密码
int ccr=0;//密码错误1s后关闭蜂鸣器使用的变量
void main()
{
system();
Timer2Init();
Write_EEPROM(0x07,0);
/*
修改密码时候不能关机要不然无法存入密码,密码还没有初始值。
这样情况可以重新在EEPROM的0X08地址写入0,下载进去然后又下载原来的程序就行了。
*/
//Write_EEPROM(0x08,0);
//如果修改密码过0x08地址的值变成1
if((ucRead_EEPROM(0x07)==0)&&(ucRead_EEPROM(0x08)==1))
{
kl=0;
}
//判断需要不重新初始化密码
if((k==0)&&(kl==1))
{
Write_EEPROM(0x01,o/100000);
Write_EEPROM(0x02,o/10000%10);
Write_EEPROM(0x03,o/1000%10);
Write_EEPROM(0x04,o/100%10);
Write_EEPROM(0x05,o/10%10);
Write_EEPROM(0x06,o%10);
smh();
}
while(1)
{
smh(); //不断获取最新密码值
//显示i的值未输入正确密码的值
if(m!=1)
{
smg_show();
kby();
}
//S19第一次按下LED1亮
if(k==1)
{
m=0;
s=0;
Device(0x80,~0x01);
P3=0xef;P4=0xff;
if(P30==0) {Delay(1);if(P30==0){k=2;while(P30==0){}}}
}
//输入密码正确后操作
if((i==shong)&&(s==6)&&(k==0))
{
i=0;
q=1;
m=1;
s=0;
}
//S19第二次按下密码的值发生改变
if(k==2)
{
o=i;
Write_EEPROM(0x01,o/100000);
Write_EEPROM(0x02,o/10000%10);
Write_EEPROM(0x03,o/1000%10);
Write_EEPROM(0x04,o/100%10);
Write_EEPROM(0x05,o/10%10);
Write_EEPROM(0x06,o%10);
Write_EEPROM(0x08,1);
smh();
i=0;
s=0;
q=0;
m=0;
k=0;
}
//输入密码错误操作
if((i!=shong)&&(s==6)&&(k==0))
{
Device(0xa0,0x40);
i=0;
s=0;
ms=0;
ccr++;
}
}
}
void t2() interrupt 12//中断入口
{
ms++;
//密码输入错误1秒钟后关闭蜂鸣器
if((ms==1000)&&(ccr<3))
{
Device(0xa0,0);
}
//输入密码错误超过三次的现象
if(ccr==3)
{
m=1;
smg(3,0);Delay(1);
smg(4,12);Delay(1);
Device(0xa0,0);
}
//密码正确的操作
if((q==1)&&(k==0))
{
smg_correct();
Device(0xa0,0x10);
Device(0x80,0xaa);
P3=0xef;P4=0xff;
if(P30==0) {Delay(1);if(P30==0){k=1;while(P30==0){}}}
}
}
iic.c
#include "reg52.h"
#include "intrins.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
void Delay_Ms(unsigned int ms) //@12.000MHz
{
unsigned char i, j;
while(ms--)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
//写入AT24C02
void Write_EEPROM(unsigned char add, unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
Delay_Ms(5);
}
//读取AT24C02
unsigned char ucRead_EEPROM(unsigned char add)
{
unsigned char dat;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
dat=IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return dat;
}
iic.h
#ifndef _IIC_H
#define _IIC_H
void Write_EEPROM(unsigned char add, unsigned char dat);
unsigned char ucRead_EEPROM(unsigned char add);
#endif