?? lock_main.c
字號:
/******************************************************************************************************************
程序名: 射頻卡門禁系統(tǒng)
功能概述:
1、 點陣LCD(128*64)顯示。在正常、設(shè)置情況下LCD顯示系統(tǒng)各個時期的菜單以供選擇。
2、 射頻卡開鎖,開鎖時用射頻卡放在讀卡器上(距離<15CM)即可開鎖,如果用非法卡連續(xù)刷寫次數(shù)超過3
次則報警(報警功能沒有添加),這時系統(tǒng)將關(guān)閉刷卡器30分鐘,在30分鐘后再允許刷卡。
3 本系統(tǒng)分為:
1)、1個主機。
2)、2個讀卡頭(一個在門外供刷卡用、一個在主機旁用于管理操作)
4、 本鎖開鎖時供電,平時斷電(12V)。
5、 8個按鍵(AD轉(zhuǎn)換采樣取值)(設(shè)置、+、-、↑、↓、確認(rèn)、返回、說明)
6、 每次按下鍵、刷卡時有峰鳴器指示
7、 LCD背光在有按鍵按下時、或刷卡時自動點亮,延時30秒關(guān)閉
8、 門外有人體紅外傳感器探頭,發(fā)現(xiàn)2米內(nèi)有人,自動進入預(yù)警狀態(tài),如果是在晚上超過7點鐘,則點亮門前的燈泡照明,
如果此時有人破壞(比如取下燈泡、剪斷燈炮的線、打爛燈泡)也要報警。否則、連續(xù)在門前超過1分鐘,就開始報警。
(此功能沒有添加)
9、 開門時發(fā)出“歡迎光臨”,并提示關(guān)門(此功能沒有添加)
10、 本機帶有門鈴,并能記錄前10天門鈴按下的次數(shù)。(此功能沒有添加)
11、 LCD顯示日期、星期、時間、室內(nèi)溫度、鎖的狀態(tài)、功能設(shè)置(菜單顯示)等
12、 可以查詢過去10天內(nèi)的開門記錄并由LCD顯示出來(此功能沒有添加)
13、 可以于電腦通過RS-232接口連接進行通信,監(jiān)看門的狀態(tài)、開門記錄等,方便打印(此功能沒有添加)
14、 要求鎖誤判率小于1PPM
15、 系統(tǒng)配有UPS(12V) 平時用UPS電能,只有當(dāng)主機檢測到電壓低于11.5V時,自動接入火電進行充電。
電瓶充滿時(大約5小時)自動斷電。
16、 電壓:12V
17、 電流:待機時<50MA
射頻卡類型: 4001、EM4100和含E2PROM的RF卡。如E5550。
MCU類型: ATmega16
晶振頻率: 7.3728MHZ
版本: V0.1
編程: 于軍峰
編譯日期: 2007-05-01
******************************************************************************************************************/
#include<iom16v.h>
#include<macros.h>
#include<stdio.h>
#include"LCD_12864.H" //LCD頭文件
#include"read_card.H" //讀卡頭文件
#define key_inc (PINC&(1<<PC0)) //按鍵+,選擇日期、時間時用
#define key_dec (PINC&(1<<PC1)) //按鍵-,選擇日期、時間時用
#define BAUDRATE 9600 //波特率
#define F_CPU 7372800 //晶振頻率
#define LCD_LAMP 60 //LCD默認(rèn)30S后關(guān)閉
#define BATTERY_TIME 5 //每十分鐘檢測一次電池電量
#define ADC_PINA0 0x00 //ADC0 按鍵AD 單端通道,不放大
#define ADC_PINA1 0x01 //ADC1 溫度采樣
#define ADC_PINA2 0x02 //ADC2 電平電量檢測
#define LCD_BACK_ON PORTC&=~(1<<PC5)
#define LCD_BACK_OFF PORTC|=(1<<PC5)
#define buzzer_on PORTD&=~(1<<PD7)
#define buzzer_off PORTD|=(1<<PD7)
#define charge_on PORTC&=~(1<<PC6)
#define charge_off PORTC|=(1<<PC6)
#define LOCK_ON PORTC&=~(1<<PC3)
#define LOCK_OFF PORTC|=(1<<PC3)
#define CHARGE_STATUS (PINC&(1<<PC2))
#define null 0
#define vref 5000 //AD轉(zhuǎn)換參考電壓
#define OVER_FLOW 10 //進入菜單設(shè)置時,如果在10S內(nèi)沒有按下任何鍵,則自動退出
#pragma data:code
//const uchar manage_card[5]={0x0b,0,0x2d,0x23,0x5f}; //住房卡-----當(dāng)作管理卡
const uchar manage_card[5]={0x33,0,0x7c,0x09,0xb1}; //000 8128945-----當(dāng)作管理卡
//*************************************************溫度測定查表****************************************************
//******************************************溫度范圍是:-30度----+99度*********************************************
const uint temp_1[130]={
4304,4270,4235,4198,4161,4122,4083,4042,4001,3958,
3914,3870,3824,3778,3731,3683,3635,3585,3535,3484,
3433,3381,3329,3276,3223,3169,3116,3062,3008,2953,
2899,2844,2789,2733,2678,2622,2568,2514,2459,2405,
2353,2299,2248,2196,2145,2095,2045,1996,1948,1901,
1854,1808,1763,1719,1676,1599,1590,1549,1508,1468,
1429,1391,1354,1318,1282,1247,1214,1181,1149,1117,
1087,1057,1028,1000,973 ,946 ,920 ,895 ,870 ,846 ,
823 ,800 ,777 ,755 ,755 ,713 ,692 ,673 ,654 ,632 ,
617 ,600 ,583 ,567 ,551 ,536 ,521 ,506 ,491 ,478 ,
465 ,452 ,440 ,428 ,417 ,405 ,394 ,384 ,373 ,364 ,
354 ,345 ,335 ,326 ,318 ,310 ,302 ,294 ,286 ,279 ,
271 ,265 ,258 ,252 ,245 ,239 ,233 ,227 ,222 ,216 ,
};
//*****************************************************************************************************************
#pragma data:data
uchar card_data[5][5]={
{0,0,0,0,0}, //卡1
{0,0,0,0,0}, //卡2
{0,0,0,0,0}, //卡3
{0,0,0,0,0}, //卡4
{0,0,0,0,0}, //卡5
};
uchar tem[7]={7, 5, 1, 8, 0, 0, 6}; //日期、時間、星期數(shù)組
// 年/月/日 /H /M /S /W
//********************************************目錄結(jié)構(gòu)體定義*******************************************************
struct menu_item
{
short menu_count;
char *display_string;
void (*subs)();
struct menu_item *children_menus;
struct menu_item *parent_menus;
};
//**********************************************結(jié)構(gòu)數(shù)組聲明*******************************************************
struct menu_item main_menu[4];
struct menu_item alarm_menu[2];
struct menu_item infrared_menu[2];
struct menu_item lamp_menu[2];
struct menu_item (*menu_point) = main_menu;
struct menu_item card_main_menu[4];
struct menu_item card_inc_menu[2];
struct menu_item card_dec_menu[2];
struct menu_item (*menu_card) = card_main_menu;
uchar user_choose = 0;
uchar max_items=0;
uint temp_value=0; //溫度檢測AD值
//********************************************變量定義*************************************************************
uchar second_temp=0; //秒變量
uchar scan_en=0; //主屏掃描標(biāo)志位
uchar key=0; //按鍵變量
uchar kk=0; //按鍵按下標(biāo)志位
uchar auto_return=0; //菜單自動返回變量
uchar return_en=0; //菜單自動返回標(biāo)志位
uchar left_right=0; //左右鍵變量
uchar choose_temp=0; //子菜單標(biāo)題變量
uchar return_temp=0; //返回臨時變量
uchar set_time_temp=0; //設(shè)置時間時菜單變量,如果=1表示屏顯在設(shè)置時間菜單
uchar twinkling_addr=0x91; //設(shè)置時間時閃動顯示位置變量
uchar inc_card_en=0; //添加新卡允許變量
uchar manage_card_inc_en=0; //管理卡
uchar cold=0; //溫度正負(fù)極標(biāo)志位
uchar temp0=0; //溫度值變量
uchar xx=88; //溫度更新變量,開機賦一個比較大的數(shù),目的是開機就顯示溫度
uchar close_read=0;
lcd_back_en=0; //LCD背光計時變量允許
lcd_back_time=0; //LCD背光計時變量
//*****************************************************************************************************************
void delay_ms (unsigned int m); //延時
void read_adc(void); //按鍵ADC處理
void date_time_display(void); //時間日期顯示
void root_directory(void); //引導(dǎo)主畫面
void set_menu(void); //設(shè)置菜單
void clear_screen(void); //清屏
void clear_gdram(void); //清全部GDRAM
void select_menu(uchar data1); //選擇菜單時,標(biāo)志
void time_set_display(void); //時間、日期設(shè)置顯示
uint adc_sampling(uchar adc_input); //ADC采樣
uchar get_degree(void); //溫度查表
uchar temperature_check(void); //室溫檢測
uchar charge_tem=0; //每十分鐘,檢測一次電池電量,此變量主要是計時
uint battery_temp=0; //電平電壓變量
//************************************************函 數(shù) 聲 明 區(qū)***************************************************
void main_menu_initial(void); //主菜單初始化
void alarm_menu_initial(void); //報警菜單初始化
void infrared_menu_initial(void);
void lamp_menu_initial(void);
void menu_initial(void);
void card_main_menu_initial(void);
void card_inc_menu_initial(void);
void card_dec_menu_initial(void);
void show_menu(void);
void date_time_set(void);
void alarm_set(void);
void infrared_set(void);
void lamp_set(void);
void nullsubs(void);
void twinkling_addr_pro(void);
void lcd_week_pro(void);
void key_inc_dec(void);
void lcd_menu_set(void);
void card_pro(void);
void buzzer_pro(uchar p);
//*****************************************************************************************************************
void inc_new_card(void); //添加新卡的處理函數(shù)
void query_card(void); //查詢卡函數(shù)
void save_card(void); //保存卡時處理函數(shù)
void no_save_card(void); //取消保存卡時處理函數(shù)
void clear_card(void); //刪除全部卡
void no_clear_card(void); //取消刪除卡
void card_menu_show(void); //管理卡菜單顯示
void card_menu_pro(void); //管理卡菜單處理
void char_twinkling(uchar data_1); //字符消隱
//*****************************************************************************************************************
void eeprom_write(uint eeprom_address, uchar eeprom_data); //寫----EEPROM 操作
uchar eeprom_read(uint eeprom_address); //讀----EEPROM 操作
//*************************************************主程序**********************************************************
void main(void)
{
PORTA=0XF8; //PA0---按鍵AD;PA1---室內(nèi)溫度AD;PA2---電平電量檢測
PORTB=0XFF;
PORTC=0XFF;
PORTD=0XFF;
DDRA =0XF8; //AD轉(zhuǎn)換時要設(shè)為輸入、且端口要清0
DDRB =0XFF;
DDRC =0b11111000;
DDRD =0b11110010; //INT0、INT1、RXD設(shè)成輸入;TXD設(shè)成輸出
TIMSK=(1<<OCIE1A); //輸出比較A 匹配中斷使能
TCCR1A=0;
TCCR1B=0X0D; //CTC模式,1024分頻
OCR1A=7200; //定時1S
GICR=(1<<INT1)|(1<<INT0); //打開外部中斷0、1
MCUCR=(1<<ISC00); //INT0 引腳上任意的邏輯電平變化都將引發(fā)中斷
ADCSRA=(1<<ADEN)|0x06; //使能ADC,時鐘64分頻 125KHz@8MHz system clock
WDTCR=0x0f; //(1<<WDE)|(1<<WDP2)|(1<<WDP1); //打開看門狗,溢出時間為2.1S
write_com(0x01); //清除顯示,并且設(shè)定地址指針為00H
menu_initial(); //菜單數(shù)組初始化
send_initial(); //串口初始化
WDR(); //喂狗
card_pro(); //讀EEPROM,到RAM中
lcd_reset(); //LCD初始化
write_com(0x90);
buzzer_on;
LCD_BACK_ON; //打開LCD背光
han_zi_display(" 系統(tǒng)正在啟動 ");
write_com(0x88);
han_zi_display(" 請稍后......");
delay_ms(500);
clear_gdram(); //清除GDRAM--繪圖RAM
clear_screen(); //清屏
buzzer_off; //峰鳴器指示
lcd_back_en=0xaa; //打開計時變量
lcd_back_time=0; //計時變量清0
SEI(); //使能全局中斷
while(1)
{
WDR(); //喂狗
if(scan_en==0) //只有在scan_en=0的時候掃描主屏,平時只更新時間
{
scan_en=~scan_en;
clear_screen();
temp0=temperature_check(); //溫度檢測
root_directory();
}
if(second_temp!=tem[5]) //每秒鐘掃描一次
{
second_temp=tem[5];
date_time_display();
}
if(close_read==1)
{
if(xx>=5)
{
xx=0;
close_read=0;
second_temp=0;
GICR=((1<<INT1)|(1<<INT0)); //開外部中斷0、1
}
}
if(kk) //=1表示有按鍵按下
{
kk=0;
read_adc(); //AD轉(zhuǎn)換,取得鍵值
buzzer_pro(1); //峰鳴器指示
LCD_BACK_ON; //打開LCD背光
lcd_back_en=0xaa; //打開計時變量
lcd_back_time=0; //計時變量清0
if(key==1)
{
GICR&=~(1<<INT0); //關(guān)閉讀卡外部中斷0
lcd_menu_set(); //LCD菜單設(shè)置
GICR=((1<<INT1)|(1<<INT0)); //開外部中斷0、1
}
else if(key==8)
{
GICR&=~((1<<INT1)|(1<<INT0)); //關(guān)閉部中斷0、1
key=0;
clear_screen(); //清屏
write_com(0x80);
han_zi_display(" 警 告 ");
write_com(0x88);
han_zi_display("版權(quán)歸于軍峰所有");
write_com(0x98);
han_zi_display(" 拷貝必究!!!");
delay_ms(6000);
scan_en=0; //主菜單調(diào)用允許標(biāo)志位
clear_screen(); //**************
GICR=((1<<INT1)|(1<<INT0)); //開外部中斷0、1
}
else
{
key=0;
GICR=((1<<INT1)|(1<<INT0)); //開外部中斷0、1
}
}
WDR(); //喂狗
if(inc_card_en==0xaa) //=0xaa表示調(diào)用管理菜單允許
{
inc_card_en=0;
rev_dat[0]=rev_dat[1]=rev_dat[2]=rev_dat[3]=rev_dat[4]=0xff;
lcd_dis_num=0;
card_menu_pro();
GICR=((1<<INT1)|(1<<INT0)); //開外部中斷0、1
}
if(charge_tem>=BATTERY_TIME)
{
charge_tem=0;
battery_temp=0;
WDR(); //喂狗
battery_temp=adc_sampling(ADC_PINA2); //AD采樣電平電量
if(battery_temp<=3750) //3750=12V,當(dāng)電平電壓小于12V時,開始充電
{
charge_on;
if(CHARGE_STATUS!=0)
{
buzzer_pro(10); //峰鳴器指示
}
}
else if((CHARGE_STATUS==1)||(battery_temp>=4375)) //如果大于4375=14V,表示要關(guān)閉充電器
{
charge_off;
}
}
}
}
//************************************************管理卡主菜單操作*************************************************
void card_menu_pro(void)
{
clear_screen();
menu_card= card_main_menu;
user_choose=0;
card_menu_show();
return_en=1; //打開菜單自動返回變量
GICR|=(1<<INT1); //打開外部中斷1***********************
while(auto_return<OVER_FLOW)
{
WDR(); //喂狗
if(kk)
{
kk=0;
auto_return=0; //清除菜單自動返回累計時間變量
read_adc();
buzzer_pro(1); //峰鳴器指示
LCD_BACK_ON; //打開LCD背光
lcd_back_en=0xaa; //打開計時變量
lcd_back_time=0; //計時變量清0
WDR();
switch(key)
{
case 0: //沒有按下按鍵
break;
case 1: //設(shè)置
key=0;
break;
case 2: //向上
key=0;
if (user_choose == 0)
{
user_choose = max_items;
}
user_choose --;
break;
case 3: //向下
key=0;
user_choose ++;
if (user_choose == max_items)
{
user_choose = 0;
}
break;
case 4: //向左
key=0;
break;
case 5: //向右
key=0;
break;
case 6: //確認(rèn)
key=0;
if (menu_card[user_choose].subs != nullsubs)
{
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -