题目要求
功能简述
“门禁系统” 主要有两种工作模式:
模式 1: 7: 00—22: 00 为自动门状态, 该状态下门的开和关是通过超声波测距来的测距来控制, 当测到的距离小于 30mc 时门就开, 门开 5 秒后自动闭。
模式 2: 22: 00—7: 00 密码门状态,门的开是通过输入正确的密码来起动, 门开启后 5 秒后自动关闭, 密码输入错误达到 3 次时则通过蜂鸣器来报警3 秒。
系统框图如下:
设计任务及要求
1.时间显示单元
通过 DS1302 获得时间, 时间初始值为 06: 59: 00, 通过 CT107D上的 8 位数码管显示出来,显示格式如下:
2.矩形键盘功能
4*4 键盘功能分布如下:
a. 在密码门状态下系统显示如下(等待密码输入状态):
此状态在可以输入 6 位密码,每输一位密码并用数码管从左到右依次显示出来,显示如下:
系统初始密码为**“654321”**,密码输入完成后按确认键确认密码输入
b. 重设密码状态(设置新密码):
在矩形键盘上有一个“设置” 键是用于修改密码的。当按下此键后就进入等待输入旧密码的显示界面,如下 :
当正确输入 6 位旧密码后按下确认完成旧密码输入,若密码正确就进入新密码输入界面,如下:
6位新密码输入完成后按确认键就完成了新密码的设置。
c. “复位”键功能:
“复位” 键用于将当前密码恢复为系统初始密码“654321”。
d. “退出”键功能:
用于在修改密码完成之前退出密码的修改回到密码门等待输入密码状态,显示如下:
3. 门的开和关控制
当超声波测距小于 30cm,或正确输入密码后继电器闭合表示已门打开 5 秒, 5 秒后继电器断开表示门已关闭。
4.蜂鸣器单元
在输入密码的状态下若连续 3 次输入错误的密码时,蜂鸣器报警 3 秒,在修改密码输入旧密码 3 次输错后蜂鸣器报警 3 秒并退出密码修改功能。
5.EEPROM 单元
用于存储当前密码或新密码,当确认输入密码后从 EEPROM中取出当前密码与已取入的密码进行对比。
程序代码
主函数
#include "stc15f2k60s2.h"
#include "ds1302.h"
#include "driver.h"
#include "sonic.h"
#include "iic.h"
bit confirm_key; //确认按键
extern bit auto_door_flag; //自动门标志
extern bit code_door_flag; //输入密码标志
uchar password;
uchar a=2,b=2,c=2;
uchar mode_display=1; //显示模式
uchar mode3_count; //模式3状态下对按键次数计数
uchar error_count; //输入密码错误计数
uchar errorin_count; //修改密码时,错误计数
uchar password_tab[6]={
6,5,4,3,2,1}; //密码
uchar key_val=0;
extern bit open_flag; //开门标志
extern bit error_flag; //报警标志
extern uchar set_display1[8]; //设置-输入旧密码页面
extern uchar set_display2[8]; //设置-输入新密码页面
extern uchar word_tab[8]; //输入密码界面
void Password_init(); //密码初始化
void input();
void delay_ms(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=850;j>0;j--);
}
void main()
{
All_init();
Timer0Init();
//Password_init(); //第一次下载程序用
DS1302_init();
while(1)
{
password_tab[0]=Read_2402(0x00);
password_tab[1]=Read_2402(0x01);
delay_ms(5);
password_tab[2]=Read_2402(0x02);
password_tab[3]=Read_2402(0x03);
delay_ms(5);
password_tab[4]=Read_2402(0x04);
password_tab[5]=Read_2402(0x05);
delay_ms(5);
input(); //和显示有关的输入
if(mode_display==1)
{
if((word_tab[2]==password_tab[0])&&(word_tab[3]==password_tab[1]))
{
if((word_tab[4]==password_tab[2]) &&(word_tab[5]==password_tab[3]))
{
if((word_tab[6]==password_tab[4]) &&(word_tab[7]==password_tab[5]))
{
if(confirm_key)
{
confirm_key=0;
open_flag=1; /*密码正确*/
error_count=0;
word_tab[2]=11; word_tab[3]=11;
word_tab[4]=11; word_tab[5]=11;
word_tab[6]=11; word_tab[7]=11;
a=2;
}
}
}
}
else //if((word_tab[2]!=password_tab[0])||(word_tab[3]!=password_tab[1]) ||(word_tab[4]!=password_tab[2]) ||(word_tab[5]!=password_tab[3]) ||(word_tab[6]!=password_tab[4])||(word_tab[7]!=password_tab[5]))
{
if(confirm_key)
{
confirm_key=0;
error_count++; /*密码错误*/
word_tab[2]=11; word_tab[3]=11;
word_tab[4]=11; word_tab[5]=11;
word_tab[6]=11; word_tab[7]=11;
a=2;
}
}
}
if(mode_display==2) /*输入旧密码*/
{
if((set_display1[2]==password_tab[0])&&(set_display1[3]==password_tab[1]))
{
if((set_display1[4]==password_tab[2]) &&(set_display1[5]==password_tab[3]))
{
if((set_display1[6]==password_tab[4]) &&(set_display1[7]==password_tab[5]))
{
if(confirm_key)
{
confirm_key=0;
mode_display=3; /*进入设置新密码页面*/
errorin_count=0;
set_display2[2]=11; set_display2[3]=11;
set_display2[4]=11; set_display2[5]=11;
set_display2[6]=11; set_display2[7]=11;
b=2;
}
}
}
}
else //if((set_display1[2]!=password_tab[0])||(set_display1[3]!=password_tab[1]) ||(set_display1[4]!=password_tab[2]) ||(set_display1[5]!=password_tab[3]) ||(set_display1[6]!=password_tab[4])||(set_display1[7]!=password_tab[5]))
{
if(confirm_key)
{
confirm_key=0;
errorin_count++; /*密码错误*/
set_display1[2]=11; set_display1[3]=11;
set_display1[4]=11; set_display1[5]=11;
set_display1[6]=11; set_display1[7]=11;
b=2;
}
}
}
if(mode_display==3)
{
password_tab[0]=set_display2[2];
password_tab[1]=set_display2[3];
password_tab[2]=set_display2[4];
password_tab[3]=set_display2[5];
password_tab[4]=set_display2[6];
password_tab[5]=set_display2[7];
}
if(error_count==3||errorin_count==3)
{
error_count=0;
errorin_count=0;
error_flag=1;
}
DIS_time();
DIS_sonic();
key_val=key_init();
switch(key_val)
{
case 5:
password=8;
break;
case 6:
password=4;
break;
case 7:
password=0;
break;
case 9:
password=9;
break;
case 10:
password=5;
break;
case 11:
password=1;
break;
case 14:
password=6;
break;
case 15:
password=2;
break;
case 18:
password=7;
break;
case 19:
password=3;
break;
case 12: //确认按键
confirm_key=1;
if(mode_display==3)
{
mode_display=1;
Write_2402(0x00,password_tab[0]);
delay_ms(5);
Write_2402(0x01,password_tab[1]);
delay_ms(5);
Write_2402(0x02,password_tab[2]);
delay_ms(5);
Write_2402(0x03,password_tab[3]);
delay_ms(5);
Write_2402(0x04,password_tab[4]);
delay_ms(5);
Write_2402(0x05,password_tab[5]);
delay_ms(5);
}
break;
case 13: //设置按键
mode_display=2;
set_display1[2]=11; set_display1[3]=11;
set_display1[4]=11; set_display1[5]=11;
set_display1[6]=11; set_display1[7]=11;
b=2;
break;
case 4: //进入密码输入状态
mode_display=1;
word_tab[2]=11; word_tab[3]=11;
word_tab[4]=11; word_tab[5]=11;
word_tab[6]=11; word_tab[7]=11;
a=2; b=2; c=2;
break;
case 17: //复位
password_tab[0]=6;
password_tab[1]=5;
password_tab[2]=4;
password_tab[3]=3;
password_tab[4]=2;
password_tab[5]=1;
Write_2402(0x00,password_tab[0]);
delay_ms(5);
Write_2402(0x01,password_tab[1]);
delay_ms(5);
Write_2402(0x02,password_tab[2]);
delay_ms(5);
Write_2402(0x03,password_tab[3]);
delay_ms(5);
Write_2402(0x04,password_tab[4]);
delay_ms(5);
Write_2402(0x05,password_tab[5]);
delay_ms(5);
error_count=0;
errorin_count=0;
break;
case 16: //退出
if(mode_display==3)
{
mode_display=1;
word_tab[2]=11; word_tab[3]=11;
word_tab[4]=11; word_tab[5]=11;
word_tab[6]=11; word_tab[7]=11;
password_tab[0]=set_display1[2]; //密码还是原来密码
password_tab[1]=set_display1[3];
password_tab[2]=set_display1[4];
password_tab[3]=set_display1[5];
password_tab[4]=set_display1[6];
password_tab[5]=set_display1[7];
}
break;
}
}
}
void input()
{
if(key_val&&(key_val!=4)&&(key_val!=8)&&(key_val!=12)&&(key_val!=16)&&(key_val!=13)&&(key_val!=17))
{
if(mode_display==1)
{
word_tab[a]=password;
a++;
if(a==8)
a=2;
}
if(mode_display==2)
{
set_display1[b]=password;
b++;
if(b==8)
b=2;
}
if(mode_display==3)
{
set_display2[c]=password;
c++;
if(c==8)
c=2;
}
}
}
void Password_init()
{
Write_2402(0x00,6);
delay_ms(5);
Write_2402(0x01,5);
delay_ms(5);
Write_2402(0x02,4);
delay_ms(5);
Write_2402(0x03,3);
delay_ms(5);
Write_2402(0x04,2);
delay_ms(5);
Write_2402(0x05,1);
delay_ms(5);
}
驱动
#include "driver.h"
#include "ds1302.h"
#include "sonic.h"
uchar code SMG_TAB[]={
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40,0x00};
uchar SMG_WEI[]={
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar time_display[8];
uchar distance_display[8];
uchar set_display1[8]={
11,10,11,11,11,11,11,11};
uchar set_display2[8]={
10,11,11,11,11,11,11,11};
uchar word_tab[8]={
10,10,11,11,11,11,11,11};
extern uchar mode_display;
bit open_flag;
bit error_flag;
bit flag200ms;
bit auto_door_flag;
bit code_door_flag;
uint distance;
void All_init()
{
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=(P2&0X1F)|0X80;
P0=0XFF;
P2=P2&0X1F;
}
//void ledlight(unsigned char dat)
//{
// P2=(P2&0X1F)|0X80;
// P0=dat;
// P2=P2&0X1F;
//}
void DIS_time() //时间初始化
{
Read_time();
time_display[0]=SMG_TAB[TIME[2]/16]; time_display[1]=SMG_TAB[TIME[2]%16];
time_display[2]=0X40;
time_display[3]=SMG_TAB[TIME[1]/16]; time_display[4]=SMG_TAB[TIME[1]%16];
time_display[5]=0X40;
time_display[6]=SMG_TAB[TIME[0]/16]; time_display[7]=SMG_TAB[TIME[0]%16];
if((TIME[2]>=7)&&((TIME[2]<=22))) //自动门
{
auto_door_flag=1;
code_door_flag=0;
//mode_display=0;
}
else //密码门
{
auto_door_flag=0;
code_door_flag=1;
//mode_display=1;
}
}
void DIS_sonic() //超声波测距初始化
{
if(flag200ms)
{
distance=Recive();
flag200ms=0;
}/*
distance_display[0]=SMG_TAB[distance/1000]; distance_display[1]=SMG_TAB[distance/100%10];
distance_display[2]=SMG_TAB[distance/10%10];
distance_display[3]=SMG_TAB[distance%10]; distance_display[4]=0x00;
distance_display[5]=0X00;
distance_display[6]=0x00; distance_display[7]=0x00; */
if((distance<30)&&(auto_door_flag==1)) //距离小于30厘米
{
open_flag=1;
}
}
void Timer0Init() //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
}
void timer0() interrupt 1
{
uchar i;
uint sonicflag_count;
uint open_count; //关门倒计时
uint close_count;
uchar SMG_count;
SMG_count++;
sonicflag_count++;
if(sonicflag_count==200)
{
sonicflag_count=0;
flag200ms=1;
}
if(open_flag)
{
P2=(P2&0X1F)|0XA0;
P04=1; P06=0;
P2=P2&0X1F;
open_count++;
if(open_count==5000)
{
open_count=0;
open_flag=0;
}
}
else
{
P2=(P2&0X1F)|0XA0;
P04=0; P06=0;
P2=P2&0X1F;
}
if(error_flag)
{
P2=(P2&0X1F)|0XA0;
P06=1; //蜂鸣器响
P2=P2&0X1F;
close_count++;
if(close_count==3000)
{
close_count=0;
error_flag=0;
if(mode_display==2)
mode_display=1;
}
}
else
{
P2=(P2&0X1F)|0XA0;
P06=0; //关闭蜂鸣器
P2=P2&0X1F;
}
if(SMG_count==3)
{
SMG_count=0;
P2=(P2&0X1F)|0XC0;
P0=0X00;
P2=(P2&0X1F)|0XC0;
P0=SMG_WEI[i];
P2=P2&0X1F;
if(mode_display==0)
{
P2=(P2&0X1F)|0XE0;
P0=~time_display[i];
P2=P2&0X1F;
}
if(mode_display==1)
{
P2=(P2&0X1F)|0XE0;
P0=~SMG_TAB[word_tab[i]];
P2=P2&0X1F;
}
if(mode_display==2)
{
P2=(P2&0X1F)|0XE0;
P0=~SMG_TAB[set_display1[i]];
P2=P2&0X1F;
}
if(mode_display==3)
{
P2=(P2&0X1F)|0XE0;
P0=~SMG_TAB[set_display2[i]];
P2=P2&0X1F;
}
i++;
if(i==8)
i=0;
}
}
unsigned char key_init()
{
static uchar key_state=0;
uchar key1,key2;
uchar key_press, key_value=0;
P30=0; P31=0; P32=0; P33=0; P34=1; P35=1; P42=1; P44=1;
if(P34==0) key1=0xe0;
if(P35==0) key1=0xd0;
if(P42==0) key1=0xb0;
if(P44==0) key1=0x70;
if((P34==1)&&(P35==1)&&(P42==1)&&(P44==1))
key1=0xf0;
P30=1; P31=1; P32=1; P33=1; P34=0; P35=0; P42=0; P44=0;
if(P30==0) key2=0x0e;
if(P31==0) key2=0x0d;
if(P32==0) key2=0x0b;
if(P33==0) key2=0x07;
if((P30==1)&&(P31==1)&&(P32==1)&&(P33==1))
key2=0x0f;
key_press=key1|key2;
switch(key_state)
{
case key_state0:
if(key_press!=0xff)
key_state=key_state1;
break;
case key_state1:
if(key_press!=0xff)
{
if(key_press==0x7e) key_value=7;
if(key_press==0x7d) key_value=6;
if(key_press==0x7b) key_value=5;
if(key_press==0x77) key_value=4;
if(key_press==0xbe) key_value=11;
if(key_press==0xbd) key_value=10;
if(key_press==0xbb) key_value=9;
if(key_press==0xb7) key_value=8;
if(key_press==0xde) key_value=15;
if(key_press==0xdd) key_value=14;
if(key_press==0xdb) key_value=13;
if(key_press==0xd7) key_value=12;
if(key_press==0xee) key_value=19;
if(key_press==0xed) key_value=18;
if(key_press==0xeb) key_value=17;
if(key_press==0xe7) key_value=16;
key_state=key_state2;
}
else
key_state=key_state0;
break;
case key_state2:
if(key_press==0xff)
key_state=key_state0;
break;
}
return key_value;
}
超声波模块
#include "sonic.h"
#include "intrins.h"
void Delayus();
unsigned int Recive()
{
long UltraTemp=0;
long i,UltraDistance=0;
Echo=1;
for (i=0;i<10;i++)
{
Trig=~Trig;
Delayus();
}
while(Echo)
{
UltraTemp++;
if(UltraTemp>=10000)
break;
}
UltraDistance=UltraTemp/7;
return UltraDistance;
}
void Delayus() //延时13us
{
unsigned char i;
_nop_();
_nop_();
i = 33;
while (--i);
}
DS1302时钟
#include "ds1302.h"
/********************************************************************/
/*单字节写入一字节数据*/
unsigned char Write_addr[]={
0x80,0x82,0x84}; //写地址 秒、分、时
unsigned char Read_addr[]={
0x81,0x83,0x85};
unsigned char TIME[3]={
0X00,0X59,0X06};
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
for (i=0;i<8;i++)
{
if (dat & 0x01) // 等价于if((addr & 0x01) ==1)
{
SDA_SET; //#define SDA_SET SDA=1 /*电平置高*/
}
else
{
SDA_CLR; //#define SDA_CLR SDA=0 /*电平置低*/
}
SCK_SET;
SCK_CLR;
dat = dat >> 1;
}
}
/********************************************************************/
/*单字节读出一字节数据*/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i<8;i++)
{
dat = dat >> 1;
if (SDA_R) //等价于if(SDA_R==1) #define SDA_R SDA /*电平读取*/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
return dat;
}
/********************************************************************/
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{
RST_CLR; /*RST脚置低,实现DS1302的初始化*/
SCK_CLR; /*SCK脚置低,实现DS1302的初始化*/
RST_SET; /*启动DS1302总线,RST=1电平置高 */
addr = addr & 0xFE;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/
Write_Ds1302_Byte(dat); /*写入数据:dat*/
RST_CLR; /*停止DS1302总线*/
}
/********************************************************************/
/*从DS1302单字节读出一字节数据*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr)
{
unsigned char temp;
RST_CLR; /*RST脚置低,实现DS1302的初始化*/
SCK_CLR; /*SCK脚置低,实现DS1302的初始化*/
RST_SET; /*启动DS1302总线,RST=1电平置高 */
addr = addr | 0x01;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/
RST_CLR; /*停止DS1302总线*/
SDA_CLR; //数据线电平置低
return temp;
}
void DS1302_init()
{
unsigned char i;
Ds1302_Single_Byte_Write(0x8e,0x00); //允许写
for(i=0;i<3;i++)
{
Ds1302_Single_Byte_Write(Write_addr[i],TIME[i]);
}
Ds1302_Single_Byte_Write(0x8e,0x80); //禁止写
}
void Read_time()
{
unsigned char i;
for(i=0;i<3;i++)
{
TIME[i]=Ds1302_Single_Byte_Read(Read_addr[i]);
}
}
EEPROM模块
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(12MHz)
日 期: 2011-8-9
*/
#include "iic.h"
void iic_delay(unsigned char i)
{
do
{
_nop_();
}while(i--);
}
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
iic_delay(5);
SDA = 0;
iic_delay(5);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
iic_delay(5);
SDA = 1;
}
//应答位控制
void IIC_Ack(unsigned char ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
iic_delay(5);
SCL = 1;
iic_delay(5);
SCL = 0;
SDA = 1;
iic_delay(5);
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
iic_delay(5);
SCL = 1;
iic_delay(5);
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
SCL = 0;
return 1;
}
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
iic_delay(5);
SCL = 1;
byt <<= 1;
iic_delay(5);
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
iic_delay(5);
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
iic_delay(5);
}
return da;
}
void Write_2402(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char Read_2402(unsigned char dat)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
return temp;
}
以上就是全部代码,欢迎交流,共同学习~