/**
* 項目名:門禁系統
* 文件名: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++;
}
}
}