📄 51
字号:
#include <reg52.h>#include <string.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define ulong unsigned long#define IDLE 0#define KEYA 0x00#define SPI_REN()IE0=0;EX0=1 //关闭所有中断后,开启外部中断INT0#define SPI_RDIS()EX0=0 //关闭外部中断INT0#define MI_OK 0#define MI_CRCERR 2#define DS1302_SECOND 0x80 //秒寄存器#define DS1302_MINUTE 0x82 //分寄存器#define DS1302_HOUR 0x84 //小时寄存器#define DS1302_WEEK 0x8A //星期寄存器#define DS1302_DAY 0x86 //日寄存器#define DS1302_MONTH 0x88 //月寄存器#define DS1302_YEAR 0x8C //年寄存器#define EER 0xff#define REP 0x80#define x1 0x80 //第一行坐标#define x2 0x88 //第三行坐标#define x3 0x90 //第二行坐标#define x4 0x98 //第四行坐标#define comm 0 //指令标志#define dat 1 //数据标志sbit ACC0=ACC^0;sbit ACC7=ACC^7;sbit SCLK=P1^0; //zlg500时钟脚sbit SDATA=P1^1; //zlg500数据脚sbit SS=P3^2; //zlg500传输启动线sbit zlg500_RST=P1^2; //zlg500复位脚sbit SDA=P1^3; //2402数据线引脚sbit SCL=P1^4; //2402时钟线引脚sbit DS1302_RST=P1^5; //DS1302复位线引脚sbit DS1302_CLK=P1^6; //DS1302时钟线引脚sbit DS1302_IO=P1^7; //DS1302数据线引脚sbit cs= P2^2; //高电平为数据,低电平为指令sbit std= P2^3; //数据输出位sbit LCD_sclk= P2^4; //时钟sbit psb= P2^5; //H=并口; L=串口;sbit rst= P2^6; //Reset Signal 低电平有效typedef struct SYSTEMTIME{ uchar Second; uchar Minute; uchar Hour; uchar Week; uchar Day; uchar Month; uchar Year;}SYSTEMTIME; //定义的时间类型uchar code tab[]={"身份错误!"};uchar code tab1[]={"重复打卡!"};uchar code tab2[]={"打卡成功!"};uchar code tab3[]={"考勤系统"};uchar code table[]={"0123456789-"};long idata value=1;uchar idata tt[2]; //存tagtypeuchar idata card_snr[4]; //存卡的序列号uchar idata size,ad_stor=0,ad2402=0,num=0;uchar idata bankdata[16]; //块数据缓冲区uchar idata spi_buffer[26]; //SPI数据接收发送缓冲区 uchar idata time[4]; //时间缓冲区uchar idata status[8]; //考勤状态uchar code Nkey_b[6]={ //证实的密码 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF};uchar buf[8]={0,0,10,0,0,10,0,0}; //时间显示缓冲区SYSTEMTIME time1;bit bdata newdata=0;bit tim,FLAG;void spi_init(void); //SPI初始化函数void T0_evaluate(void); //T0载入初值函数void init_zlg500(void); //初始化zlg500函数void delay(void); //延时函数void zlg500_rst(void); //zlg500复位函数uchar request(uchar _Mode,uchar idata *_TagType);//Mifare卡询问操作函数uchar anticoll(uchar _Bcnt,uchar idata *_SNR); //Mifare卡防冲突操作函数uchar select(uchar idata *_SNR,uchar idata *_Size);//Mifare卡选择函数uchar authKey(uchar _Mode,uchar _SecNr,uchar *_Key);//Mifare卡密码验证函数uchar halt(void); //Mifare卡挂起函数uchar read(uchar _Adr,uchar idata *_Data); //Mifare卡块读取函数uchar config(void); //ZLG500配置函数uchar get_info(uchar idata *_Info); //ZLG500序列号读取函数uchar set_cbit(void); //控制位置高电平函数uchar clr_cbit(void); //控制位置低电平函数uchar buzzer(uchar _Frquence,uchar _10ms); //无源蜂鸣器控制函数uchar spi_send(uchar idata *dp,uchar lenght); //SPI数据发送函数uchar spi_rcv(uchar idata *dp); //SPI数据接收函数uchar zlg500cmd(uchar _length); //ZLG500A指令操作函数void Init_DS1302(void); //DS1302初始化void DS1302InputByte(uchar d); //DS1302void Write_1302(uchar ucAddr, uchar ucDa); //DS1302写数据void DS1302_SetProtect(bit flag); //DS1302写保护设定void DS1302_SetTime(uchar Address, uchar Value); //DS1302设置时间函数void DS1302_GetTime(SYSTEMTIME *Time); //DS1302时间转换函数//void DS1302_time(void); //DS1302时间显示函数void Start_bit(void); //I2C起始函数void Stop_bit(void); //I2C停止函数bit Write_8bit(uchar ch); //I2C总线写8位数据函数uchar DS1302OutputByte(void); //DS1302读一个字节uchar Read1302(uchar ucAddr); //DS1302读数据bit Page_wr(uchar firstw_ad,uchar counter,uchar *firstr_ad);//I2C总线页面写函数bit Page_clr(void); //清除EEPROM寄存器内容函数void wr_lcd(uchar dat_comm,uchar content); //串行传输数据void delay1(uint us); //延时void init_lcd(void); //初始化lcdvoid chn_disp(uchar code *chn,uchar j); //显示汉字或字符void chn_disp1(void); //显示串口送入数据void clrram(void); //清DDRAMvoid record(void); //考勤记录函数uchar compare(void); //身份比对函数void ad_2402(void); //存储地址修改函数void disp(void); //显示函数/*************************************************************/main(){ init_zlg500(); //初始化zlg500 Init_DS1302(); //初始化DS1302 spi_init(); //初始化SPI init_lcd(); //初始化LCD while (1) { while (request(IDLE,tt)!=0)disp(); //请求 if (anticoll(0,card_snr)!=0)continue; //防碰撞操作 if (select(card_snr,&size)!=0)continue; //选择卡 if (authKey(KEYA,5,Nkey_b)!=0)continue; //直接密码证实 if (read(1,bankdata)!=0)continue; //读出块值16字节,地址是块20的数据 halt(); //使卡进入HALT状态 clr_cbit(); //清除MIFARE读卡器中的控制位 set_cbit(); //设置MIFARE读卡器中的控制位 record(); //记录考勤信息 buzzer(198,20); //蜂鸣器口输出2KHz方波持续200毫秒 ad_2402(); //修改存储地址 }}/*******************显示函数*****************/void disp(void){ uchar i; DS1302_GetTime(&time1); //获取当前时间 buf[7]=(time1.Second)%10; buf[6]=(time1.Second)/10; buf[4]=(time1.Minute)%10; buf[3]=(time1.Minute)/10; buf[1]=(time1.Hour)%10; buf[0]=(time1.Hour)/10; if(num++==0) { clrram(); //清屏 wr_lcd(comm,0x30); //基本指令动作 wr_lcd(comm,x1); //设定DDRAM地址至10H for (i=0;i<4;i++) { wr_lcd(dat,tab3[i]); //将显示码送入第1行显示 } } wr_lcd(comm,0x30); //基本指令动作 wr_lcd(comm,x4); for (i=0;i<8;i++) { wr_lcd(dat,tab[buf[i]]); //在第四行显示时间 }}/***************存储地址修改函数***************/void ad_2402(void){ DS1302_GetTime(&time1); //获取时间 time[0]=time1.Second; //秒 time[1]=time1.Minute; //分 time[2]=time1.Hour; //时 time[3]=time1.Day; //日 if (((time[3]==1)|(time[3]==16))&(time[0]==1)&(time[1]==0)&(time[2]==0)) { Page_clr(); //1号定时清EEPROM ad_stor=0; //修改存储地址 } if ((time[0]==1)&(time[1]==0)&(time[2]==12)) //12:00:01 { tim=0; //下午考勤 ad_stor+=8; ad2402=ad_stor; //修改存储地址 } else if((time[0]==1)&(time[1]==0)&(time[2]==6)) //06:00:01 { tim=1; //上午考勤 ad_stor+=8; ad2402=ad_stor; //修改存储地址 }}/*******************延时函数********************/void delay(void){ uchar i,j; for (i=255;i>0;i--) for (j=255;j>0;j--); //延时}/*******************身份比对函数****************/uchar compare(void){ uchar n; for (n=0;n<8;n++) { if (tab[n]==bankdata[0]) //对比身份 { if ((status[n]&0x01)==0) { status[n]|=n; //记录工号 return n; } else { return REP; } } } return EER;}/*******************考勤记录函数******************/void record(void){ uchar temp,i; temp=compare(); if (temp==EER) { wr_lcd(comm,0x30); //基本指令动作 wr_lcd(comm,x3); //设定DDRAM地址至10H for (i=0;i<4;i++) { wr_lcd(dat,tab[i]); //将显示码送入第二行显示 } num=255; } if (temp==REP) { wr_lcd(comm,0x30); //基本指令动作 wr_lcd(comm,x3); //设定DDRAM地址至10H for (i=0;i<4;i++) { wr_lcd(dat,tab1[i]); //将显示码送入第二行显示 } num=255; } if (temp<10) { wr_lcd(comm,0x30); //基本指令动作 wr_lcd(comm,x3); //设定DDRAM地址至10H for (i=0;i<4;i++) { wr_lcd(dat,tab2[i]); //将显示码送入第二行显示 } DS1302_GetTime(&time1); //获取访问时间 time[0]=time1.Minute; time[1]=time1.Hour; if(tim==1) { if(time[1]>8) //8点以后上班 { status[temp]|=0x10; //迟到 } else { status[temp]|=0x20; //正常到岗 } } if(tim==0) { if(time[1]>14) //14点以后上班 { status[temp]|=0x10; //迟到 } else { status[temp]|=0x20; //正常到岗 } } while(Page_wr(ad2402,1,time)==0); //等待写入成功 num=255; }}/******************T0载入初值函数********************/void T0_evaluate(void){ TH0=0x4c; //载入初值 TL0=0x00;}/*****************初始化zlg500函数****************/void init_zlg500(void){ zlg500_rst(); //zlg500A复位 while((config())!=MI_OK); //配置RC500 while((get_info(bankdata))!=MI_OK); //读取信息 while((clr_cbit())!=MI_OK); //清除MIFARE读卡器中的控制位 while((set_cbit())!=MI_OK); //设置MIFARE读卡器中的控制位}/******************zlg500A复位函数****************/void zlg500_rst(void){ zlg500_RST=1; //复位 delay(); zlg500_RST=0; delay();}/*****************SPI数据接收函数*****************/uchar spi_rcv(uchar idata *dp){ uchar dat1,i,j; SCLK=0; SDATA=1; //主机响应 while (!SS) { for (i=0;i<8;i++) { SCLK=1; _nop_();_nop_(); dat1<<=1; if (SDATA)dat1=dat1|0x80; _nop_();_nop_(); SCLK=0; } *(dp+j)=dat1; } SDATA=0; return 0;}/*****************SPI初始化函数******************/void spi_init(void){ SS=1; //主机空闲,释放控制线 SDATA=0; //数据线置低 SCLK=0; //时钟线置低 TMOD=0x01; //工作方式为方式1 PT0=1; //T0中断优先级最高 IT0=1; //INT0为下降沿触发方式 ET0=1; //开T0中断 EA=1; //开总中断}/****************SPI数据发送函数*****************/uchar spi_send(uchar idata *dp,uchar lenght){ uchar dat1,j,i=0; FLAG=0; ET0=1; //开T0中断 TR0=1; //启动计时 EX0=0; //关外部INT0中断 SDATA=1; //数据传输开始请求 SCLK=0; while (SDATA); //等待 SS=0; while (!SDATA); //等待从机响应 while ((FLAG!=1)&&(i<lenght)) //连续发送lenght个数据 { dat1=*(dp+i++); for (j=0;j<8;j++) { if ((dat1&0x80)==0x80) SDATA=1; else SDATA=0; _nop_();_nop_();_nop_();_nop_(); SCLK=1; dat1<<=1; _nop_();_nop_();_nop_();_nop_(); SCLK=0; } } SS=1; SDATA=0; TR0=0; if (FLAG==1) return 0xff; else return 0;}/*****************软件看门狗函数*****************/void WDG(void) interrupt 1 //50ms未发送完毕触发中断{ TR0=0; //停止计数 FLAG=1; //置错误标志位}/******************INT0中断函数******************/void spi_int(void) interrupt 0 using 1{ spi_rcv(spi_buffer); //接收数据送入spi_buffer缓冲区 newdata=1; //newdata置1}/**************ZLG500A指令操作函数***************/uchar zlg500cmd(uchar _length){ uchar spi_wdg=10; //软件计时器置数 uchar i,BCC_sum; spi_buffer[_length]=spi_buffer[0]; //发送BCC校验码计算 for (i=1;i<_length;i++) { spi_buffer[_length]^=spi_buffer[i]; } spi_buffer[_length]=~spi_buffer[_length]; T0_evaluate(); //装载T0初值 if (spi_send(spi_buffer,_length+1)!=0) //若发送失败,返回0xff return 255;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -