1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
| /\* 编译环境: KEIL5 单片机型号AT89S52 12M 功能描述:Proteus在线电子密码锁的功能仿真: 包含4组初始密码6个0,6个1,6个2,6个3,6个4. 在解锁状态下,连续按Reset键5次,进入密码组重设。 当重设密码组大于ARR[4]时,ARR[0]则会被覆盖。 \*/ #include "LCD1602.h" //#include <intrins.h>
#define key\_port P3//用KEY\_PORT代替P3
sbit beek_c = P2^2;//定义蜂鸣器控制口 sbit lock_c = P2^3;//定义锁信号输出口
//\*\*\*\*\*\*\*\*\*\*\*\*\*\*函数声明\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* void init\_t0();//定时器0初始化函数 void judge\_xianshi(void);//显示处理程序 void read\_key(void);//按键键码读取子函数,返回相应的键码 uchar keybord_value;//全局变量,存储最终的键码,其值为0-F void read\_password(void);//6位数据的读取,也就是密码的读取 uchar deal\_password(void);//输入密码和系统码对比,看是否符合开锁条件
//返回值为1就开锁,返回值为2为密码错误 void makesurekeydeal();//确认键处理程序 void cancelkeydeal();//取消键处理程序
//\*\*\*\*\*\*\*\*\*\*\*矩阵键盘键码\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* const unsigned char code tabl2[16]={0xee,0xed,0xeb,0xe7,0xde,0xdd,0xdb,0xd7,0xbe, // s1 s2 s3 s4 s5 s6 s7 s8 s9 0xbd,0xbb,0xb7,0x7e,0x7d,0x7b,0x77};// // s10 s11 s12 s13 s14 s15 s16 uchar system[4][6];//定义 4\*6个数据作为系统的密码 也就是4组6位数
uchar passin[6];//定义全局变量,储存输入的6个按键数据 uchar temppassin[6];//输入的数据暂存 uchar flag1;//按键键入是否成功的标准,为1成功 为0失败 uchar passcount;//键入次数的统计 uchar flag2;//密码是否对的标志单位 ,为1成功 ,为2失败 uchar flag4;//蜂鸣器鸣响计时 uchar flag5;//reset重置密码累加次数 uchar flag7;//开锁状态 uchar t0_crycle; uchar error_count;//密码输入次数 static uchar CNT =0;//修改密码组 //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*主程序\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* void main() { uchar i; for(i=0;i<6;i++) { system[0][i]=1;//设置第一组6位系统密码为111 111 } for(i=0;i<6;i++) { system[1][i]=2;//设置第2组6位系统密码为222 222 } for(i=0;i<6;i++) { system[2][i]=3;//设置第3组6位系统密码为333 333 } for(i=0;i<6;i++) { system[3][i]=4;//设置第2组6位系统密码为444 444 } passcount=0; flag5=0; flag7=0; flag4=0; flag1=0; beek_c=1;//关闭蜂鸣器 lock_c=0;//关闭锁 LCMInit();//液晶初始化设置 init\_t0(); TR0=0;//关闭定时器T0 error_count=0; while(1) { read\_key();//读取键码 read\_password();//把键码转为密码 judge\_xianshi();//显示 } } //显示处理程序 void judge\_xianshi() { uchar i; if(flag5 >= 5){//修改密码期间输入显示 DisplayListChar(0,0,0, "Set New password");// DisplayListChar(1,0,0, "ARR["); DisplayOneChar(1,4, CNT + 0X30); DisplayListChar(1,5,0, "]:"); for(i=0;i<passcount&&i<6;i++)//显示输入的6个数据 DisplayOneChar( 1, 9+i,temppassin[i]+0x30);//修改密码时显示输入内容
} else if (flag5 == 0) { lock_c = 0;//断开锁信号输出 DisplayListChar(0,4,0, "Elec-Lock");//常规开锁显示输入界面 DisplayListChar(1,0,0, "Password:"); for(i=0;i<passcount&&i<6;i++)//显示输入的6个数据 // DisplayOneChar( 1, 9+i, '\*'); //启用则,第二行为隐藏,并注释下面一句 DisplayOneChar( 1, 9+i, passin[i]+0x30);//第二行为真实显示,可以把这句注释,并启用上面一行,就隐藏密码了 } else if ((flag5 > 0) && (flag5 <5)) { DisplayListChar(0,2,0, "Unlock Status");//常规开锁显示输入界面 DisplayListChar(1,0,0, "Password:"); for(i=0;i<passcount&&i<6;i++)//显示输入的6个数据 // DisplayOneChar( 1, 9+i, '\*');//启用则,第二行为隐藏,并注释下面一句 DisplayOneChar( 1, 9+i, passin[i]+0x30);//第二行为真实显示,可以把这句注释,并启用上面一行,就隐藏密码了 }
} //6位数据的读取,也就是密码的读取 void read\_password() { if(flag1==1 )//判断键入是否成功 { flag1=0; if(passcount<6 && flag5==0) { if(keybord_value<10){ //只接收0-9数字 passin[passcount] = keybord_value; passcount++; } }
if(passcount<6 && flag5!=0) { if(keybord_value < 10 )//只接收0-9数字 { temppassin[passcount]=keybord_value; passcount++; } } cancelkeydeal();//取消键处理程序 makesurekeydeal();//确认键处理程序 if(keybord_value==15 && flag7==1)//在开锁状态下,连续按#15按键5次或以上判断为重置密码 { flag5++;//重复按5次#15按键或以上,进入修改密码 if(flag5>=5){ passcount = 0;//清除按键输入 WriteCommandLCM(0x01,1); //清除显示一下 } } } } //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* //确认键处理程序 void makesurekeydeal() { uchar i;
if(keybord_value==12 && flag7==0 )//判断是否为确认键 { flag2 = deal\_password();// 判断输入的密码是否正确 passcount=0; if(flag2==1)//输入的密码正确 { flag7 = 1; beek_c=0;//开蜂鸣器 lock_c=1;//开锁 flag5=1; DisplayListChar(1,0,0, "Opening........");//在液晶的第二行显示字符"OPERING TR0=1;//开启定时器 flag4=0;//定时器(TR0=1)开启后,FLAG4每0.1秒自加1 error_count=0;//错误统计次数归零 while(flag4<=20);//密码正确开锁信号闭合2秒 蜂鸣器响2秒 flag4=0; TR0=0;//关闭定时器,蜂鸣器停止 WriteCommandLCM(0x01,1); //清除显示一下 beek_c=1;//关闭蜂鸣器 } if(flag2==2)//输入的密码错误 { beek_c=0; TR0=1; error_count++;//密码输入错误后,计数器+1 DisplayListChar(1,0,0, "Input Error TIS"); DisplayOneChar( 1,12,error_count+0x30);//显示输入多少次错误 while(flag4<=5);//密码输入错误蜂鸣器响0.5秒,关0.5秒的频率响2次 beek_c=1; flag4=0; while(flag4<=5); beek_c=0; flag4=0; while(flag4<=5); beek_c=1; flag4=0; flag2=0; TR0=0; if(error_count>=3)//如果密码输入3次错误经锁定2.54分钟或需要重新断电 { DisplayListChar(0,0,0, "Input Error 3 Ts"); DisplayListChar(1,0,0, "locked 3 minutes"); TR0=1; while(flag4<=254);//锁定时间过后系统恢复 DisplayListChar(0,0,0, "Electronics Lock"); TR0=0; error_count=0; flag4=0; } }
WriteCommandLCM(0x01,1); //清除显示一下 } if(flag5 >=5){//在开锁状态下,连续按reset按键5次以上,进入密码组重置 if(keybord_value==12 && flag7==1 )//确认修改密码 { for(i=0;i<6;i++) { system[CNT][i]=temppassin[i];//把暂存单元的数据传给对应的开始密码 temppassin[i]=0;//暂存单元清零,下次修改密码可以再次利用 } flag7=0;//各种标志单元清零 flag2=0; flag5=0; passcount=0; //按键次数计数清零 CNT++; CNT %=4; WriteCommandLCM(0x01,1); //清除显示一下 DisplayListChar(0,0,0, "Reset Succeed!"); delayms(1000); delayms(1000); delayms(1000); WriteCommandLCM(0x01,1); //清除显示一下 } } } //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* //取消键处理程序 void cancelkeydeal() { uchar i; if(keybord_value==13 )//判断是否为取消键 { if(flag7==0)//没有开锁状态下 { for(i=0;i<passcount;i++) { passin[i]=0; }//清零 passcount=0;//按取消键后,键入按键次数的计数单元清零 } else if(flag7==1)//开锁状态下 { if(flag5>=5)CNT--;//在重置密码状态下,放弃修改密码 flag7=0;//关闭开锁状态 flag2=0; flag5=0;//重置密码累加次数归零 passcount=0; } WriteCommandLCM(0x01,1); //清除显示一下 } }
uchar deal\_password()//输入密码和系统码对比,看是否符合开锁条件 { uchar i,j,temp2,temp; temp2=0; for(j=0;j<4;j++)//依次判断4组 { temp=0; for(i=0;i<6;i++) { if(system[j][i]==passin[i])temp++;//如果系统密码和键入的密码对应的位一样,则暂存单元自加1 } if(temp==6) { temp2=1; return(1);//如果TEMP为6,证明键入的密码和4组系统密码中的一组一样; break;//退出判断 } } return(2);//没有比对成功的密码组 } void read\_key(void) { uchar key_value,i=1; uchar key_high_value,key_low_value;//定义变量暂存高四位和低四位按键的键码 key_port=0xf0;//置按键控制口为1,准备读入数据 key_value=key_port & 0xf0; if(key_value!=0xf0)//如果没有按键按下,则相等 { delay\_50us(200);//延时10ms去除抖动 key_port=0xf0;//再次讲IO置1,准备读入去除抖动后的数据 key_value=key_port & 0xf0; switch (key_value) { case 0xf0:break;//经软件延时后,判断为误判,则退出函数,返回 case 0x70:key_high_value=0x70;break; case 0xb0:key_high_value=0xb0;break; case 0xd0:key_high_value=0xd0;break; case 0xe0:key_high_value=0xe0;break; default:key_high_value=0x00;break;//多个按键同时按下,显示0,然后退出 } key_port=0x0f;//交换高四位和低四位的状态,再次读取键码 key_value = key_port & 0x0f; switch(key_value) { case 0x07:key_low_value=0x07;break; case 0x0b:key_low_value=0x0b;break; case 0x0d:key_low_value=0x0d;break; case 0x0e:key_low_value=0x0e;break; default:key_low_value=0x00;break; } key_value = key_high_value | key_low_value; for(i=0;i<16;i++)//只取前14位数值进行处理,最后2个按键不计入 { if(key_value==tabl2[i]) { keybord_value=i; flag1=1;//置按键码读取成功标志位1; if(flag5 >0 && keybord_value==14)//已开锁标志位 { flag1=0; } break; } } beek_c=0;//开蜂鸣器 TR0=1; while(flag4<=1);//按按键的时候蜂鸣器响0.1秒 flag4=0; TR0=0;//关闭定时器 beek_c=1;//关闭蜂鸣器 key_port=0xf0;//置按键控制口为1,准备读入数据 while((key_port & 0xf0 )!=0xf0 && keybord_value!=14 ); //等待按键释放,按键释放后才往下执行程序 } } //定时器0中断服务程序 void timer0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256;//定时器设置为定时50MS t0_crycle++; if(t0_crycle==2)// 0.1秒 { t0_crycle=0; flag4++; //定时器开启后,FLAG4每0.1秒自加1 if(flag5!=0 && flag4>=40)//输入密码正确开锁后超过2分钟后不能进入修改开锁密码的界面 { flag4=0; TR0=0; } } } //定时器0初始化 void init\_t0() { TMOD=0x01;//设定定时器工作方式1,定时器定时50毫秒 TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1;//开总中断 ET0=1;//允许定时器0中断 t0_crycle=0;//定时器中断次数计数单元 }
|