1. 基本要求
1.1 使用国信长天单片机竞赛实训平台,完成“智能门锁”功能的程序设计与调试
1.2 设计与调试过程中,可参考组委会提供的“资源数据包”。
1.3 Keil工程文件以准考证号命名,完成设计后,提交完整、可编译的Keil工程文件到服务器。
2. 硬件框图
3. 功能描述
3.1 基本功能
通过单片机控制外围器件完成智能门锁的设计。其中,继电器显示门状态,LED指示门开启的状态和按键输入模式,数码管显示基本信息,E2PROM可以对设置的新密码进行保存。
3.2 初始状态说明
指示灯全部熄灭
数码管全部熄灭
继电器关闭
3.3 按键功能
主函数
#include "stc15f2k60s2.h"
#include "iic.h"
#include "key.h"
#include "led.h"
typedef unsigned char uchar;
typedef unsigned int uint;
uchar code SMG_duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40,0x00,0x39};
uchar SMG_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar pass_word[]={0x08,0x08,0x08,0x08,0x08,0x08}; //密码
uchar tab[]={10,11,11,11,11,11,11,11}; //密码输入显示缓存区
uchar tab_xiugai[]={12,11,11,11,11,11,11,11}; // 密码修改显示缓存区
uchar open_display[8]; //门打开显示
uchar init_display[8]; //初始化显示
uchar e2_flag;
uchar open_flag; //开门标志
uchar error_flag; //密码错误标志
uchar led_flag;
uchar mode_display=0; //显示模式
uchar password; //按键输入密码
static uchar a,b;
uchar count; //按下次数
uchar gai_count; //修改密码时,对按键计数
uchar ffff;
uchar key_init();
void Timer0Init(); //1毫秒@11.0592MHz
void password_init();
void delay_ms(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=850;j>0;j--);
}
void main()
{
uchar key_val;
All_init();
Timer0Init();
password_init();
while(1)
{
init_display[0]=0x00; init_display[1]=0x00;
init_display[2]=0x00; init_display[3]=0x00;
init_display[4]=0x00; init_display[5]=0x00;
init_display[6]=0x00; init_display[7]=0x00;
open_display[0]=0x3f; open_display[1]=0x00;
open_display[2]=0x00; open_display[3]=0x00;
open_display[4]=0x3f; open_display[5]=0x73;
open_display[6]=0x79; open_display[7]=0x37;
if(mode_display==1)
{
if((key_val)&&(key_val!=13)&&(key_val!=17)&&(key_val!=4)&&(key_val!=8)&&(key_val!=12)&&(key_val!=16))
{
for(a=2;a<=7;a++)
{
tab[a]=tab[a+1];
}
tab[7]=password;
count++;
ledlight(0xbf);
}
}
if(count==6) //密码输入完成
{
count=0; /*密码正确*/
if((tab[2]==pass_word[0])&&(tab[3]==pass_word[1])&&(tab[4]==pass_word[2])&&(tab[5]==pass_word[3])&&(tab[6]==pass_word[4])&&(tab[7]==pass_word[5]))
{
if(mode_display==1)
{
open_flag=1;
mode_display=2;
}
}
/*密码错误*/
if((tab[2]!=pass_word[0])||(tab[3]!=pass_word[1])||(tab[4]!=pass_word[2])||(tab[5]!=pass_word[3])||(tab[6]!=pass_word[4])||(tab[7]!=pass_word[5]))
{
error_flag=1;
led_flag=1;
}
}
key_val=key_init();
switch(key_val)
{
case 7:
password=0;
break;
case 11:
password=1;
break;
case 15:
password=2;
break;
case 19:
password=3;
break;
case 6:
password=4;
break;
case 10:
password=5;
break;
case 14:
password=6;
break;
case 18:
password=7;
break;
case 5:
password=8;
break;
case 9:
password=9;
break;
case 16:
if(mode_display==0)
mode_display=1;
tab[0]=10; tab[1]=11;
tab[2]=11; tab[3]=11;
tab[4]=11; tab[5]=11;
tab[6]=11; tab[7]=11;
count=0;
break;
case 8: //清除
tab[0]=10; tab[1]=11;
tab[2]=11; tab[3]=11;
tab[4]=11; tab[5]=11;
tab[6]=11; tab[7]=11;
tab_xiugai[0]=12; tab_xiugai[1]=11;
tab_xiugai[2]=11; tab_xiugai[3]=11;
tab_xiugai[4]=11; tab_xiugai[5]=11;
tab_xiugai[6]=11; tab_xiugai[7]=11;
count=0;
gai_count=0;
break;
case 12: //修改
if(mode_display==2)
{
mode_display=3;
}
if(mode_display==3)
{
ffff++;
if(ffff==2) //回到初始状态
{
ffff=0;
mode_display=0;
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=P2&0X1F;
ledlight(0xff);
count=0;
if(gai_count==6)
{
gai_count=0;
pass_word[0]=tab_xiugai[2];
pass_word[1]=tab_xiugai[3];
pass_word[2]=tab_xiugai[4];
pass_word[3]=tab_xiugai[5];
pass_word[4]=tab_xiugai[6];
pass_word[5]=tab_xiugai[7];
}
write_2402(0x00,pass_word[0]);
delay_ms(10); //每次写完要延时10ms
write_2402(0x01,pass_word[1]);
delay_ms(10);
write_2402(0x02,pass_word[2]);
delay_ms(10);
write_2402(0x03,pass_word[3]);
delay_ms(10);
write_2402(0x04,pass_word[4]);
delay_ms(10);
write_2402(0x05,pass_word[5]);
delay_ms(10);
}
}
break;
}
if(mode_display==3)
{
if((key_val)&&(key_val!=13)&&(key_val!=17)&&(key_val!=4)&&(key_val!=8)&&(key_val!=12)&&(key_val!=16))
{
for(b=2;b<=7;b++)
{
tab_xiugai[b]=tab_xiugai[b+1];
}
tab_xiugai[7]=password;
gai_count++;
ledlight(0x7f);
}
}
}
}
void password_init()
{
e2_flag=read_2402(0x09);
if(e2_flag==10) //确保第一次程序下载到板子上后,初始密码为888 888
{
pass_word[0]=read_2402(0x00);
delay_ms(10); //防止连续读取数据时出错
pass_word[1]=read_2402(0x01);
delay_ms(10);
pass_word[2]=read_2402(0x02);
delay_ms(10);
pass_word[3]=read_2402(0x03);
delay_ms(10);
pass_word[4]=read_2402(0x04);
delay_ms(10);
pass_word[5]=read_2402(0x05);
delay_ms(10);
}
else
{
pass_word[0]=8; pass_word[1]=8;
pass_word[2]=8; pass_word[3]=8;
pass_word[4]=8; pass_word[5]=8;
write_2402(0x09,10);
delay_ms(5);
}
}
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;
static uchar SMG_count;
static uint door_count,led_count;
SMG_count++;
if(SMG_count==3)
{
SMG_count=0;
P2=0XC0; P0=0X00;
P2=0XC0;
P0=SMG_wei[i];
if(mode_display==0) //初始化显示
{
P2=0Xe0;
P0=~init_display[i];
}
if(mode_display==1) //密码输入显示
{
P2=0Xe0;
P0=~SMG_duan[tab[i]];
}
if(mode_display==2) //门打开显示
{
P2=0Xe0;
P0=~open_display[i];
}
if(mode_display==3) //修改页面
{
P2=0Xe0;
P0=~SMG_duan[tab_xiugai[i]];
}
i++;
if(i==8)
i=0;
}
if(mode_display!=3)
{
if(mode_display==2)
{
if(open_flag) //密码正确,门打开
{
P2=(P2&0X1F)|0XA0;
P0=0X10;
P2=P2&0X1F;
ledlight(0xff);
door_count++;
if(door_count>5000)
{
door_count=0;
open_flag=0;
}
}
if(open_flag==0)
{
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=P2&0X1F;
mode_display=0;
tab[0]=10; tab[1]=11;
tab[2]=11; tab[3]=11;
tab[4]=11; tab[5]=11;
tab[6]=11; tab[7]=11;
}
}
if(error_flag) //密码错误
{
led_count++;
if(led_flag)
{
ledlight(0xfe); //L1点亮
}
if(led_flag==0)
{
ledlight(0xff); //亮5秒熄灭
mode_display=0;
tab[0]=10; tab[1]=11;
tab[2]=11; tab[3]=11;
tab[4]=11; tab[5]=11;
tab[6]=11; tab[7]=11;
error_flag=0;
}
if(led_count>5000)
{
led_count=0;
led_flag=0;
}
}
}
}
按键模块
#include "key.h"
unsigned char key_init()
{
static unsigned char key_state=0;
unsigned char key1,key2;
unsigned char key_value=0;
unsigned char key_press;
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 0:
if(key_press!=0xff)
key_state=1;
break;
case 1:
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=2;
}
else
key_state=0;
break;
case 2:
if(key_press==0xff)
key_state=0;
break;
}
return key_value;
}
LED驱动模块
#include "led.h"
void All_init()
{
P2=(P2&0X1F)|0X80;
P0=0XFF;
P2=P2&0X1F;
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=P2&0X1F;
}
void ledlight(unsigned char led)
{
P0=0XFF;
P2=(P2&0X1F)|0X80;
P0=led;
P2=P2&0X1F;
}
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 add,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char read_2402(unsigned char dat)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0); //写入 为0
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1); //读出为1
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
return temp;
}
以上就是代码全部内容,手敲代码不易,留个关注和赞再走吧~