1、题目
(1)硬件框图
(2) 功能描述
1、基本功能
通过单片机控制外围器件完成智能门锁的设计。其中,继电器显示门状态,LED指示门开启的状态和按键输入模式,数码管显示基本信息,E2PROM可以对设置的新密码进行保存。
2、初始化状态说明
- 指示灯全部熄灭
- 数码管全部熄灭
- 继电器关闭
3、按键功能
- 按S16键进入密码输入模式,密码输入时,每按一个键,对应的数字在数码管的最右位,同时原来显示的数字向左移动一位。
- 密码输入正确,继电器打开,数码管最左侧显示O,最右侧四位显示open,其余位关闭。门开启5秒后,无按键操作,进入关门状态,继电器、数码管和LED全部关闭。
- 密码输入错误,L1指示灯点亮5秒,5秒后,指示灯L1熄灭,设备进入初始状态,等待新的密码输入操作。
- 密码输入正确后,在门开启的状态下,按S12按键可以修改密码,修改时数码管最左边一位显示C,输入6位新密码后再按S12按键,密码修改完成。退出密码修改界面,门开启5s之内没有按键操作,门、LED和数码管全部关闭,进入初始状态。
- 密码输入未完成且输入错误时,可以使用清除按键,清除已经输入的密码。
- 键盘功能定义
4、存储功能
- 密码存储在EEPROM存储器中,修改后自动保存。
5、 LED指示功能
- 指示灯L1: 密码输入错误时,L1点亮,5秒后熄灭。
- 指示灯L7: 密码输入状态下亮,其他状态熄灭。
- 指示灯L8: 密码修改状态下亮,其他状态熄灭。
(3)设计说明
- 关闭蜂鸣器等与本试题程序设计无关的外设资源;
- 设备首次上电时,初始密码默认未6个8。
2、试题分析
在这里先分析一下这个题目:
矩阵按键:
//定义r为行,c为列,如果r1=0,c1=0,按键则为第一行第一列,其余同理;
sbit r1=P3^0;
sbit r2=P3^1;
sbit r3=P3^2;
sbit r4=P3^3;
sbit c1=P4^4;
sbit c2=P4^2;
sbit c3=P3^5;
sbit c4=P3^4;
注意按键端口表示方法,可参考:
https://blog.csdn.net/fanjufei123456/article/details/104263738
按键函数定义(flag和flag1分别为输入、修改模式下的标志位):
void keyscan(){
r1=0;r2=1;r3=1;r4=1;
c1=1;c2=1;c3=1;c4=1;
if(!c1)
{
delayms(5);
{
num=0;
flag=1;
flag1=1;
}
while(!c1);
}
else if(!c2)
{
delayms(5);
{
num=1;
flag=1;
flag1=1;
}
while(!c2);
}
else if(!c3)
{
delayms(5);
{
num=2;
flag=1;
flag1=1;
}
while(!c3);
}
else if(!c4)
{
delayms(5);
{
num=3;
flag=1;
flag1=1;
}
while(!c4);
}
r1=1;r2=0;r3=1;r4=1;
c1=1;c2=1;c3=1;c4=1;
if(!c1)
{
delayms(5);
{
num=4;
flag=1;
flag1=1;
}
while(!c1);
}
else if(!c2)
{
delayms(5);
{
num=5;
flag=1;
flag1=1;
}
while(!c2);
}
else if(!c3)
{
delayms(5);
{
num=6;
flag=1;
flag1=1;
}
while(!c3);
}
else if(!c4)
{
delayms(5);
{
num=7;
flag=1;
flag1=1;
}
while(!c4);
}
r1=1;r2=1;r3=0;r4=1;
c1=1;c2=1;c3=1;c4=1;
if(!c1)
{
delayms(5);
{
num=8;
flag=1;
flag1=1;
}
while(!c1);
}
else if(!c2)
{
delayms(5);
{
num=9;
flag=1;
flag1=1;
}
while(!c2);
}
r1=1;r2=1;r3=1;r4=0;
c1=1;c2=1;c3=1;c4=1;
if(!c2)
{
delayms(5);
{
clean=1;
}
while(!c2);
}
else if(!c3)
{
delayms(5);
{
if(xiugai==0)
{
xiugai=1;
}
else if(xiugai==1)
{
xiugai=0;
}
}
while(!c3);
}
else if(!c4)
{
delayms(5);
{
moshi=1;
}
while(!c4);
}
}
if(moshi==1)
{
if(clean==1)
{
clean=0;
f1=10;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
}
f1=10;
if((f8==11)&&(flag==1))
{
flag=0;
f8=num;
}
else if((f7==11)&&(flag==1))
{
flag=0;
f7=num;
}
else if((f6==11)&&(flag==1))
{
flag=0;
f6=num;
}
else if((f5==11)&&(flag==1))
{
flag=0;
f5=num;
}
else if((f4==11)&&(flag==1))
{
flag=0;
f4=num;
}
else if((f3==11)&&(flag==1))
{
flag=0;
f3=num;
}
}
if((xiugai==1)&&(flag2==1))
{
if(xiugai_show==0)
{
xiugai_show=1;
EA=0;ET0=0;
f1=12;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
}
P2=0X80;P0=0X7F;
if((f8==11)&&(flag1==1))
{
flag1=0;
f8=num;
m8=num;
EEPROM_Write(m8,0x00);
}
else if((f7==11)&&(flag1==1))
{
flag1=0;
f7=num;
m7=num;
EEPROM_Write(m7,0x01);
}
else if((f6==11)&&(flag1==1))
{
flag1=0;
f6=num;
m6=num;
EEPROM_Write(m6,0x02);
}
else if((f5==11)&&(flag1==1))
{
count2=0;
flag1=0;
f5=num;
m5=num;
EEPROM_Write(m5,0x03);
}
else if((f4==11)&&(flag1==1))
{
flag1=0;
f4=num;
m4=num;
EEPROM_Write(m4,0x04);
}
else if((f3==11)&&(flag1==1))
{
flag1=0;
f3=num;
m3=num;
EEPROM_Write(m3,0x05);
}
}
初始化继电器蜂鸣器:
void init_buzzer_relay(){
P2=0XA0; //P27=1,P26=0,P25=1,其余为0,此时38译码器中的Y5=0,进而的得到Y5C=1
P0=0X00; //P06=0关闭蜂鸣器,P04=0关闭集电器
}
3、驱动代码
iic.c
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(12MHz)
日 期: 2011-8-9
*/
#include "iic.h"
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
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;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
//EEPROM读
unsigned char EEPROM_Read(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
//EEPROM写
void EEPROM_Write(unsigned char dat,unsigned char add)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
iic.h
#ifndef _IIC_H
#define _IIC_H
#include "stc15f2k60s2.h"
#include "intrins.h"
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();}
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
//函数声明
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Ack(unsigned char ackbit);
void IIC_SendByte(unsigned char byt);
bit IIC_WaitAck(void);
unsigned char IIC_RecByte(void);
unsigned char EEPROM_Read(unsigned char add);
void EEPROM_Write(unsigned char dat,unsigned char add);
#endif