📄 lock_main.c
字号:
}
//*************************************************清整个GDRAM空间*************************************************
void clear_gdram(void)
{
uchar x,y;
for(y=0;y<64;y++) //64
{
for(x=0;x<16;x++) //16
{
write_com(0x34);
write_com(y+0x80); //行地址
write_com(x+0x80); //列地址
write_com(0x30);
write_data(0x00);
write_data(0x00);
WDR(); //喂狗
}
}
}
//********************************************清屏*****************************************************************
void clear_screen(void)
{
write_com(0x01);
delay_ms(10);
}
//*********************************************系统起动引导主画面**************************************************
void root_directory(void)
{
write_com(0x80); //第一行(如果是地址是:80H,即LCD的第一行的第一个位置显示)
han_zi_display(" 门禁系统 ");
write_com(0x91);
write_data((tem[0]/10)+0x30);
write_data((tem[0]%10)+0x30);
han_zi_display("年");
write_data((tem[1]/10)+0x30);
write_data((tem[1]%10)+0x30);
han_zi_display("月");
write_data((tem[2]/10)+0x30);
write_data((tem[2]%10)+0x30);
han_zi_display("日");
write_com(0x8d);
switch(tem[6])
{
case 0:
han_zi_display("星期日");
break;
case 1:
han_zi_display("星期一");
break;
case 2:
han_zi_display("星期二");
break;
case 3:
han_zi_display("星期三");
break;
case 4:
han_zi_display("星期四");
break;
case 5:
han_zi_display("星期五");
break;
case 6:
han_zi_display("星期六");
break;
default:
break;
}
write_com(0x98);
han_zi_display("室内温度:");
if(cold==0xaa)
{
write_data('-');
}
else
{
write_data(0x20);
}
write_data(temp0/10+0x30);
write_data(temp0%10+0x30);
write_com(0x9e);
han_zi_display("℃");
}
//**********************************************时间、日期显示*****************************************************
void date_time_display(void)
{
write_com(0x88);
write_data((tem[3]/10)+0x30); //HOUR
write_data((tem[3]%10)+0x30);
if(set_time_temp==0) //=0 表示没有进入时间设置菜单
{
write_data(':'); //通常情况下,":"要显示为半角,目的:好看
}
else
{
han_zi_display("时"); //进入设置时间菜单时,显示为汉字,目的:方便反白显示
}
write_data((tem[4]/10)+0x30); //MINUTE
write_data((tem[4]%10)+0x30);
if(set_time_temp==0) //=0 表示没有进入时间设置菜单
{
write_data(':'); //通常情况下,":"要显示为半角,目的:好看
write_data((tem[5]/10)+0x30); //SECOND
write_data((tem[5]%10)+0x30);
}
else
{
han_zi_display("分"); //进入设置时间菜单时,显示为汉字,目的:方便反白显示
}
}
//*********************************************读EEPROM,到RAM中***************************************************
void card_pro(void)
{
uchar i=0,u=0,r=1; //EEPROM地址从0x01处保存
for(i=0;i<5;i++) //共有5张开门卡,1张管理卡
{
for(u=0;u<5;u++) //每个卡有5个字节数据
{
card_data[i][u]=eeprom_read(r++); //把EEPROM中的5张开门卡复制到RAM中
WDR(); //喂狗
}
}
}
//********************************************比较匹配A 中断*******************************************************
#pragma interrupt_handler time1_comp:7 //工作在CTC模式 每1S中断一次
void time1_comp(void)
{
if(return_en) //菜单不动作自动返回允许变量
{
auto_return++; //当auto_return>=OVER_FLOW时自动退出菜单设置
}
xx++;
if(lcd_back_en==0xaa) //LCD背光计时变量允许
{
lcd_back_time++;
if(lcd_back_time>=LCD_LAMP) //30秒后关闭LCD背光
{
lcd_back_time=0;
lcd_back_en=0;
LCD_BACK_OFF;
}
}
if(set_time_temp==0)
{
tem[5]++;
if(tem[5]>=60) //60 秒进位
{
tem[5]=0;
tem[4]++;
charge_tem++;
scan_en=0;
if(tem[4]>=60) //60 分进位
{
tem[4]=0;
tem[3]++;
if(tem[3]>=24) //24 小时进位
{
tem[3]=0;
tem[6]++;
tem[2]++;
if(tem[6]>=7) //7 星期进位
{
tem[6]=0;
}
if((tem[1]==1)||(tem[1]==3)||(tem[1]==5)||(tem[1]==7)||(tem[1]==8)||(tem[1]==10)||(tem[1]==12)) //判断大小月
{
if(tem[2]>=32) //如果为大月,则有31天
{
tem[2]=1;
tem[1]++;
}
}
else
{
if(tem[2]>=31) //如果为小月,则代表只有30天
{
tem[2]=1;
tem[1]++;
}
}
if(tem[1]>=13) //月进位
{
tem[1]=1;
tem[0]++;
if(tem[0]>=29) //当年大于2029年时,清零即2007年
{
tem[0]=7;
}
}
}
}
}
}
}
//*********************************************读卡中断INT0********************************************************
#pragma interrupt_handler int0_inter:2 //读卡
void int0_inter(void)
{
uchar i;
uchar card_num=0;
card_num=read_card_number(); //读卡
if(card_num==0xaa)
{
buzzer_pro(1); //峰鸣器指示
LCD_BACK_ON; //打开LCD背光
lcd_back_en=0xaa; //打开计时变量
lcd_back_time=0; //计时变量清0
WDR(); //喂狗
if((manage_card[0]==rev_dat[0])&&(manage_card[1]==rev_dat[1])&&(manage_card[2]==rev_dat[2])&&(manage_card[3]==rev_dat[3])&&(manage_card[4]==rev_dat[4])&&(manage_card_inc_en==0))
{
inc_card_en=0xaa; //管理卡
GIFR=(1<<INTF0);
GICR&=~((1<<INT1)|(1<<INT0)); //关闭外部中断0、1
return;
}
if(manage_card_inc_en==0xaa) //添加卡
{
manage_card_inc_en=0;
GIFR=(1<<INTF0);
GICR&=~(1<<INT0); //关闭外部中断0
return;
}
for(i=0;i<5;i++)
{
if((card_data[i][0]==rev_dat[0])&&(card_data[i][1]==rev_dat[1])&&(card_data[i][2]==rev_dat[2])&&(card_data[i][3]==rev_dat[3])&&(card_data[i][4]==rev_dat[4]))
{ //卡1
GICR&=~((1<<INT1)|(1<<INT0)); //关闭外部中断0、1
xx=0;
WDR(); //喂狗
LOCK_ON; //开锁
delay_ms(500);
LOCK_OFF;
rev_dat[0]=rev_dat[1]=rev_dat[2]=rev_dat[3]=rev_dat[4]=0xff;
i=6;
}
}
close_read=1;
card_num=0;
xx=0;
GICR&=~(1<<INT0); //关闭外部中断0
card_num=0;
}
GIFR=(1<<INTF0);
}
//*********************************************按键中断INT1********************************************************
#pragma interrupt_handler int1_on:3
void int1_on(void)
{
delay_ms(10); //按键采样, 注意,一定要延时8MS以上,否则会造成连键现象
kk=1;
GICR&=~(1<<INT1); //关闭外部中断1
GIFR=(1<<INTF1);
}
//*****************************************************************************************************************
//文件名: 用AD来检测按键
//编译日期: 2007-01-21
//功能描述:
// 1、共8个KEY,利用AD口其中的一个,来测电压不同来判断哪个按键按下。
//CPU类型: ATmega16
//晶振频率: 7.3728MHZ
//版本: V0.1
//编程: 于军峰
//*****************************************************************************************************************
//理论值:
// S1=0V S2=0.45V S3=0.83V S4=1.15V S5=1.42V S6=1.66V S7=1.875V S8=2.05V 无按下时=5V
//
// S1=SET S2=向上 S3=向下 S4=向左 S5=向右 S6=确认 S7=返回 S8=关于
//
//**********************************************AD来检测按键*******************************************************
void read_adc(void)
{
uint key_val=0;
key_val=adc_sampling(ADC_PINA0);
if(key_val<400)
{
key=1;
}
else if(key_val<600) //向上
{
key=2;
}
else if(key_val<1000) //向下
{
key=3;
}
else if(key_val<1200) //向左
{
key=4;
}
else if(key_val<1500) //向右
{
key=5;
}
else if(key_val<1700) //OK
{
key=6;
}
else if(key_val<1900) //返回
{
key=7;
}
else if(key_val<2200) //说明
{
key=8;
}
else
{
key=0;
return;
}
}
//************************************************ADC 采样*********************************************************
uint adc_sampling(uchar adc_input)
{
ulong temp32=0;
uint tem_3=0;
CLI(); //关中断
ADMUX=(0x40|adc_input); //选择外接参考电压,AVCC, AREF 引脚外加滤波电容
//adc_input:单端通道 0x00~0x07,0x1E,0x1F
ADCSRA|=(1<<ADSC); //启动AD转换
while ((ADCSRA&(1<<ADIF))==0);
ADCSRA|=(1<<ADIF); //写1清除标志位
temp32=ADC;
//**************************************第一次采样的值舍去不要*****************************************************
ADMUX=(0x40|adc_input); //选择外接参考电压,AVCC, AREF 引脚外加滤波电容
//adc_input:单端通道 0x00~0x07,0x1E,0x1F
ADCSRA|=(1<<ADSC); //启动AD转换
while ((ADCSRA&(1<<ADIF))==0);
ADCSRA|=(1<<ADIF); //写1清除标志位
temp32=ADC;
temp32*=vref;
tem_3=((uint)(temp32/1024));
SEI(); //开中断
return(tem_3);
}
//**********************************************室温检测***********************************************************
uchar temperature_check(void)
{
uchar adc_result1=0;
temp_value=adc_sampling(ADC_PINA1); //AD采样
adc_result1=get_degree();
if(adc_result1<=30) //是否为零下
{
adc_result1=31-adc_result1;
cold=0xaa;
}
else
{
cold=0;
adc_result1-=31;
}
return(adc_result1);
}
//**********************************************温度查表***********************************************************
uchar get_degree(void)
{
uchar x=129; //只检测温度-30---+99
for (x=129;x>0;x--) // 查表
{
if (temp_1[x]>=temp_value)
{
return x;
}
}
return x;
}
//********************************************峰鸣器处理***********************************************************
void buzzer_pro(uchar p)
{
for(;p>0;p--)
{
WDR(); //喂狗
buzzer_on;
delay_ms(15);
buzzer_off;
delay_ms(15);
}
}
//**************************************************Program End****************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -