📄 师姐全部程序wsy.c
字号:
/*0x0020-0x36af 存储2000张卡号(5B卡号+1B权限+1B门号) 14000B
0x36b0-0x3727 存储60个节假日 120B
0x3730-0x386f 存储时间段 320B
0x3870-0xffff 存储门禁事件纪录*/
#include<c8051f020.h> // SFR declarations
#include<intrins.h>
#include<absacc.h>
#define SYSCLK 22118400 //系统时钟频率(Hz)
#define BAUDRATE 9600 //波特率
#define uchar unsigned char //typedef unsigned char uchar;
#define uint unsigned int
#define nop() _nop_()
#define cs_fm P4&=0xF8 // FM20l08片选允许
#define ncs_fm P4|=~0xF8 // 不选中任何芯片
#define BANK1 P4|=0x08 // 选择BANK1:64-128K
#define BANK0 P4&=0xF7 // 选择BANK0:0-64K
#define cs_12887 P4=P4&0xF8|0x02 // 选中DS12887
#define cs_74377 P4=P4&0xF8|0x03 // 选中74377
#define cs_74244 P4=P4&0xF8|0x04 // 选中74244
#define cs_74245 P4=P4&0xF8|0x05 // 选中74245
#define YEAR XBYTE[0x09] //年
#define MON XBYTE[0x08] //月
#define DAY XBYTE[0x07] //日
#define WEEK XBYTE[0x06] //星期
#define HOU XBYTE[0x04] //时
#define MIN XBYTE[0x02] //分
#define SEC XBYTE[0x00] //秒
#define A_12887 XBYTE[0x0a] //12887寄存器A
#define B_12887 XBYTE[0x0b] //12887寄存器B
#define C_12887 XBYTE[0x0c] //12887寄存器C
#define D_12887 XBYTE[0x0d] //12887寄存器D
#define LCD1 XBYTE[0x00]
sbit BG_IO = P1^2; //液晶背光
sbit rs = P1^3; //液晶数据指令 H=data; L=command;
sbit rw = P1^4; //液晶读写 H=read; L=write;
sbit RD0_IO = P3^0; //串口0发送控制。0为发送,1为接收
sbit RD1_IO = P3^1; //串口1发送控制。0为发送,1为接收
sbit BELL_IO = P3^2; //蜂鸣器
sbit LED_IO = P3^3;
sbit FQK_IO = P3^4; //防撬开关
sbit i_txct = P3^6; //读卡
sbit i_scio = P3^5;
sbit lvl = P1^5; //铁电低电压检测
bit keyon_flag=0 ; //有键按下
bit keyon_flag1=0 ; //最终确认键按下
bit clrlcd_flag=0 ; //编程状态下,输入错误时,删除先前输入的数字
bit delcard_flag=0; //编程状态下删除卡号
bit chaxun_flag=0 ; //查询事件记录标志
bit open_flag=0 ; //开锁标志
bit enter_flag=0 ; //确认
bit timechange_flag=0 ; //更改时间标志
bit esc_flag=0 ; //取消标志
bit program_flag=0; //编程标志位
bit second_flag=0 ; //1秒定时标志
bit readcad_flag=0;
bit keywrcard_flag=0; //刷卡写卡号或写节假日
bit quanxian_flag=0;
bit shiqu_flag=0; //写时区权限和门号
bit qxtime_flag=0; //写时段
bit delqxtime_flag=0;
bit delshijian_flag=0;
bit next_flag=0;
bit last_flag=0;
bit chacard_flag=0;
bit chashiduan_flag=0;
bit chaholiday_flag=0;
bit one_flag=0;
bit chashijian_flag=0;
uchar count_time3=5; //定时器3定时初值10ms,而键盘扫描是50ms扫描一次,故循环值为5
uint count_time1=1000;
uint count_time2;
uchar JDQ_TIME;
uchar keytimes1=0; //按键次数
uchar recode ; //列扫描码
uchar sccode ; //行扫描码
uchar idata keynumber ; //键值
uchar idata pp=0xff ; //P0口的初始化,在程序中会变化
uchar idata scantime ; //键盘扫描程序中扫描次数
uchar idata gc_cad[8]; //存储读到的卡号
uchar idata gc_crc8=0;
uchar idata keycodebuf[5];
uchar idata key_card[5]; //存储键盘输入的卡号
uchar idata key_time[7]; //键盘输入的要修改的时间
uchar idata read_time[7]; //从ds12887读到的时间
uchar idata key_holiday[2];
uchar idata key_shiqu[2];
uchar idata qx_time[10]; //键盘输入的权限时间段
uchar idata shiqu_num=0;
uchar idata door_num=0;
uchar idata shu=0;
uchar idata hang,lie;
uchar xdata *point1;
uchar idata b[10];
uchar idata quanxian_num;
uchar idata sv0count;
uchar idata kflag=0;
uint idata check_crc=0;
uchar idata addr;
uchar idata cmdbuf[15]=0;
uchar idata sendkeycode[8];
uchar idata shiduan[8];
uchar idata holiday[2];
uchar up_flag=0;
//sendyd();
unsigned char code crc8[256]={ 0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83,
0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e,
0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc,
0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0,
0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62,
0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d,
0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff,
0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5,
0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07,
0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58,
0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a,
0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6,
0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24,
0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b,
0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9,
0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f,
0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd,
0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92,
0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50,
0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c,
0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee,
0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1,
0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73,
0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49,
0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b,
0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4,
0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16,
0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a,
0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8,
0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7,
0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35
};
uchar code AC_TABLE[]={
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, //第一行汉字位置
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, //第二行汉字位置
0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, //第三行汉字位置
0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, //第四行汉字位置
};
///定时器0延时1us///
void Timer0_us(uchar us)
{
uchar i;
TCON&=~0x30;
TMOD&=~0x0f;
TMOD|=0x01;
CKCON|=0x08;
for(i=0;i<us;i++)
{
TR0=0;
TH0=(-SYSCLK/1000000)>>8;
TL0=-SYSCLK/1000000;
TR0=1;
while(TF0==0);
TF0=0;
}
}
///定时器0延时1ms///
void Timer0_ms(uint ms)
{
uint i;
TCON&=~0x30; //停止定时器0并清除溢出标志
TMOD&=~0x0f;
TMOD|=0x01; //配置定时器0为16位方式
CKCON|=0x08; //定时器0对SYSCLK计数,即T0M=1,定时器0使用系统时钟
for(i=0;i<ms;i++)
{
//计数毫秒
TR0=0; //停止定时器T0
TH0=(-SYSCLK/1000)>>8; //设置定时溢出周期为1ms或TH0=(65536-SYSCLK/1000)>>8;
TL0=(-SYSCLK/1000); //TL0=(65536-SYSCLK/1000)&0X00ff;
TR0=1; //启动定时器0
while(TF0==0)
{}; //等待溢出
TF0=0; //清除溢出标志
}
}
/////用定时器3中断扫描键盘///////////////
void time3() interrupt 14 using 1
{
TMR3CN&=0x7F; //清除溢出标志
TMR3RLH =0xb8;
TMR3RLL =0x00; //初始化重装载值,定时10ms初值
if(count_time3--==0)
{
count_time3=5;
cs_74377; ///////使377有效
nop();
P7=0x0f ;///键盘驱动信号设为低,送全0扫描码
P4&=0x7f; //P4.7=0 即/wr=0
nop();
nop();
P4|=0x80; ///P4.7=1,即Wr=1,产生上升沿
nop();
nop();
cs_74244; ///P4.7=1,使244有效
//有键按下
if((P7&0x7f)!=0x7f) ///此时244有效,P7.7用于用于连接语音芯片的RAC管脚
{
Timer0_ms(20);
//Timer0_ms(20); ///延时20ms
if((P7&0x7f)!=0x7f)
{
sccode=0xef ; //逐行扫描初值
while(sccode!=0xff)
{
cs_74377 ; //377有效
nop();
P7=pp&sccode ; //输出行扫描码
P4&=0x7f ; //wr=0
nop();
nop();
P4|=0x80; //wr=1
nop();
cs_74244 ; //244有效
nop();
nop();
if((P7&0x7f)!=0x7f)
{
recode=(P7|0x80);
keyon_flag=1 ; //键按下标志位置1
BELL_IO=0;
Timer0_ms(150); //Timer0_ms(200);
BELL_IO=1;
sccode=0xff ;
}
else
{
sccode=(sccode<<1)|0x01 ; //行扫描码左移1位
scantime++;
}
}
switch(scantime)
{
case 0x00 : //第一行有键按下
switch(recode)
{
case 0xfe :
keynumber=0x0B ; ///B键
break ;
case 0xfd :
if(chaxun_flag)
{
chashijian_flag=1;
one_flag=1;
}
else
keynumber=0x0D ; //D键
break ;
case 0xfb :
if(quanxian_flag==1)
{delqxtime_flag=1;}
else if(chaxun_flag)
delshijian_flag=1;
else
keynumber=0x0F ; //F键
break ;
case 0xf7 :
if(quanxian_flag==1)
{qxtime_flag=1;}
else if(chaxun_flag)
{chashiduan_flag=1;
one_flag=1;}
else
keynumber=0x0E ; //E键
break ;
case 0xef :
if(chaxun_flag)
{
chacard_flag=1;
one_flag=1;
}
else
keynumber=0x0C ; //C键
break ;
case 0xdf :
keynumber=0x0A; //A键
break ;
default :
break ;
}
break ;
case 0x01 : //第二行有键按下
switch(recode)
{
case 0xfe :
if((program_flag==1)||(quanxian_flag==1))
delcard_flag=1;/// 只有在编程状态下,按下此键才可以删除卡号
else
chaxun_flag=1 ; //查询门禁事件记录;编程状态下删除卡号
break ;
case 0xfd : //编程键或查询时下翻键
if(chaxun_flag==1)
next_flag=1;
else
program_flag=1;
break ;
case 0xfb : //退出键
if((timechange_flag==1)||(program_flag==1)||(chaxun_flag==1)||(quanxian_flag==1)||(chaxun_flag==1)) //只有在按了"设置时间"按键或按了编程键之后,"退出"键才有效
esc_flag=1 ;
else
keyon_flag=0;
break ;
case 0xf7 ://修改权限
quanxian_flag=1;
break ;
case 0xef :
if(quanxian_flag)
{shiqu_flag=1;} //修改权限时写时区权限
else if(chaxun_flag)
last_flag=1;
else
timechange_flag=1 ;//修改时间或门禁事件查询时上翻键
break ;
case 0xdf : // 远程开锁
if((program_flag==1)||(quanxian_flag==1))
keywrcard_flag=1;
else if(chaxun_flag)
{chaholiday_flag=1;
one_flag=1;}
else
open_flag=1 ;
break ;
default :
break ;
}
break ;
case 0x02 :
//第三行有键按下
switch(recode)
{
case 0xfe :
keynumber=0x01 ;
break ;
case 0xfd :
keynumber=0x02 ;
break ;
case 0xfb :
keynumber=0x03 ;
break ;
case 0xf7 :
keynumber=0x04 ;
break ;
case 0xef :
keynumber=0x05 ;
break ;
case 0xdf :
keynumber=0x06 ;
break ;
default :
break ;
}
break ;
case 0x03 : //第四行有键按下
switch(recode)
{
case 0xfe :
keynumber=0x07 ;
break ;
case 0xfd :
keynumber=0x08 ;
break ;
case 0xfb :
keynumber=0x09 ;
break ;
case 0xf7 :
//keynumber='删除';
clrlcd_flag=1 ;
break ;
case 0xef :
keynumber=0x00 ;
break ;
case 0xdf :
//keynumber='确认';
if(((timechange_flag==1)&&(keytimes1>=15))||((program_flag==1)&&(keytimes1>=11))||
((quanxian_flag==1)&&(keytimes1>=5))||((quanxian_flag==1)&&(keytimes1>=21))) //只有将年月日小时分钟都设置完后,
//或在编程状态下,输入卡号之后,按"确认"键方可有效。
enter_flag=1 ;
else
keyon_flag=0;
break ;
default :
break ;
}
break ;
default :
break ;
}
//end switch
}
//end 去抖if
}
//end
if(keyon_flag)
{
if(P0!=0x7f)
keyon_flag1=1 ;
}
scantime=0 ;
P0=pp ;
P4|= 0x07;
}
}
void wr_lcd (uchar dat_comm,uchar content)
{
//chk_busy ();
Timer0_us(1);
//delay (12);
if(dat_comm)
{
rs=1; //data
rw=0; //write
}
else
{
rs=0; //command
rw=0; //write
}
P7=content; //output data or comm
cs_74245;
Timer0_us(1);//加延时
//delay (24);
P4|=0x07;
}
//------------------初始化-----------------//
void init_lcd (void)
{
wr_lcd (0,0x30); //30---基本指令动作
wr_lcd (0,0x01); //清屏,地址指针指向00H
wr_lcd (0,0x06); //光标的移动方向
wr_lcd (0,0x0c); //开显示,关游标
}
void display(uchar *ptr,uchar ddram)
{
uchar i;
wr_lcd (0,0x30);
if(ddram<0x88)
{hang=0;}//定位行地址:第一行
else if(ddram<0x90)
{hang=2;}//定位行地址:第三行
else if(ddram<0x98)
{hang=1;}//定位行地址:第二行
else
{hang=3;}//定位行地址:第四行
switch(hang)
{
case 0:wr_lcd(0,0x80);
break;
case 1:wr_lcd(0,0x90);
break;
case 2:wr_lcd(0,0x88);
break;
case 3:wr_lcd(0,0x98);
}
for(i=0;i<16;i++)
{wr_lcd(1,ptr[i]);//输出单个字符
}///end of for(i1=0;i1<16;i1++)
}
///显示单个汉字///////
void chn_disp1 (uchar *chn,uchar addr)
{
uchar i;
wr_lcd (0,0x30);
wr_lcd (0,addr);
for(i=0;i<2;i++)
{
wr_lcd(1,chn[i]);
}
}
/*void chn_disp8 (uchar *chn,uchar addr)
{
uchar i;
wr_lcd (0,0x30);
wr_lcd (0,addr);
for(i=0;i<16;i++)
{
wr_lcd(1,chn[i]);
}
}*/
////在指定单元显示单个字符////
void num_disp1 (uchar *num,uchar addr)
{
wr_lcd (0,0x30);
wr_lcd (0,addr);
wr_lcd(1,num[0]);
}
////在指定单元显示单个字符////
void num_disp2 (uchar *num)
{
wr_lcd (0,0x30);
wr_lcd(1,num[0]);
}
////在指定的单元显示一个数字////////////
void num_disp(uchar t,uchar addr)
{
wr_lcd (0,0x30);
switch(t)
{
case 0:
wr_lcd (0,addr);
wr_lcd (1,0x30);
break;
case 1:
wr_lcd (0,addr);
wr_lcd(1,0x31);
break;
case 2:
wr_lcd (0,addr);
wr_lcd(1,0x32);
break;
case 3:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -