我按照这个程序做出来的,总是输入密码错误,不知道是啥问题,麻烦大神帮看看是啥问题。
#include <reg52.h> #include <intrins.h> #define uchar unsigned char // 以后unsigned char就可以用uchar代替 #define uint unsigned int // 以后unsigned int 就可以用uint 代 sbit SDA_P = P2^1; // 定义了AT24C02的SCL引脚 sbit SCL_P = P2^0; // 定义了AT24C02的SDA引脚 sbit LcdEn_P = P2^5; // 1602液晶的EN管脚 sbit LcdRw_P = P2^6; // 1602液晶的RW管脚 sbit LcdRs_P = P2^7; // 1602液晶的RS管脚 sbit Beep_P = P3^3; // 蜂鸣器引脚 sbit Relay_P = P3^2; // 继电器引脚 uchar ArrCodeBuff[6]; // 密码输入缓冲区 uchar ArrCodeUnlock[6]; // 解锁密码 uchar ArrCodeTemp[6]; // 临时数组(修改密码时会用到) uchar ArrCodeAdmin[6]={1,2,3,1,2,3}; // 管理员密码 uchar row,column; // 液晶的当前行列坐标 uchar inputNum=0; // 输入的密码位数 uchar inputMode=1; // =1输入解锁密码,=2输入修改密码1,=3输入解锁密码2 uchar errTime=0; // 密码输入错误的次数 /*********************************************************/ // 毫秒级的延时函数,time是要延时的毫秒数 /*********************************************************/ void DelayMs(uint time) { uint i,j; for(i=0;i<time;i++) for(j=0;j<112;j++); } /*********************************************************/ // 延时6微秒 /*********************************************************/ void Delay6us() { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } /*********************************************************/ // 1602液晶写命令函数,cmd就是要写入的命令 /*********************************************************/ void LcdWriteCmd(uchar cmd) { LcdRs_P = 0; LcdRw_P = 0; LcdEn_P = 0; P0=cmd; DelayMs(2); LcdEn_P = 1; DelayMs(2); LcdEn_P = 0; } /*********************************************************/ // 1602液晶写数据函数,dat就是要写入的数据 /*********************************************************/ void LcdWriteData(uchar dat) { LcdRs_P = 1; LcdRw_P = 0; LcdEn_P = 0; P0=dat; DelayMs(2); LcdEn_P = 1; DelayMs(2); LcdEn_P = 0; } /*********************************************************/ // 1602液晶初始化函数 /*********************************************************/ void LcdInit() { LcdWriteCmd(0x38); // 16*2显示,5*7点阵,8位数据口 LcdWriteCmd(0x0C); // 开显示,不显示光标 LcdWriteCmd(0x06); // 地址加1,当写入数据后光标右移 LcdWriteCmd(0x01); // 清屏 } /*********************************************************/ // 液晶光标定位函数 /*********************************************************/ void LcdGotoXY(uchar y, uchar x) { // 第一行 if(y==0) LcdWriteCmd(0x80+x); // 第二行 if(y==1) LcdWriteCmd(0x80+0x40+x); row=y; column=x; } /*********************************************************/ // 液晶输出字符串函数 /*********************************************************/ void LcdPrintStr(uchar *str) { while(*str!='\0') LcdWriteData(*str++); } /*********************************************************/ // IIC起始函数 /*********************************************************/ void IIcStart() { SDA_P=1; Delay6us(); SCL_P=1; Delay6us(); SDA_P=0; Delay6us(); } /*********************************************************/ // IIC终止函数 /*********************************************************/ void IIcStop() { SDA_P=0; Delay6us(); SCL_P=1; Delay6us(); SDA_P=1; Delay6us(); } /*********************************************************/ // IIC写一个字节 /*********************************************************/ void IIcWriteByte(uchar dat) { uchar i; for(i=0;i<8;i++) { dat=dat<<1; SCL_P=0; Delay6us(); SDA_P=CY; Delay6us(); SCL_P=1; Delay6us(); } SCL_P=0; Delay6us(); SDA_P=1; Delay6us(); } /*********************************************************/ // IIC读一个字节 /*********************************************************/ uchar IIcReadByte() { uchar i,temp,dat=0; SCL_P=0; Delay6us(); SDA_P=1; Delay6us(); for (i=0;i<8;i++) { SCL_P=1; Delay6us(); temp=SDA_P; Delay6us(); dat=(dat<<1)|temp; SCL_P=0; Delay6us(); } return(dat); } /*********************************************************/ // IIC总线响应 /*********************************************************/ void IIcRespons() { uchar i=0; SCL_P=1; Delay6us(); while((SDA_P==1)&&(i<250)) { i++; } SCL_P=0; Delay6us(); } /*********************************************************/ // IIC读出数据 /*********************************************************/ uchar IIcReadDat(uchar addr) { uchar dat; IIcStart(); // 开始信号 IIcWriteByte(0xa0); // 写芯片地址(写) IIcRespons(); // 等待应答 IIcWriteByte(addr); // 写内存地址(0-255) IIcRespons(); // 等待应答 IIcStart(); // 开始信号 IIcWriteByte(0xa1); // 写芯片地址(读) IIcRespons(); // 等待应答 dat=IIcReadByte(); // 读取一个字节数据 IIcRespons(); // 等待应答 IIcStop(); // 结束信号 DelayMs(2); // 简短延时 return dat; // 返回读取到的数据 } /*********************************************************/ // IIC写入数据 /*********************************************************/ void IIcWriteDat(uchar addr,uchar dat) { IIcStart(); // 开始信号 IIcWriteByte(0xa0); // 写芯片地址(写) IIcRespons(); // 等待应答 IIcWriteByte(addr); // 写内存地址(0-255) IIcRespons(); // 等待应答 IIcWriteByte(dat); // 写入数据 IIcRespons(); // 等待应答 IIcStop(); // 结束信号 DelayMs(2); // 简短延时 } /********************************************************** 矩阵键盘扫描程序. 如果扫描到有按键按下,则返回按键值,返回值情况如下所示: ------------------------------------------------------------- | 第1列 第2列 第3列 第4列 | |第1行 1 2 3 12 | |第2行 4 5 6 13 | |第3行 7 8 9 14 | |第4行 10 0 11 15 | ------------------------------------------------------------ 如果扫描不到有按键按下,则返回99 **********************************************************/ uchar KeyScanf() { uchar ret,temp1,temp2; P1=0x0f; if(P1!=0x0f) { DelayMs(15); if(P1!=0x0f) { temp1=P1; // 判断出是哪一行按键按下 P1=0xf0; DelayMs(5); temp2=P1; // 判断出是哪一列按键被按下 ret=temp1|temp2; // 通过行和列的值,确定是哪个按键被按下 switch(ret) { case 0xe7: return 1; case 0xd7: return 2; case 0xb7: return 3; case 0x77: return 12; case 0xeb: return 4; case 0xdb: return 5; case 0xbb: return 6; case 0x7b: return 13; case 0xed: return 7; case 0xdd: return 8; case 0xbd: return 9; case 0x7d: return 14; case 0xee: return 10; case 0xde: return 0; case 0xbe: return 11; case 0x7e: return 15; } return ret; } } return 99; } /*********************************************************/ // 液晶显示密码 /*********************************************************/ void LcdPrintCode(uchar num) { LcdGotoXY(row,column); // 液晶显示定位 LcdWriteData(num+0x30); // 显示输入的密码 DelayMs(150); // 等待150毫秒 LcdGotoXY(row,column); // 重新回到刚刚的显示位置 LcdWriteData('*'); // 显示“*”替换刚刚显示的数字 column++; // 液晶显示光标的纵坐标加1 } /********************************************************/ // 蜂鸣器鸣叫 /*********************************************************/ void MingJiao(uint time) { Beep_P=0; // 蜂鸣器开始鸣叫 DelayMs(time); // 延时 Beep_P=1; // 蜂鸣器停止鸣叫 } /*********************************************************/ // 清除密码输入缓冲区的内容 /*********************************************************/ void ClearCodeBuff() { uchar i; for(i=0;i<6;i++) // 循环执行6次 { ArrCodeBuff=' '; // 每次清除一位密码缓冲区 } inputNum=0; // 输入的密码位数为0 } /*********************************************************/ // 密码输入初始化 /*********************************************************/ void inputInit() { LcdGotoXY(0,0); // 光标定位 LcdPrintStr(" State:lock "); // 液晶第0行显示" State:lock " LcdGotoXY(1,0); // 光标定位 LcdPrintStr("Password: "); LcdGotoXY(1,9); // 液晶第1行显示"Password: " ClearCodeBuff(); // 清除密码缓冲区 } /*********************************************************/ // 密码初始化 /*********************************************************/ void CodeInit() { uchar dat,i; dat=IIcReadDat(10); if(dat!=88) // 如果是第一次使用AT24C02芯片 { IIcWriteDat(0,1); // 给AT24C02第0个内存写入第一个密码“1” IIcWriteDat(1,2); // 给AT24C02第1个内存写入第二个密码“2” IIcWriteDat(2,3); // 给AT24C02第2个内存写入第三个密码“3” IIcWriteDat(3,4); // 给AT24C02第3个内存写入第四个密码“4” IIcWriteDat(4,5); // 给AT24C02第4个内存写入第五个密码“5” IIcWriteDat(5,6); // 给AT24C02第5个内存写入第六个密码“6” IIcWriteDat(10,88); // 第10个内存写入数字“88”,代表密码初始化好了 } for(i=0;i<6;i++) // 从AT24C02读取6个密码,赋值给密码数组ArrCode { ArrCodeUnlock=IIcReadDat(i); } } /*********************************************************/ // 主函数,程序从这里开始执行 /*********************************************************/ void main() { uchar i; // 临时变量 uchar keyVal; // 按键扫描的返回值 uchar ArrCodeTemp[6]; // 临时数组 LcdInit(); // 液晶初始化 inputInit(); // 密码输入初始化 CodeInit(); // 密码初始化 while(1) { if(inputNum==6) // 如果输入了6位密码了 LcdWriteCmd(0x0c); // 关闭光标闪烁 else // 如果输入不够6位密码 LcdWriteCmd(0x0f); // 开启光标闪烁 keyVal=KeyScanf(); // 扫描按键是否有按键 if(keyVal!=99) // 如果有按键被按下了 { MingJiao(50); // 那么蜂鸣器鸣叫50毫秒 } /* 0-9 数字 */ if(keyVal<10) // 如果数字键被按下 { if(inputNum<6) // 如果输入的密码不到6位 { ArrCodeBuff[inputNum]=keyVal; // 给缓冲区加入一个新的密码记录 inputNum++; // inputNum加1,代表当前的密码输入多了一位 LcdPrintCode(keyVal); // 将输入的密码显示出来 } while(KeyScanf()!=99); // 等待按键释放 } /* 删除一个密码 */ if(keyVal==10) // 如果删除键被按下 { if(inputNum>0) // 如果当前已经有输入密码了 { column--; // 光标退回上一个位置 LcdGotoXY(row,column); LcdWriteData(' '); // 显示空格 LcdGotoXY(row,column); // 光标退回上一个位置 inputNum--; // inputNum减1,代表当前的密码删掉了一位 ArrCodeBuff[inputNum]=' '; // 清除一位密码缓冲区 } while(KeyScanf()!=99); // 等待按键释放 } /* 清除全部密码 */ if(keyVal==11) // 如果取消键被按下 { ClearCodeBuff(); // 清除密码缓冲区 if(inputMode==1) // 如果当前正在输入解锁密码 { LcdGotoXY(1,0); // 光标定位 LcdPrintStr("Password: "); // 液晶第1行显示“Password: ” LcdGotoXY(1,9); // 光标定位 } if(inputMode==2) // 如果当前正在输入修改密码1 { LcdGotoXY(0,0); // 光标定位 LcdPrintStr(" input1: "); // 液晶第0行显示“input1: ” LcdGotoXY(0,8); // 光标定位 } if(inputMode==3) // 如果当前正在输入修改密码2 { LcdGotoXY(1,0); // 光标定位 LcdPrintStr(" input2: "); // 液晶第1行显示“input1: ” LcdGotoXY(1,8); // 光标定位 } while(KeyScanf()!=99); // 等待按键释放 } /* 手动关锁 */ if(keyVal==12) { while(KeyScanf()!=99); // 等待按键释放 } /* 取消密码修改 */ if(keyVal==13) // 如果修改密码按键被按下 { if((inputMode==2)||(inputMode==3)) // 如果当前正在输入修改密码 { inputInit(); // 输入初始化(退出修改) Relay_P=1; // 继电器闭合 inputMode=1; // 改为输入解锁密码模式 } while(KeyScanf()!=99); } /* 管理员密码 */ if(keyVal==14) { for(i=0;i<6;i++) { if(ArrCodeBuff!=ArrCodeAdmin) break; } if(i<6) { LcdGotoXY(1,0); LcdPrintStr(" ERROR "); MingJiao(5000); } else { LcdGotoXY(1,0); LcdPrintStr("Password Init OK"); MingJiao(3000); IIcWriteDat(10,' '); CodeInit(); } inputInit(); } /* 确认按键 */ if(keyVal==15) // 如果确定键被按下 { /*解锁密码*/ if(inputMode==1) // 如果当前正在输入解锁密码 { for(i=0;i<6;i++) // 把密码缓冲区的内容和解锁密码进行6次比较 { if(ArrCodeBuff!=ArrCodeUnlock) break; } if(i<6) // 如果密码错误 { errTime++; // 错误次数加1 LcdGotoXY(1,0); // 光标定位 LcdPrintStr(" ERROR "); // 第1行显示" ERROR " LcdGotoXY(1,11); // 光标定位 LcdWriteData(errTime+0x30); // 显示错误的次数 LcdWriteCmd(0x0c); // 关闭光标闪烁 MingJiao(3000); // 蜂鸣器鸣叫3秒 if(errTime==3) // 如果错误了3次 { LcdGotoXY(1,0); // 光标定位 LcdPrintStr("Password:lock "); // 第1行显示"Password:locd errTime=0; // 密码错误次数清零 DelayMs(60000); // 延时60秒 } } else // 如果密码正确 { errTime=0; // 密码错误次数清零 Relay_P=0; // 打开继电器 LcdGotoXY(0,0); // 光标定位 LcdPrintStr(" State:open "); // 第0行显示" State:open " LcdGotoXY(1,0); // 光标定位 LcdPrintStr(" "); // 第1行显示" " for(i=0;i<100;i++) // 进行10秒等待,执行100次循环 { keyVal=KeyScanf(); // 扫描按键 DelayMs(100); // 等待100毫秒 if(keyVal==12) // 如果手动关锁按键被按下 break; // 退出for循环,结束开始等待 if(keyVal==13) // 如果按下修改密码键 { LcdGotoXY(0,0); // 光标定位 LcdPrintStr(" input1: ");// 第0行显示" input1: " LcdGotoXY(1,0); // 光标定位 LcdPrintStr(" input2: ");// 第1行显示" input2: " LcdGotoXY(0,8); // 光标定位 inputMode=2; // 切换密码输入模式 ClearCodeBuff(); // 清除密码缓冲区 while(KeyScanf()!=99); // 等待按键释放 break; // 退出for循环,进入密码修改 } } } if(inputMode==1) // 如果当前处于输入解锁密码状态 { Relay_P=1; // 闭合继电器 inputInit(); // 密码输入初始化 } } /*修改密码1*/ else if(inputMode==2) // 如果当前正在输入修改密码1 { for(i=0;i<6;i++) // 将输入的密码暂时存入ArrCodeTemp数组 { ArrCodeTemp=ArrCodeBuff; } LcdGotoXY(1,8); // 光标定位 inputMode=3; // 改为输入 修改密码2 ClearCodeBuff(); // 清除密码缓冲区 while(KeyScanf()!=99); // 等待按键释放 } /*修改密码2*/ else { for(i=0;i<6;i++) // 将2次输入的密码进行比较 { if(ArrCodeBuff!=ArrCodeTemp) break; } if(i<6) // 密码修改错误 { LcdGotoXY(0,0); // 光标定位 LcdPrintStr("Password Modify "); // 第0行显示"Password Modify " LcdGotoXY(1,0); // 光标定位 LcdPrintStr("-----failed-----"); // 第1行显示"-----failed-----" MingJiao(3000); // 蜂鸣器鸣叫3秒 } else // 密码修改成功 { LcdGotoXY(0,0); // 光标定位 LcdPrintStr("Password Modify "); // 第0行显示"Password Modify " LcdGotoXY(1,0); // 光标定位 LcdPrintStr("---Successful---"); // 第1行显示"---Successful---" MingJiao(2000); // 蜂鸣器鸣叫2秒 for(i=0;i<6;i++) { IIcWriteDat(i,ArrCodeTemp);// 将新的密码存入EEPROM芯片 ArrCodeUnlock=ArrCodeTemp;// 将新的密码存入密码数组 } } Relay_P=1; // 继电器闭合 inputMode=1; // 改为输入解锁密码模式 for(i=0;i<6;i++) // 清空修改密码缓冲区 { ArrCodeTemp=' '; } inputInit(); // 输入初始化 while(KeyScanf()!=99); // 等待按键释放 } } } }
|