/**********************************************************************************
功能: 包含必要头文件,宏定义,位定义,以及变量和函数的声明
***********************************************************************************/
#include"STC15W4K.h"
#define uint unsigned int
#define uchar unsigned char
//on_off的状态值,表示电子密码的状态
#define FLAG_OFF 0 //关闭
#define FLAG_ON 1 //打开
#define FLAG_SETTING 2 //设置
//nset状态值,表示是否处于重置状态
#define FLAG_RESET_ON 1 //重置
#define FLAG_RESET_OFF 0 //非重置
//key的几个特殊值
#define KEY_BORDER 0x0a //键值边界,密码数字不超过9
#define KEY_ENSURE 0x0c //关闭
#define KEY_RESET 0x0d //重置
//按键的位定义
sbit L1 = P1^0;
sbit L2 = P1^1;
sbit L3 = P1^2;
sbit L4 = P1^3;
//led以及蜂鸣器定义,test用作测试
sbit LED_ON = P3^2;
sbit LED_OFF = P3^3;
sbit LED_SET = P3^4;
sbit test = P3^5;
sbit fmq = P3^6;
sbit led = P5^5;
//全局声明变量
extern uchar key_times;
extern uchar nset;
extern uchar on_off;
extern uchar i,j,temp;
extern uchar key;
extern uchar key_delay;
//函数声明
void delayms(uint xms);
void scankey();
void led_change(uchar option);
bit judge();
void init();
void scomm();
#include "function.h"
//保存当前密码,输入密码
uchar password[] = {0x01,0x01,0x01,0x01,0x01,0x01};
uchar input[] = {0xff,0xff,0xff,0xff,0xff,0xff};
/**********************************************************************************
功能: 延时,最小单位为ms(晶振为11.0592
计算方法:一个for循环 = 8个指令周期 = 8*12个机器周期 = 8*12*1/11.0592 = 0.0086ms
xms = 0.0086 * 110 = 0.946 ms
***********************************************************************************/
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
/**********************************************************************************
功能: 改变几个led的状态
***********************************************************************************/
void led_change(uchar option)
{
if(option == 0) //关闭状态
{
LED_ON = 1;
LED_OFF = 0;
LED_SET = 1;
}
else if(option == 1) //打开状态
{
LED_ON = 0;
LED_OFF = 1;
LED_SET = 1;
}
else if(option == 2) //设置状态
{
LED_ON = 1;
LED_OFF = 1;
LED_SET = 0;
}
}
/**********************************************************************************
功能: 扫描按键得出键值
方法: 先扫行,再扫列
***********************************************************************************/
void scankey()
{
P1 = 0xef;
//key = 0xff;
for(i=0;i<4;i++)
{
if(L1==0)
{
delayms(key_delay);
if(L1==0)
key = i*4+0;
if(key < KEY_BORDER && on_off != FLAG_ON)//开锁后按键不计数
key_times = key_times+1;
}
if(L2==0)
{
delayms(key_delay);
if(L2==0)
key = i*4+1;
if(key < KEY_BORDER && on_off != FLAG_ON)
key_times = key_times+1;
}
if(L3==0 && on_off != FLAG_ON)
{
delayms(key_delay);
if(L3==0)
key = i*4+2;
if(key < KEY_BORDER)
key_times = key_times+1;
}
if(L4==0 && on_off != FLAG_ON)
{
delayms(key_delay);
if(L4==0)
key = i*4+3;
if(key < KEY_BORDER)
key_times = key_times+1;
}
delayms(5); //准备下一次扫描的时间间隔
temp=P1;
temp=temp|0x0f;
temp=temp<<1;
temp=temp|0x0f;
P1=temp;
}
//扫描后判断键值
switch(key)
{
case KEY_ENSURE:
{
led_change(0); //改变灯的状态
key_times = 0;
on_off = FLAG_OFF;//定义宏
}
break;
case KEY_RESET:
{
if(on_off == FLAG_ON)
{
led_change(2);
key_times = 0;
on_off = FLAG_SETTING;
nset = FLAG_RESET_ON;
}
else if(on_off == FLAG_OFF)
{
fmq = 0;
delayms(10);
fmq = 1;
key = 0x00; //防止在此处循环
}
}
break;
default:break;
}
}
/**********************************************************************************
功能: 判断密码是否符合设置密码,以及重置新密码
***********************************************************************************/
bit judge()
{
if(nset == FLAG_RESET_OFF) //默认状态下
{
//test密码输入后可以进入
switch(key_times)
{
case 1:input[0] = key;break;
case 2:input[1] = key;break;
case 3:input[2] = key;break;
case 4:input[3] = key;break;
case 5:input[4] = key;break;
case 6:input[5] = key;break;
default:break;
}
}
if(nset == FLAG_RESET_ON) //重置状态下,替换旧密码同时打开锁
{
switch(key_times)
{
case 1:password[0] = key;input[0] = key;break;
case 2:password[1] = key;input[1] = key;break;
case 3:password[2] = key;input[2] = key;break;
case 4:password[3] = key;input[3] = key;break;
case 5:password[4] = key;input[4] = key;break;
case 6:password[5] = key;input[5] = key;break;
default:break;
}
}
if(key_times == 6)
{
if(nset == FLAG_RESET_ON )
nset = FLAG_RESET_OFF;
key_times = 0;
for(j=0;j<6;j++)
{
if(password[j] != input[j]) //报警
{
LED_ON = 1;
fmq = 0;
delayms(30);
LED_OFF = ~LED_OFF;
delayms(30);
LED_OFF = ~LED_OFF;
delayms(30);
LED_OFF = ~LED_OFF;
delayms(30);
LED_OFF = ~LED_OFF;
fmq = 1;
return 0;
}
}
on_off = FLAG_ON;
scomm();
return 1;
}
return 0;
}
/**********************************************************************************
功能: 初始化,包括对led,定时器,串口的初始化
***********************************************************************************/
void init()
{
led_change(0);
fmq = 0;
delayms(20);
fmq = 1;
P1M0 = 0;P1M1 = 0;
SCON = 0x40;
T2L = 0xe0; //定时器2作为波特率发生器
T2H = 0xfe;
AUXR = 0x14;
AUXR |= 0x01;
TI = 1;
}
/**********************************************************************************
功能: 发送单片机信息,一次七个字节,其中首字节为状态,其余六字节为当前密码
***********************************************************************************/
void scomm()
{
uchar i;
SBUF = on_off;
while(TI == 0);
TI = 0;
for(i=0;i<6;i++)
{
while(TI == 0);
{
TI = 0;
SBUF = password[i];
}
}
}
/********************************************************************************************
File name: 电子密码锁
Main fouction: 六位密码开解锁,包含重置功能,并将实时信息发送到上位机
Last modified Date: 2017-10-22
Created by: zzh
Steps for test 1 输入原始密码111111,看是否打开
2 再锁定,看是否关闭
3 此时输入错误密码,看是否报警
4 此时重设,因未解锁看是否报警
5 输入正确密码,此时重设,输入新密码,此时应保持解锁状态
6 关锁,输入新密码
7 重复2~6
*********************************************************************************************/
#include "function.h"
//变量初始化
uchar key_times = 0;
uchar nset = FLAG_RESET_OFF;
uchar on_off = FLAG_OFF;
uchar i,j,temp;
uchar key = 0xff;
uchar key_delay = 5;
void main()
{
uint t;
init();
while(1)
{
scankey();
if(judge() == 1)
{
led_change(1);
on_off = FLAG_ON;
}
if(key_times > 6)
key_times = 0;
}
}