• 说在前面:因为我的板子是液晶屏和数码管不能同时用,所以下面我使用的是液晶屏,下面的代码通俗易懂也有注释,如果有的控件不知到如何使用的可以查看我之前的几篇C51文章,这个密码锁就是基于之前的笔记所写的内容.
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
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
#include<reg52.h>
//#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define data1602 P0
#define LED P2
/*******引脚定义*******/
//按键的控制引脚
sbit S1 = P3^7;
sbit S2 = P3^6;
sbit S3 = P3^5;
sbit S4 = P3^4;
sbit S5 = P3^3;
sbit S6 = P3^2;

//LCD1602的控制引脚
sbit RS = P1^0;
sbit RW = P1^1;
sbit E = P1^2;
sbit BF = data1602^7; //BF表示data1602的最高位,判断是忙还是闲

sbit Alam = P1^5;//蜂鸣器引脚
//sbit key = P3^3;//开锁

bit isInitPass = 1;//是否在初始化密码
bit pass=0; //密码正确标志
bit isReset = 0; //是否在重设密码
uchar countNum = 0; //选择数字位数
uchar countPass = 1;//输入密码位数
uchar ErrorCont = 0; //错误次数计数
uchar timeNum=0; //计时间次数
uchar trueTime='5'; // 锁定时间
//液晶显示数据数组
uchar code initLock1[] = {" Welcome to "};
uchar code initLock2[] = {" password lock "};
uchar code SetNew[] = {"==SetPassword== "};
uchar code Input[] = {"input: "}; //INPUT
uchar code start_line1[] = {"==please input=="};
uchar code start_line2[] = {"password: "};
uchar code superPassword[] = {"=Super Password="};
uchar code Correct[] = {" correct "}; //输入正确
uchar code Error[] = {" error "}; //输入错误
uchar code codepass[] = {" pass "};
uchar code LockOpen[] = {" open "}; //OPEN
uchar code Reset[] = {"=ResetPassword= "};
uchar code oldPassword[] = {"please input old"}; //输入旧密码
uchar code setOK[] = {"Set Password OK "};
uchar code NULL[] = {" "};
uchar code ResetOK[] = {"ResetPasswordOK!"};
uchar code initword[] = {"Init password..."};
uchar code ErrorTry[] = {"error,try again!"};
uchar code again[] = {"input again "};
uchar code wait[] = {"please wait s "};
uchar code table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//流水灯

uchar InitPassword[6]={'0','0','0','0','0','0'}; //初始化密码暂存数组
uchar CurrentPassword[6]={'0','0','0','0','0','0'};//输入密码暂存数组
uchar adminpassword[6]={'1','3','1','4','2','0'};//管理员密码
uchar PassNum[10] = {'0','1','2','3','4','5','6','7','8','9'}; //存放所有数字

/*******延时函数*******/
void delay(uint z)//z毫秒
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*******空函数*******/
/*void Nop(void) //空操作
{
_nop_(); //仅作延时用一条语句大约1us
_nop_();
_nop_();
_nop_();
}*/
/*******忙检测函数*******/
bit LCD_busy()
{
bit busy;
P0 = 0xff;//防止干扰
RS = 0; //命令模式
RW = 1; //读模式
E = 1;
busy = BF;//将忙标志位的数值赋给busy
E = 0;
return busy;
}
/*******写命令函数*******/
void LCD_write_cmd(uchar cmd)//cmd为需要写的命令
{
while(LCD_busy());//只有当LCD_busy()为0(闲)时才跳出循环
RS = 0; //命令模式
RW = 0; //写模式
data1602 = cmd; //将命令内容的十六进制送到P0端口
delay(1);
E = 1; //拉高使能端,为制造有效的下降沿做准备
delay(1);
E = 0; //由高变低,产生下降沿,液晶执行命令,使命令送到LCD1602的DB0~DB7
}
/*******写数据函数*******/
void LCD_write_data(uchar dat)//dat为需要写的数据
{
while(LCD_busy());//只有当LCD_busy()为0(闲)时才跳出循环
RS = 1; //数据模式
RW = 0; //写模式
data1602 = dat; //将数据内容的十六进制送到P0端口
delay(1);
E = 1;
delay(1);
E = 0; //使能端,高电平有效,使命令送到LCD1602的DB0~DB7
}
/*******IT0中断初始化函数*******/
void IT_init()
{
IT0 = 0; //设置低电平触发外部中断
EA = 1; //开总中断
EX0 = 1;//开外部中断
}
/*******定时器T0中断初始化函数*******/
void Time_init()
{
TMOD = 0x01;//将定时器0设为方式1,即16位定时器
TH0 = (65536-45872)/256;//给定时器的高八位赋初值
TL0 = (65536-45872)%256;//给定时器的低八位赋初值
EA = 1;//开总中断
ET0 = 1;//开定时器0中断
}
/*******LCD初始化函数*******/
void LCD_init()
{
LCD_write_cmd(0x38); //将设置“两行、八位数据、5*7的点阵”命令写入LCD的控制器
LCD_write_cmd(0x0c); //开显示关光标
LCD_write_cmd(0x06); //光标右移指令
LCD_write_cmd(0x01); //清除显示
}
/*******LCD写显示地址函数*******/
void LCD_write_address(uchar x,uchar y)
{
x&=0x0f; //列地址限制在0~15之间
y&=0x01; //行地址限制在0~1
if(y==0)
LCD_write_cmd(x|0x80);//数据指针=80+地址变量,写入列地址
else
LCD_write_cmd((x+0x40)|0x80); //如果是第二行,将列地址写入
}
/*******LCD显示函数*******/
void LCD_display(uchar x,uchar y,uchar buf) //x:列 y:行,buf:显示的字符
{
LCD_write_address(x,y);//先将地址写入
LCD_write_data(buf); //再写入要显示的数据
}

