门禁系统项目驱动程序
2015-07-06 来源:51hei
门禁系统项目驱动程序
(1)晶振 11.0592MHZ
(2)芯片 DS1302,AT24C64,HEF4053BP
(3)ZIMO21.EXE纵向、字节倒序取字模
(4)完整代码下载(包含头文件):http://www.51hei.com/f/12154f.rar
*****************************************************************************/
#include 'reg51.h'
#include 'intrins.h'
#include '7041_Door.h' //字模
#define LCD_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{ //定义EEPROM地址
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,NSK12Flag = 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 RST_1302 = P2^0;
sbit RS_485 = P3^2; //485R/S,其为1时允许发送,为0时允许接收
sbit CON_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;
else RData &= 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_DisWord(70,4,zhuang);
LCD_Data_DisWord(82,4,tai);
}
void LCD_Display2(){ //刷卡后显示此卡有效或无效
LCD_Data_DisWord(2,4,ka); //显示刷卡后的卡号
LCD_Data_DisWord(14,4,hao);
LCD_Data_DisNum(26,4,maohao);
}
void LCD_Display3(){ //显示电机状态:打开或关闭
//LCD_DisCell(); //显示固定不变的内容
LCD_Data_DisWord(2,4,dian); //电机状态
LCD_Data_DisWord(14,4,ji);
LCD_Data_DisWord(26,4,zhuang);
LCD_Data_DisWord(38,4,tai);
LCD_Data_DisNum(50,4,maohao);
}
void LCD_Display4(){ //显示数据上传过程:上传成功或失败
LCD_Data_DisWord(2,4,shu); //数据上传
LCD_Data_DisWord(14,4,ju);
LCD_Data_DisWord(26,4,shang);
LCD_Data_DisWord(38,4,chuan);
LCD_Data_DisNum(50,4,maohao);
LCD_Data_DisWord(56,4,kuang1);
LCD_Data_DisWord(68,4,kuang1);
LCD_Data_DisWord(80,4,kuang1);
LCD_Data_DisWord(92,4,kuang1);
LCD_Data_DisWord(104,4,kuang1);
LCD_Data_DisWord(116,4,kuang1);
LCD_Data_DisWord(35,6,cheng);
LCD_Data_DisWord(47,6,gong);
LCD_Data_DisWord(75,6,shibai);
LCD_Data_DisWord(87,6,bai);
}
void LCD_Display5(){ //显示存卡过程:存入或取消存储
LCD_Data_DisWord(2,0,cun); //存卡
LCD_Data_DisWord(14,0,ka);
LCD_Data_DisWord(2,2,ka); //卡号
LCD_Data_DisWord(14,2,hao);
LCD_Data_DisNum(26,2,maohao);
}
void LCD_Display6(){ //显示卡号删除过程:确认删除或取消删除
LCD_Data_DisWord(2,0,liu); //浏览卡号
LCD_Data_DisWord(14,0,lan);
LCD_Data_DisWord(26,0,ka);
LCD_Data_DisWord(38,0,hao);
LCD_Data_DisWord(2,2,ka); //卡号显示
LCD_Data_DisWord(14,2,hao);
LCD_Data_DisNum(26,2,maohao);
LCD_Data_DisWord(35,4,shan);
LCD_Data_DisWord(47,4,chu);
LCD_Data_DisWord(75,4,qu);
LCD_Data_DisWord(87,4,quxiao);
}
/******************************AT24C64存储程序*******************************/
void I2C_Start(void){ //I2C总线启动
SCL_24C64 = 1;
_nop_();
SDA_24C64 = 1;
_nop_();
SDA_24C64 = 0;
}
void I2C_Stop(void){ //I2C总线通信结束
SCL_24C64 = 0;
SDA_24C64 = 0;
_nop_();
SCL_24C64 = 1;
SDA_24C64 = 1;
}
void I2C_ACK_Send(bit ack){//发送返回帧
SDA_24C64 = ack;
SCL_24C64 = 1;
_nop_();
SCL_24C64 = 0;
SDA_24C64 = 1; //释放总线
}
bit I2C_ACK_Receive(){//接收返回帧
bit ACKR;
SDA_24C64 = 1; //释放总线
SCL_24C64 = 1;
_nop_();
ACKR = SDA_24C64;
SCL_24C64 = 0;
return ACKR;
}
void I2C_SendByte(uchar WData){ //写入一个字节的数据
uchar Count;
SCL_24C64 = 0;
for(Count = 0;Count < 8;Count ++){
WData <<= 1;
SDA_24C64 = CY;
SCL_24C64 = 1; //下降沿写入数据
_nop_();
SCL_24C64 = 0;
}
}
uchar I2C_ReceiveByte(){ //读出一个字节的数据
uchar Count,RData;
SCL_24C64 = 0;
for(Count = 0;Count < 8;Count ++){
RData <<= 1;
SCL_24C64 = 1; //高电平读出数据
_nop_();
if(SDA_24C64)
RData |= 0x01;
else RData &= 0xfe;
SCL_24C64 = 0;
}
return RData;
}
void I2C_Write_AT24C64(uchar WAddrH,uchar WAddrL,uchar *Point,uchar WNum){//向WAddrH,WAddrL为首地址的页中写入WNum个字节
bit ACK;uchar Cnt;
I2C_Start(); //启动通信
do{
I2C_SendByte(0xa0); //AT24C64的写地址
ACK = I2C_ACK_Receive();
}while(ACK);
do{
I2C_SendByte(WAddrH); //写字节高地址
ACK = I2C_ACK_Receive();
}while(ACK);
do{
I2C_SendByte(WAddrL); //写字节低地址
ACK = I2C_ACK_Receive();
}while(ACK);
for(Cnt = 0;Cnt < WNum;Cnt ++,Point ++){ //循环写入WNum个字节
do{
I2C_SendByte(*Point); //写的内容
ACK = I2C_ACK_Receive();
}while(ACK);
}
I2C_Stop(); //通信结束
}
uchar I2C_Read_AT24C64(uchar WAddrH,uchar WAddrL,uchar RNum){ //从WAddrH,WAddrL为首地址的页中读取RNum个字节
uchar Cnt; //一页最多32个字节
bit ACK;
I2C_Start(); //启动通信
do{
I2C_SendByte(0xa0);//AT24C64的写地址
ACK = I2C_ACK_Receive();
}while(ACK);
do{
I2C_SendByte(WAddrH); //写入地址的高5位
ACK = I2C_ACK_Receive();
}while(ACK);
do{
I2C_SendByte(WAddrL); //写入地址的低8位
ACK = I2C_ACK_Receive();
}while(ACK);
I2C_Start(); //再次启动通信
do{
I2C_SendByte(0xa1); //AT24C64的读地址
ACK = I2C_ACK_Receive();
}while(ACK);
for(Cnt = 0;Cnt < RNum;Cnt ++){ //循环读取RNum个字节
RD24C64[Cnt] = I2C_ReceiveByte();
if(Cnt != RNum - 1)
I2C_ACK_Send(0);
}
I2C_ACK_Send(1); //读取最后一个字节的数据后的返回帧
I2C_Stop(); //通信结束
}
void AT24C64Init(){ //24C64初始化
//I2C_Write_AT24C64(0x00,0x1f,&CardMax,1); //将存储卡的最大数目初始化为0
//I2C_Write_AT24C64(0x00,0x1e,&CardNum,1); //将存储卡的数目初始化为0
I2C_Read_AT24C64(0x00,0x1f,1); //读取0x00,0x1f地址中的内容,其为存储卡过程中曾存卡的最多个数
CardMax = RD24C64[0]; //将读取的数据存入卡数目最大值变量CardMax中
I2C_Read_AT24C64(0x00,0x1e,1); //读取0x00,0x1e地址中的内容,其为存储卡的数目
CardNum = RD24C64[0]; //将读取的数据存入卡数目变量CardNum中
EEAddr = 0x0000; //将24C64的地址初始化到首地址
}
/******************************按键控制程序*********************************/
void KeyScan(){ //按键扫描
if(!KEY1){
DelCount = 0;
while(DelCount < 2);
if(!KEY1){
while(!KEY1);
Function = 1;
}
}
if(!KEY2){
DelCount = 0;
while(DelCount < 2);
if(!KEY2){
while(!KEY2);
Function = 2;
}
}
if(!KEY3){
DelCount = 0;
while(DelCount < 2);
if(!KEY3){
while(!KEY3);
Function = 3;
}
}
if(!KEY4){
DelCount = 0;
while(DelCount < 2);
if(!KEY4){
while(!KEY4);
Function = 4;
}
}
}
void KeyFunc(){ //按键功能分配
uchar Cnt = 0;
bit CFlag = 0; //待存入的卡与EEPROM中的卡号比较标志位
switch(Function){ //具体按键功能分配程序
case 1: if(!SwitchFlag){//切换标志位,用于存卡及浏览卡号时上翻
TimeDisFlag = 1;//存储卡号期间主函数运行时不再显示时间
KEndFlag = 0; //确认在进入存卡系统后刷卡有效,否则无效
WXFlag = 1; //按下KEY1后,接着按key2无效
StoreFlag = 1; //存储标志位,0为无效,1为存储
LCD_All_Clear(); //清全屏
LCD_Display5(); //显示存卡界面
while(!KEndFlag);//等待刷卡后读取卡信息结束
KEndFlag = 0; //确认在进入存卡系统后刷卡有效,否则无效
for(Cnt = 1;Cnt < 11;Cnt ++){ //显示读取的卡号
if(CardNo[Cnt] >= 0x40)
LCD_Data_DisNum(32 + Cnt * 6,2,num[CardNo[Cnt]-0x40+10]);
else LCD_Data_DisNum(32 + Cnt * 6,2,num[CardNo[Cnt]-0x30]);
}
LCD_Data_DisWord(35,4,cun); //显示汉字“存入”“取消”
LCD_Data_DisWord(47,4,ru);
LCD_Data_DisWord(75,4,qu);
LCD_Data_DisWord(87,4,quxiao);
}
if(SwitchFlag){ //浏览卡号时上翻功能
if(!NSK12Flag){
while(1){
if(EEAddr == 0x0000)
EEAddr = 0x0000 + (CardMax - 1) * 0x20;
else EEAddr -= 0x20; //24C64存储时一页存储一张卡号
I2C_Read_AT24C64(EAddrH,EAddrL,12); //读取24C64中存储的卡号
if(RD24C64[0] == 1){ //从24C64EEAddr地址中读取的卡号有效
for(Cnt = 2;Cnt < 12;Cnt ++){ //显示读取的卡号
if(RD24C64[Cnt] >= 0x40)
LCD_Data_DisNum(32 + (Cnt - 1) * 6,2,num[RD24C64[Cnt]-0x40+10]);
else LCD_Data_DisNum(32 + (Cnt - 1) * 6,2,num[RD24C64[Cnt]-0x30]);
}
break; //显示一个有效的卡号后退出
}
}
}
}
break;
case 2: if(!WXFlag){
if(SwitchFlag){ //浏览卡号时下翻功能
if(!NSK12Flag){
while(1){
EEAddr += 0x20; //往下翻页
if(EEAddr == 0x0000 + CardMax * 0x20)
EEAddr = 0x0000;
I2C_Read_AT24C64(EAddrH,EAddrL,12);
if(RD24C64[0] == 1){ //读取的卡号有效
for(Cnt = 2;Cnt < 12;Cnt ++){ //显示读取的卡号
if(RD24C64[Cnt] >= 0x40)
LCD_Data_DisNum(32 + (Cnt - 1) * 6,2,num[RD24C64[Cnt]-0x40+10]);
else LCD_Data_DisNum(32 + (Cnt - 1) * 6,2,num[RD24C64[Cnt]-0x30]);
}
break;
}
}
}
}
if(!SwitchFlag){ //删除卡号
TimeDisFlag = 1;//删除卡号期间主函数运行时不再显示时间
DeleteFlag = 1; //删除标志位,0为无效,1为存储
SwitchFlag = 1;
LCD_All_Clear(); //清全屏
I2C_Read_AT24C64(0x00,0x1e,1);
CardNum = RD24C64[0];
if(CardNum == 0)NSK12Flag = 1;
for(EEAddr = 0x0000;EEAddr < 0x0000 + CardMax * 0x20;EEAddr += 0x20){//读出卡号和存储器中的卡号进行比较
I2C_Read_AT24C64(EAddrH,EAddrL,12);
if(RD24C64[0] == 1){
for(Cnt = 2;Cnt < 12;Cnt ++){ //显示读取的卡号
if(RD24C64[Cnt] >= 0x40)
LCD_Data_DisNum(32 + (Cnt - 1) * 6,2,num[RD24C64[Cnt]-0x40+10]);
else LCD_Data_DisNum(32 + (Cnt - 1) * 6,2,num[RD24C64[Cnt]-0x30]);
}
break;
}
}
LCD_Display6(); //显示存卡界面
}
}
break;
case 3: if(StoreFlag){ //存储卡号
Cnt = 0;
for(EEAddr = 0x0000;EEAddr < 0x0000 + CardMax * 0x20;EEAddr += 0x20){//读出卡号和存储器中的卡号进行比较
I2C_Read_AT24C64(EAddrH,EAddrL,12);
if(RD24C64[0] == 1){
for(Cnt = 0;Cnt < 11;Cnt ++){ //11位卡号进行比较
if(CardNo[Cnt] != RD24C64[Cnt + 1]) //比较过程中有不相等的就读下一内存
break;
}
}
if(Cnt == 11){ //一组数据比较过程中全部相等时,此卡已存在
CFlag = 1;
LCD_Page_Clear(4);//清除4,5页的显示内容
LCD_Data_DisWord(34,4,ci); //显示“此卡已存在”
LCD_Data_DisWord(46,4,ka);
LCD_Data_DisWord(58,4,yi);
LCD_Data_DisWord(70,4,cun);
LCD_Data_DisWord(82,4,zai);
break;
}
}
if(!CFlag){
I2C_Read_AT24C64(0x00,0x1e,1);
CardNum = RD24C64[0];
I2C_Read_AT24C64(0x00,0x1f,1);
CardMax = RD24C64[0];
if(CardNum == CardMax){ //往后边空间存储
EEAddr = 0x0000 + CardMax * 0x20;
I2C_Write_AT24C64(EAddrH,EAddrL,&Sto,1);//存入标志位,表示此页已存入卡号
DelCount = 0; //延时10ms
while(DelCount < 2);
I2C_Write_AT24C64(EAddrH,EAddrL + 1,CardNo,11); //存入11位卡号
DelCount = 0; //延时10ms
while(DelCount < 2);
CardMax ++;
CardNum ++;
I2C_Write_AT24C64(0x00,0x1f,&CardMax,1);
DelCount = 0; //延时10ms
while(DelCount < 2);
I2C_Write_AT24C64(0x00,0x1e,&CardNum,1);
}
else if(CardMax > CardNum){ //在CardMax范围内找空间存储
for(EEAddr = 0x0000;EEAddr < 0x0000 + CardMax * 0x20;EEAddr += 0x20){//读出卡号和存储器中的卡号进行比较
I2C_Read_AT24C64(EAddrH,EAddrL,12);
if(RD24C64[0] == 0){
I2C_Write_AT24C64(EAddrH,EAddrL,&Sto,1);//存入标志位,表示此页已存入卡号
DelCount = 0; //延时10ms
while(DelCount < 2);
I2C_Write_AT24C64(EAddrH,EAddrL + 1,CardNo,11); //存入11位卡号
CardNum ++;
DelCount = 0; //延时10ms
while(DelCount < 2);
I2C_Write_AT24C64(0x00,0x1e,&CardNum,1);
break;
}
}
}
LCD_Page_Clear(4);//清除4,5页的显示内容
LCD_Data_DisWord(34,4,cun); //显示“存入成功”
LCD_Data_DisWord(46,4,ru);
LCD_Data_DisWord(58,4,cheng);
LCD_Data_DisWord(70,4,gong);
}
DelCount = 0; //延时2s
StoreFlag = 0;
TimeDisFlag = 0;//返回后继续显示时间,时间显示标志为清零
while(DelCount < 400);
LCD_All_Clear(); //清全屏
}
if(DeleteFlag){ //删除
I2C_Read_AT24C64(0x00,0x1e,1);
CardNum = RD24C64[0];
if(CardNum != 0){
I2C_Write_AT24C64(EAddrH,EAddrL,&Del,1);
DelCount = 0; //延时10ms
while(DelCount < 2);
CardNum --; //删除一张卡后卡的数量减1
I2C_Write_AT24C64(0x00,0x1e,&CardNum,1);//存入标志位,表示此页已存入卡号
LCD_Page_Clear(4);//清除4,5页的显示内容
LCD_Data_DisWord(34,4,shan); //显示“删除成功”
LCD_Data_DisWord(46,4,chu);
LCD_Data_DisWord(58,4,cheng);
LCD_Data_DisWord(70,4,gong);
DelCount = 0; //延时2s
while(DelCount < 400);
}
DeleteFlag = 0;
SwitchFlag = 0;
TimeDisFlag = 0;//返回后继续显示时间,时间显示标志为清零
LCD_All_Clear(); //清全屏
}
NSK12Flag = 0;
WXFlag = 0;
break;
case 4: if(StoreFlag || DeleteFlag){
TimeDisFlag = 0;//推出存储或删除,显示时间
StoreFlag = 0;
WXFlag = 0;
DeleteFlag = 0;
NSK12Flag = 0;
SwitchFlag = 0;
LCD_All_Clear(); //清全屏
}
break;
default:break;
}
Function = 0;
}
void TimeInit(void){ //定时器,串口初始化(定时器1作为波特率发生器[9600BPS],定时器0作为程序中的延时)
TMOD = 0x21; //定时器0,工作方式1,定时器1,工作方式2
TH0 = 0xec; //定时器赋初值:5ms
TL0 = 0x78;
TR0 = 1; //启动定时器0
ET0 = 1; //开定时器0中断
TH1 = 0xfd; //波特率发生器:9600BPS
TL1 = 0xfd;
TR1 = 1;
SCON = 0x50; //串行工作方式1,允许接收
PCON = 0x00; //SMOD = 0
ES = 1; //开串行通信中断
EA = 1; //开中断总开关
}
/***************************主程序******************************/
main(){
uchar Cnt;
bit ComFlag = 0;
CON_4053 = 1;//允许读卡
Motor1 = 1; //电机正转停止
Motor2 = 1; //电机反转停止
TimeInit(); //定时器,串口初始化
LCD_Reset(); //液晶屏初始化设置
LCD_All_Clear(); //清全屏
DS1302_SetTime(); //1302设置初始时间
AT24C64Init(); //24C64初始化
while(1){
if(!TimeDisFlag){
LCD_Display1();
LCD_DisTime();
}
KeyScan(); //按键扫描
KeyFunc(); //按键功能分配
if(KEndFlag){ //卡号接收完毕
//KEndFlag = 0;
LCD_Page_Clear(4);//清除4,5页的显示内容
LCD_Display2();
for(Cnt = 1;Cnt < 11;Cnt ++){ //显示读取的卡号
if(CardNo[Cnt] >= 0x40)
LCD_Data_DisNum(32 + Cnt * 6,4,num[CardNo[Cnt]-0x40+10]);
else LCD_Data_DisNum(32 + Cnt * 6,4,num[CardNo[Cnt]-0x30]);
}
Cnt = 0;//显示卡号后Cnt已经是11,故先清零,以便下边比较卡号时使用Cnt == 11
for(EEAddr = 0x0000;EEAddr < 0x0000 + CardMax * 0x20;EEAddr += 0x20){//读出卡号和存储器中的卡号进行比较
I2C_Read_AT24C64(EAddrH,EAddrL,12);
if(RD24C64[0] == 1){
for(Cnt = 0;Cnt < 11;Cnt ++){ //11位卡号进行比较
if(CardNo[Cnt] != RD24C64[Cnt + 1]) //比较过程中有不相等的就读下一内存
break;
}
}
if(Cnt == 11){ //一组数据比较过程中全部相等时,显示有效并推出比较
ComFlag = 1;//比较后的卡号相同
LCD_Data_DisWord(70,6,you); //显示“有效”
LCD_Data_DisWord(82,6,xiao);
DelCount = 0; //延时100ms
while(DelCount < 20);
LCD_Page_Clear(4);//清除4,5页的显示内容
LCD_Page_Clear(6);//清除6,7页的显示内容
break;
}
}
LCD_DisTime(); //若比较卡号时耗时较长,及时读取时间显示
if(!ComFlag){ //比较无此卡号时显示“无效”
LCD_Data_DisWord(100,6,wu);
LCD_Data_DisWord(112,6,xiao);
DelCount = 0;
while(1){
LCD_DisTime(); //读取时间显示
if(DelCount > 400){
LCD_Page_Clear(4);//清除4,5页的显示内容
LCD_Page_Clear(6);//清除6,7页的显示内容
break;
}
}
}
if(ComFlag){
LCD_Display3();
LCD_Data_DisWord(60,4,da);
LCD_Data_DisWord(72,4,kai);
Motor1 = 0; //电机正转
DelCount = 0;
while(1){ //电机正转中
LCD_DisTime(); //时间显示
if(DelCount > 600)
break;
}
Motor1 = 1; //电机正转停止
LCD_Data_DisWord(60,4,guan);
LCD_Data_DisWord(72,4,bi);
DelCount = 0;
while(1){ //等待人过去
LCD_DisTime(); //时间显示
if(DelCount > 600)
break;
}
Motor2 = 0; //电机反转
LCD_Data_DisWord(60,4,da);
LCD_Data_DisWord(72,4,kai);
DelCount = 0;
while(1){ //电机反转中
LCD_DisTime(); //时间显示
if(DelCount > 600)
break;
}
Motor2 = 1; //电机反转停止
DelCount = 0;
LCD_Data_DisWord(60,4,guan);
LCD_Data_DisWord(72,4,bi);
while(1){ //门关上上后延时2s
LCD_DisTime(); //时间显示
if(DelCount > 400)
break;
}
LCD_Page_Clear(4);
LCD_Page_Clear(6);
}
ComFlag = 0;
KEndFlag = 0;
}
}
}
void Serial() interrupt 4{ //串行中断入口地址
if(RI){
CardNo[SCount] = SBUF;
RI = 0;
SCount ++;
if(SCount == 14){
KEndFlag = 1;
SCount = 0;
}
}
}
void Time0() interrupt 1{ //定时器0入口地址
TH0 = 0xec; // 5ms
TL0 = 0x78;
DelCount ++;
}
下一篇:基于单片机的便携数字存储示波器
- 关于GD32F150R8的智能门禁系统的性能分析
- 基于NXP LPC11的PKE 汽车无钥匙门禁系统解决方案
- 一套完整的无线门禁系统解决方案
- 指纹识别系统电路设计图集锦 —电路图天天读(200)
- 索斯科推出KEYPANION(TM) 应用程序的无线门禁系统
- 基于STM32+RC522设计的门禁系统
- 基于AT89C2051单片机的门禁系统设计
- 英飞凌与Sentry Enterprises合作,推动生物识别门禁控制系统和加密冷存储钱包平台的发展
- 大联大世平集团推出基于耐能Kneron产品的3D AI人脸识别门禁系统方案
- 基于STM32F103+AS608指纹模块+4X4矩阵按键+SIM900A发短信——智能门禁卡系统