/***************************************************************************** 门禁系统项目驱动程序
(1)晶振 11.0592MHZ (2)芯片 DS1302,AT24C64,HEF4053BP (3)Z21.EXE纵向、字节倒序取字模 (4)完整代码下载(包含头文件):http://www.51hei.com/f/12154f.rar *****************************************************************************/ #include "reg51.h" #include "intrins.h" #include "7041_Door.h"//字模
#define _DATA P1//液晶屏数据输入 #define EEAddr EAddr.All//AT24C64片内地址 #define EAddrH EAddr.array[0] #define EAddrL EAddr.array[1]
#define uchar unsigned char #define uint unsigned int
union Add{ //定义地址 uint All; uchar array[2]; }EAddr;
uchar Sto = 1,Del = 0; uint DelCount;//定时器中断中用于延时的变量DelCount uchar Function = 0;//按键功能变量Function uchar SCount = 0;//串行中断中用于计数卡号信息的循环变量 bit TimeDisFlag = 0,KEndFlag = 0,StoreFlag = 0,DeleteFlag = 0,SwitchFlag = 0,WXFlag = 0,12Flag = 0;//控制时间显示标志位TimeDisFlag,14位卡号接收完的标志KEndFlag uchar CardNo[14] = {0},GetTime[7],RD24C64[32] = 0,CardMax = 0,CardNum = 0;//存储读到的卡号CardNo[14],存储从1302读到的时间GetTime[7],存入卡的个数CardMax
/*---------------------------------定义P口-----------------------------------*/
sbit LCD_RS = P2^7; //LCD12864 sbit LCD_RW = P2^6; sbit LCD_E = P2^5; sbit LCD_CS1 = P2^4; sbit LCD_CS2 = P2^3; sbit Busy = P1^7; sbit Motor2 = P3^7; sbit Motor1 = P3^6; sbit SDA_24C64 = P3^5;//AT24C64 sbit SCL_24C64 = P3^4; sbit CLK_1302 = P2^2;//DS1302 sbit IO_1302 = P2^1; sbit R_1302 = P2^0; sbit RS_485 = P3^2;//485R/S,其为1时允许发送,为0时允许接收 sbit C_4053 = P3^3;//通信控制,其为1时读卡,为0时485通信 sbit KEY1 = P0^0;//定义按键 sbit KEY2 = P0^1; sbit KEY3 = P0^2; sbit KEY4 = P0^3;
/***************************液晶屏驱动程序*********************************/
void LCD_BusyCheck(bit BCS){//检测忙子程序 LCD_DATA = 0xff;//LCD_RS = 0,LCD_RW = 1,LCD_E = 高电平。 LCD_RS = 0; LCD_RW = 1; if(BCS){//检测片1忙状态 LCD_CS1 = 1; LCD_E = 1; while(Busy); LCD_E = 0; LCD_CS1 = 0; } else{//检测片2忙状态 LCD_CS2 = 1; LCD_E = 1; while(Busy); LCD_E = 0; LCD_CS2 = 0; } } void LCD_Write_Code(uchar WCode,bit CS){//写指令子程序 LCD_BusyCheck(CS);//调用忙检测子程序:写前检测 LCD_DATA = WCode; LCD_RS = 0;//LCD_RS = 0,LCD_RW = 0,LCD_E = 高脉冲。 LCD_RW = 0; if(CS){//检测片1忙状态 LCD_CS1 = 1; LCD_E = 1; _nop_(); LCD_E = 0; LCD_CS1 = 0; } else{//检测片2忙状态 LCD_CS2 = 1; LCD_E = 1; _nop_(); LCD_E = 0; LCD_CS2 = 0; } } void LCD_Write_Data(uchar WData,uchar CS){//写数据子程序 LCD_BusyCheck(CS);//调用忙检测子程序:写前忙状态检测 LCD_DATA = WData; LCD_RS = 1;//LCD_RS = 1,LCD_RW = 0,LCD_E = 高脉冲。 LCD_RW = 0; if(CS){//检测片1忙状态 LCD_CS1 = 1; LCD_E = 1; _nop_(); LCD_E = 0; LCD_CS1 = 0; } else{//检测片2忙状态 LCD_CS2 = 1; LCD_E = 1; _nop_(); LCD_E = 0; LCD_CS2 = 0; } } void LCD_Write(uchar xpos,uchar ypos,uchar WData){//写屏子(地址转换)程序 uchar WCS; if(xpos < 64)WCS = 1;//判断将要操作片1或片2:WCS = 1操作LCD_CS1 else WCS = 0;//WCS = 2 操作LCD_CS2 ypos &= 0x07;//页地址转换 ypos |= 0xb8; LCD_Write_Code(ypos,WCS);//写入页地址到对应片 xpos &= 0x3f;//列地址转换 xpos |= 0x40; LCD_Write_Code(xpos,WCS);//写入列地址到对应片 LCD_Write_Data(WData,WCS);//写入数据到对应片 } void LCD_Data_DisWord(uchar xpos,uchar ypos,uchar array[]){//汉字显示子程序:12*16 uchar Cnt = 0,x = 0,y = 0; for(y = ypos;y < ypos + 2;y ++){ for(x = xpos;x < xpos + 12;x ++,Cnt ++) LCD_Write(x,y,array[Cnt]);//调用写屏子程序:在对应的地址上写入要显示的内容 } } void LCD_Data_DisNum(uchar xpos,uchar ypos,uchar array[]){//数字及符号显示子程序:6*16 uchar Cnt = 0,x = 0,y = 0; for(y = ypos;y < ypos + 2;y ++){ for(x = xpos;x < xpos + 6;x ++,Cnt ++) LCD_Write(x,y,array[Cnt]);//调用写屏子程序:在对应的地址上写入要显示的内容 } } void LCD_All_Clear(void){//清屏子程序:全屏清0 uchar x,y; for(y = 0;y < 8;y ++) for(x = 0;x < 128;x ++) LCD_Write(x,y,0x00);//调用写屏子程序:全屏写0 } void LCD_Page_Clear(uchar yPage){//清屏子程序:清除以所给页坐标为起始的两页的内容 uchar x,y; for(y = yPage;y < yPage + 2;y ++) for(x = 0;x < 128;x ++) LCD_Write(x,y,0x00);//调用写屏子程序:以所给页坐标为起始的两页写0 } void LCD_Reset(void){//液晶屏初始化设置 LCD_E = 0; LCD_Write_Code(0x3f,1);//开片1显示 LCD_Write_Code(0x3f,0);//开片2显示 LCD_Write_Code(0xc0,1);//设片1起始行显示 LCD_Write_Code(0xc0,0);//设片2起始行显示 }
/******************************DS1302时钟程序*******************************/
void DS1302_WriteByte(uchar WData){ //写入一个字节 uchar Cnt; for(Cnt=0;Cnt<8;Cnt++){ WData >>= 1;//写入数据时先写低位再写高位(D0---D7) CLK_1302 = 0; IO_1302 = CY; CLK_1302 = 1; //上升沿将数据写入1302 } } uchar DS1302_ReadByte(){ //读出一个字节 uchar Cnt,RData = 0; for(Cnt = 0;Cnt < 8;Cnt ++){ RData >>= 1;//读数据时先读低位再读高位(D0---D7) CLK_1302 = 1; CLK_1302 = 0; //下降沿将数据读出来 if(IO_1302) RData |= 0x80; elseRData &= 0x7f; } return RData; } void DS1302_WriteData(uchar Waddr,uchar Wdata){ //向某地址中写入一个字节的数据 RST_1302 = 0; CLK_1302 = 0; RST_1302 = 1; DS1302_WriteByte(Waddr);//写入地址 DS1302_WriteByte(Wdata);//写入数据 CLK_1302 = 0; RST_1302 = 0; } uchar DS1302_ReadData(uchar RAddr){ //读取1302某地址中一个字节的数据 uchar Rdata; RST_1302 = 0; CLK_1302 = 0; RST_1302 = 1; DS1302_WriteByte(RAddr);//写入读取数据的地址 Rdata = DS1302_ReadByte();//读取数据 RST_1302 = 0; IO_1302 = 1; return(Rdata); } void DS1302_SetTime(){ //设置1302时间 uchar Cnt,Add = 0x80;//秒 寄存器的写地址0x80 // 秒 分 时 日 月 星期 年 uchar STime[7] = {0x00,0x19,0x14,0x18,0x07,5,0x08};
DS1302_WriteData(0x8e,0x00);//禁止写保护(可写入数据) for(Cnt = 0;Cnt < 7;Cnt ++,Add += 2)//循环写入秒,分,时,日,月,星期,年 DS1302_WriteData(Add,STime[Cnt]); DS1302_WriteData(0x8e,0x80);//写保护(不能写入数据) } void DS1302_GetTime(){ //读取1302中当前时间 uchar Cnt,Addr = 0x81;//秒 寄存器的读地址0x81 for(Cnt = 0;Cnt < 7;Cnt ++,Addr += 2)//循环读取秒,分,时,日,月,星期,年 GetTime[Cnt] = DS1302_ReadData(Addr); }
/**************************液晶屏显示程序******************************/
void LCD_DisTime(){//显示从1302读取的时间 DS1302_GetTime(); LCD_Data_DisNum(32,0,num[GetTime[6] >> 4]);//年(由1302循环读出显示) LCD_Data_DisNum(38,0,num[GetTime[6] & 0x0f]); LCD_Data_DisNum(50,0,num[GetTime[4] >> 4]);//月 LCD_Data_DisNum(56,0,num[GetTime[4] & 0x0f]); LCD_Data_DisNum(68,0,num[GetTime[3] >> 4]);//日 LCD_Data_DisNum(74,0,num[GetTime[3] & 0x0f]); LCD_Data_DisNum(122,0,num[GetTime[5]]);//星期 LCD_Data_DisNum(32,2,num[GetTime[2] >> 4]);//时 LCD_Data_DisNum(38,2,num[GetTime[2] & 0x0f]); LCD_Data_DisNum(50,2,num[GetTime[1] >> 4]);//分 LCD_Data_DisNum(56,2,num[GetTime[1] & 0x0f]); LCD_Data_DisNum(68,2,num[GetTime[0] >> 4]);//秒 LCD_Data_DisNum(74,2,num[GetTime[0] & 0x0f]); } void LCD_DisCell(){//显示固定不变的内容(日期,时间等汉字及符号的显示)(图1~4) LCD_Data_DisWord(2,0,ri); LCD_Data_DisWord(14,0,qi); LCD_Data_DisNum(26,0,maohao); LCD_Data_DisNum(44,0,heng); LCD_Data_DisNum(62,0,heng); LCD_Data_DisWord(92,0,xing); LCD_Data_DisWord(104,0,qi); LCD_Data_DisNum(116,0,maohao); LCD_Data_DisWord(2,2,shi); LCD_Data_DisWord(14,2,jian); LCD_Data_DisNum(26,2,maohao); LCD_Data_DisNum(44,2,heng); LCD_Data_DisNum(62,2,heng); } void LCD_Display1(){//无操作状态时显示内容 LCD_DisCell(); LCD_Data_DisWord(34,4,wu);//无操作状态 LCD_Data_DisWord(46,4,cao); LCD_Data_DisWord(58,4,zuo); LCD_Data_Di