/**
* 项目名:门禁系统
* 文件名:main.h
*/
#ifndef _MAIN_H
#define _MAIN_H
sbit RELAY_PIN = P0^4;
sbit BUZZER_PIN = P0^6;
void sys_init();
void samplingDS1302();
void samplingUlt();
void initDispMode1();
void initDispMode2();
void initDispMode3();
void refreshTimeDisplay();
#endif
/**
* 项目名:门禁系统
*
* 7:00-22:00工作在模式0(自动门状态)
* 22:00-7:00工作在模式1(密码门状态)
* 难点:继电器在接通5s后断开
* 蜂鸣器报警3s
* 文件名:main.c
*/
#include <stc15f2k60s2.h>
#include <string.h>
#include "stdint.h"
#include "timer.h"
#include "digitalTube.h"
#include "matrixKey.h"
#include "DS1302.h"
#include "EEPROM.h"
#include "ultrasonic.h"
#include "electromagneticDev.h"
#include "main.h"
volatile bit flag50ms = 0, flag200ms = 0, flag500ms = 0; //任务标志
bit workingMode = 1; //工作模式,初始化时间为06:59:00
uint8_t dispMode = 0; //在密码门状态下的显示模式{0, 1, 2, 3}
uint8_t code initPassword[7] = "654321"; //初始密码
uint8_t password[7]; //当前密码
bit isOpen = 0; //继电器是否打开
volatile bit enBuzzer = 0;
sTime_t time;
static uint8_t wrongTimes = 0, passwdTmpIndex = 0; //!!!here
void main() {
uint8_t cnt500ms = 0;
sys_init();
while (1) {
if (flag50ms) {
flag50ms = 0;
keyDriver();
}
if (flag200ms) {
flag200ms = 0;
samplingDS1302();
if (workingMode == 0) { //如果工作于自动门状态
samplingUlt(); //采样超声波模块
}
}
if (flag500ms) {
flag500ms = 0;
if (workingMode == 1) { //如果工作于密码门状态
if (isOpen) { //如果检测到门是打开的
if (cnt500ms == 10) {
cnt500ms = 0;
relay_off();
isOpen = 0;
} else {
cnt500ms++;
}
}
}
}
}
}
void sys_init() {
tmr0_init(2);
tmr1_specialInit();
stc15_tmr2_init(1); //!!!
DS1302_init();
EEPROM_read(password, 0, sizeof (password)); //addr=0
if (strncmp(password, "000000", 6) == 0) { //如果没有被初始化过
strncpy(password, initPassword, 6);
EEPROM_write(initPassword, 0, sizeof (initPassword));
}
}
void samplingDS1302() { //采样实时时间用于控制工作模式
static uint8_t preSec;
DS1302_getRealTime(&time);
if (time.hour == 0x07 && time.minute == 0x00) { //如果到了7:00
workingMode = 0; //工作于自动门状态
dispMode = 0; //!!!显示模式归0
wrongTimes = 0; //!!!
passwdTmpIndex = 0; //!!!
} else if (time.hour == 0x22 && time.minute == 0x00) { //如果到了22:00
workingMode = 1; //工作于密码门状态
}
if (dispMode == 0) { //如果是显示模式0,则更新显示
if (time.sec != preSec) { //秒有变化则更新显示
preSec = time.sec;
refreshTimeDisplay();
}
}
}
void samplingUlt() { //工作于自动门状态,由超声波测得的距离控制继电器的开闭
static uint8_t ultCnt200ms = 0;
uint8_t dis;
dis = ult_getDis();
if (isOpen == 0) { //如果之前是关闭的状态
if (dis < 30) { //如果测量到的距离小于30cm
relay_on();
isOpen = 1;
}
} else if (isOpen == 1) {
if (dis >= 30) {
if (ultCnt200ms == 24) {
ultCnt200ms = 0;
relay_off();
isOpen = 0;
} else {
ultCnt200ms++;
}
} else {
ultCnt200ms = 0;
}
}
}
void keyAction(uint8_t keyCode) {
static uint8_t passwdTmp[7];
if (workingMode == 0) //如果工作于自动门状态,则对按键无响应
return;
if (keyCode == 'q') { //如果按的是确认键
if (passwdTmpIndex == 6) { //如果输入了6位密码
passwdTmpIndex = 0; //!!!复位写索引
if (dispMode == 1) { //如果当前是密码验证界面
if (strncmp(passwdTmp, password, 6) == 0) { //如果密码匹配成功
dispMode = 0; //回到时间显示界面
refreshTimeDisplay(); //重新显示时间
relay_on(); //打开继电器
isOpen = 1; //!!!!!!
wrongTimes = 0; //!!!连续错误次数归0
} else { //密码匹配失败
if (wrongTimes >= 2) { //如果连续错误次数达到3次
enBuzzer = 1;
} else {
wrongTimes++;
}
initDispMode1(); //清空输入的密码
}
} else if (dispMode == 2) { //如果当前是旧密码验证界面
if (strncmp(passwdTmp, password, 6) == 0) { //如果密码匹配成功
//passwdTmpIndex = 0; //复位
dispMode = 3; //进入新密码输入界面
initDispMode3();
wrongTimes = 0; //!!!连续错误次数归0
} else { //密码匹配失败
if (wrongTimes == 2) { //如果错误次数达到3次
enBuzzer = 1;
dispMode = 0; //!!!回到时间显示界面
refreshTimeDisplay();
wrongTimes = 0;
} else {
wrongTimes++;
}
initDispMode2(); //清空输入的密码
}
} else if (dispMode == 3) { //如果当前是新密码输入界面
strncpy(password, passwdTmp, sizeof (passwdTmp)); //更新新密码
EEPROM_write(passwdTmp, 0, sizeof (passwdTmp)); //将新密码写入EEPROM
dispMode = 0; //回到实时时间显示界面
refreshTimeDisplay();
}
}
} else if (keyCode == 's') { //如果按的是设置键
if (dispMode == 0) { //如果是实时显示界面
dispMode = 2; //进入旧密码验证界面
initDispMode2();
}
} else if (keyCode == 'f') { //如果按的是复位键
strncpy(password, initPassword, 6); //重新设置为初始密码
EEPROM_write(initPassword, 0, sizeof (initPassword));
wrongTimes = 0; //!!!之前的错误次数归0
} else if (keyCode == 't') { //如果按的是退出键
if (dispMode == 2 || dispMode == 3) { //如果在旧密码验证界面或新密码输入界面
passwdTmpIndex = 0; //!!!
dispMode = 0;
refreshTimeDisplay();
}
} else if (0 <= keyCode && keyCode <= 9) { //如果按的是0-9的数字键
if (dispMode == 0) { //如果之前是显示模式0,则按下任意数字键进入身份验证界面
dispMode = 1;
initDispMode1();
}
if (passwdTmpIndex < 6) {
passwdTmp[passwdTmpIndex] = keyCode + '0'; //!!!是字符
dspBuf[2 + passwdTmpIndex] = keyCode; //更新显示
passwdTmpIndex++; //!!!
}
}
}
void refreshTimeDisplay() {
dspBuf[0] = time.hour >> 4;
dspBuf[1] = time.hour & 0x0F;
dspBuf[2] = 11; //分隔符
dspBuf[3] = time.minute >> 4;
dspBuf[4] = time.minute & 0x0F;
dspBuf[5] = 11;
dspBuf[6] = time.sec >> 4;
dspBuf[7] = time.sec & 0x0F;
}
void initDispMode1() {
dspBuf[0] = 11; //分隔符
dspBuf[1] = 11;
dspBuf[2] = 10;
dspBuf[3] = 10;
dspBuf[4] = 10;
dspBuf[5] = 10;
dspBuf[6] = 10;
dspBuf[7] = 10;
}
void initDispMode2() {
dspBuf[0] = 10; //不显示
dspBuf[1] = 11;
dspBuf[2] = 10;
dspBuf[3] = 10;
dspBuf[4] = 10;
dspBuf[5] = 10;
dspBuf[6] = 10;
dspBuf[7] = 10;
}
void initDispMode3() {
dspBuf[0] = 11;
dspBuf[1] = 10;
dspBuf[2] = 10;
dspBuf[3] = 10;
dspBuf[4] = 10;
dspBuf[5] = 10;
dspBuf[6] = 10;
dspBuf[7] = 10;
}
void tmr0_ISR() interrupt 1 {
static uint8_t cnt2ms = 0, cnt1 = 0;
TL0 = tmr0LowByte;
TH0 = tmr0HighByte;
if (cnt2ms == 99) {
cnt2ms = 0;
flag200ms = 1;
} else {
cnt2ms++;
}
if (cnt1 == 249) { //定时500ms
cnt1 = 0;
flag500ms = 1;
} else {
cnt1++;
}
if (cnt2ms % 25 == 0) {
flag50ms = 1;
}
digitalTubeScan();
if (cnt2ms & 1)
keyScan();
}
/**
* stc15系列单片机定时器2
* 中断序号12
* 作用:驱动蜂鸣器
*/
void tmr2_ISR() interrupt 12 { //stc15单片机定时器2
static uint16_t cnt1ms = 0; //定3000ms
if (enBuzzer) { //如果蜂鸣器需要响
buzzer_toggle();
if (cnt1ms == 2999) { //如果蜂鸣器响了3s
enBuzzer = 0; //禁止蜂鸣器响
cnt1ms = 0;
} else {
cnt1ms++;
}
}
}