/*******一声提示音,表示有效输入*******/
void OneAlam()
{
Alam=0; //蜂鸣器响
delay(100); //延时5ms
Alam=1; //蜂鸣器关
}

/*******两声提示音,表示操作成功*******/
void TwoAlam()
{
uchar i = 0;
for(i=0;i<2;i++)
{
Alam=0; //蜂鸣器响
delay(100); //延时5ms
Alam=1; //蜂鸣器关
delay(100);
}
}

/*******三声提示音,表示错误*******/
void ThreeAlam()
{
uchar i = 0;
for(i=0;i<3;i++)
{
Alam=0; //蜂鸣器响
delay(100); //延时5ms
Alam=1; //蜂鸣器关
delay(100);
}
}
/*******流水灯函数*******/
void LED_display()
{
uint i;
for(i=0;i<8;i++) //数组控制流水灯
{
LED = table[i];
delay(500);
}
LED = 0x00;
delay(1000);
LED = 0xff;
}

/*******初始化界面函数*******/
void init_display()
{
uchar i;
for(i=0;i<16;i++)
LCD_display(i,0,initLock1[i]);
for(i=0;i<16;i++)
LCD_display(i,1,initLock2[i]);
}
/*******按键控制输入密码函数*******/
void pushBtn_password()
{
countNum = 0;
countPass = 1;
LCD_write_cmd(0x0e); //光标闪烁
while(1)
{
if(S1 == 0) //第一次检测按键被按下
{
delay(8); //延时8ms进行消抖
if(S1 == 0) //再次检测按键被按下,说明确实被按下了
{
if(isInitPass)
LCD_display(6+countPass,1,PassNum[countNum]); //显示数字
else
LCD_display(9+countPass,1,PassNum[countNum]);
LCD_write_cmd(0x10); //光标左移
if(isInitPass)
InitPassword[countPass-1] = PassNum[countNum]; //将输入的数字存到初始化数组中
else
CurrentPassword[countPass-1] = PassNum[countNum];//将输入的数字存到当前数组中

if(countNum == 9)
countNum = 0;
else
countNum++;
}
delay(300);
}
if(S3 == 0) //第一次检测按键被按下
{
delay(8); //延时8ms进行消抖
if(S3 == 0) //再次检测按键被按下,说明确实被按下了
{
countNum = 0;
if(countPass == 6)
countPass = 1;
else
countPass++;
if(isInitPass)
LCD_display(6+countPass,1,InitPassword[countPass-1]);
else
LCD_display(9+countPass,1,CurrentPassword[countPass-1]);
LCD_write_cmd(0x10);
}
delay(250);
}
if(S4 == 0)
{
delay(8); //延时8ms进行消抖
if(S4 == 0) //再次检测按键被按下,说明确实被按下了
{
countNum = 0;
if(countPass>1)
countPass--;
else
countPass = 1;
}
if(isInitPass)
LCD_display(6+countPass,1,InitPassword[countPass-1]);
else
LCD_display(9+countPass,1,CurrentPassword[countPass-1]);
LCD_write_cmd(0x10);
delay(300);
}
if(S5 == 0)
{
delay(8);
if(S5 == 0)
{
break;
}
}
}
LCD_write_cmd(0x0c); //光标不闪烁
}

/*******最初设置密码函数*******/
void init_password()
{
uchar i = 0;
for(i=0;i<16;i++)
LCD_display(i,0,SetNew[i]);
for(i=0;i<16;i++)
LCD_display(i,1,Input[i]);
pushBtn_password(); //按键控制输入密码
for(i=0;i<16;i++)
LCD_display(i,0,NULL[i]);
for(i=0;i<16;i++)
LCD_display(i,1,NULL[i]);

for(i=0;i<13;i++)
LCD_display(i,0,initword[i]);
delay(500);
LCD_display(13,0,initword[13]);//滚动显示初始化中
delay(500);
LCD_display(14,0,initword[14]);
delay(500);
LCD_display(15,0,initword[15]);
delay(500);
for(i=0;i<16;i++)
LCD_display(i,0,setOK[i]);
TwoAlam();//两声提示音,表示操作成功
isInitPass = 0;
}
/*******判断是否输入正确函数*******/
void judge()
{
uchar jg = 0;
uchar i;
if((CurrentPassword[0]==InitPassword[0])&&(CurrentPassword[1]==InitPassword[1])&&(CurrentPassword[2]==InitPassword[2])&&(CurrentPassword[3]==InitPassword[3])&&(CurrentPassword[4]==InitPassword[4])&&(CurrentPassword[5]==InitPassword[5]))
{
if(isReset==0)
jg = 1; //正确输入密码
else
jg = 3; //正确输入密码且在重设密码
pass = 1; //密码正确
}
else if((CurrentPassword[0]==adminpassword[0])&&(CurrentPassword[1]==adminpassword[1])&&(CurrentPassword[2]==adminpassword[2])&&(CurrentPassword[3]==adminpassword[3])&&(CurrentPassword[4]==adminpassword[4])&&(CurrentPassword[5]==adminpassword[5]))
{
if(isReset==0)
jg = 2; //正确输入管理员超级密码
else
jg = 4; //正确输入管理员超级密码且在重设密码
pass = 1;
}
else
ErrorCont++; //错误次数+1

if(jg==1)
{
for(i=0;i<16;i++)
LCD_display(i,0,Correct[i]);
for(i=0;i<16;i++)
LCD_display(i,1,LockOpen[i]);
OneAlam();
LED_display();
}
else if(jg==2)
{
for(i=0;i<16;i++)
LCD_display(i,0,superPassword[i]);
for(i=0;i<16;i++)
LCD_display(i,1,LockOpen[i]);
OneAlam();
LED_display();
}else if(jg==3)
{
for(i=0;i<16;i++)
LCD_display(i,0,Correct[i]);
for(i=0;i<16;i++)
LCD_display(i,1,NULL[i]);
OneAlam();
}
else if(jg==4)
{
for(i=0;i<16;i++)
LCD_display(i,0,superPassword[i]);
for(i=0;i<16;i++)
LCD_display(i,1,NULL[i]);
OneAlam();
}
else
{
for(i=0;i<16;i++)
LCD_display(i,0,ErrorTry[i]);
for(i=0;i<16;i++)
LCD_display(i,1,NULL[i]);
ThreeAlam();
}
}
/*******显示输入密码函数*******/
void input_Password()
{
uchar i;
do{
if(ErrorCont==3)
{
TR0 = 1; //启动定时器T0
ErrorCont = 0;
for(i=0;i<16;i++)
LCD_display(i,0,wait[i]);
LCD_display(12,0,trueTime);
for(i=0;i<16;i++)
LCD_display(i,1,again[i]);

while(trueTime >= 48)
{
if(timeNum == 20) //num=20代表用了50ms*20 = 1s
{
timeNum = 0;
trueTime--; //锁定时间减1
LCD_display(12,0,trueTime);
}
}
TR0 = 0; //关闭定时器T0
trueTime = '5';
}
for(i=0;i<16;i++)
LCD_display(i,0,start_line1[i]);
for(i=0;i<16;i++)
LCD_display(i,1,start_line2[i]);
pushBtn_password();
judge();
}while(pass==0);

}

/*******main函数*******/
void main()
{
LCD_init();
IT_init();
Time_init();
init_display();
delay(2000);
init_password();
delay(2000);
while(1)
{
input_Password();
delay(1000);
}

}
void reSetPassword() interrupt 0
{
uchar i;
isReset = 1;
isInitPass = 0;

do{
/*if(ErrorCont==3)
{
TR0 = 1; //启动定时器T0
ErrorCont = 0;
for(i=0;i<16;i++)
LCD_display(i,0,wait[i]);
LCD_display(12,0,trueTime);
for(i=0;i<16;i++)
LCD_display(i,1,again[i]);

while(trueTime >= 48)
{
if(timeNum == 20) //num=20代表用了50ms*20 = 1s
{
timeNum = 0;
trueTime--; //锁定时间减1
LCD_display(12,0,trueTime);
}
}
TR0 = 0; //关闭定时器T0
trueTime = '5';
}*/
if(ErrorCont==3)
{

}
for(i=0;i<16;i++)
LCD_display(i,0,oldPassword[i]);
for(i=0;i<16;i++)
LCD_display(i,1,start_line2[i]);
pushBtn_password();
judge();
}while(pass==0&&ErrorCont<3);

delay(1000);
if(pass == 1)
{
for(i=0;i<16;i++)
LCD_display(i,0,Reset[i]);
for(i=0;i<16;i++)
LCD_display(i,1,Input[i]);
isInitPass = 1;
pushBtn_password(); //按键控制输入密码
for(i=0;i<16;i++)
LCD_display(i,0,ResetOK[i]);
for(i=0;i<16;i++)
LCD_display(i,1,NULL[i]);
TwoAlam();
delay(1000);
}

for(i=0;i<16;i++)
LCD_display(i,0,start_line1[i]);
for(i=0;i<16;i++)
LCD_display(i,1,start_line2[i]);
isInitPass = 0;
isReset = 0;
}
void TimeCount() interrupt 1
{
TH0 = (65536-45872)/256;//重装初值
TL0 = (65536-45872)%256;
timeNum++; //每发生一次中断后,num++
}