-
Notifications
You must be signed in to change notification settings - Fork 13
/
pro10.c
596 lines (546 loc) · 12.7 KB
/
pro10.c
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
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
#include <reg51.h>
#include <intrins.h> //引入_nop_();函数
/*
_nop_();指令需要的只是一个机械周期
也就是12个时钟周期(震荡周期)
_nop_(); 指令的延迟时间为 1us。
可以较为精确得控制延迟时间。
*/
#include "zh-hans.h" //导入我们自己写的中文编码库
#define LCD_databus P1 //LCD8位数据口
sbit INT = P3^2;
sbit CS1 = P3^3; //片选1,1有效,控制左半屏
sbit CS2 = P3^4; //片选2,1有效,控制右半屏
sbit E = P3^5; //使能信号
sbit RW = P3^6; //读/写,1为读、0为写
sbit RS = P3^7; //代码/数据,1为数据、0为代码
sbit BU = P3^1; //蜂鸣器,1为响
sbit LED = P3^0; //小灯,1为亮
unsigned char key = 0x77; //按键值
char key_press = 0; //按键是否按下
/*
AMPIRE12864的组成:可以看成是两个64*64的屏幕
通过CS1、CS2两个片选信号来控制,低电平选通
RST复位信号,我们这里置为高电平表示不用复位
DBx是并行输入端
E是使能信号,置1可以设置DBx,置0表示交换结束
RW为低电平表示写入数据,高电平表示读出数据
RS为低电平表示指令操作,高电平表示数据操作
*/
/*
键盘4x4
1 2 3 返回
4 5 6 清空
7 8 9 退位
# 0 * 确定
*/
/*************************函数声明***************************/
void delay(int z);
void read_busy();
void write_LCD_cmd(char value);
void write_LCD_data(char value);
void set_page(char page);
void set_line(char startline);
void set_column(char column);
void set_on_or_off(char choose);
void select_screen(char screen);
void clear_screen(char screen);
void clear_bottom_screen();
void init_LCD();
void display(char screen,char page,char column,char *p);
void display_charactars(char screen,char page,char column,char datacode);
void init_sys();
void tip_overlength();
void tip_lesslength();
void tip_pwderror();
void input_passwd();
void enter_sys();
/**************************************************************/
// 延时
void delay(int z)
{
int x,y;
for(x=z;x>0;x--)
for(y=114;y>0;y--);
}
//读“忙”函数——数据线最高位DB7=1则busy
void read_busy()
{
P1 = 0x00; //DB送数
RS = 0; //代码
RW = 1; //读
E = 1; //1可设置DB
while(P1 & 0x80);
E = 0;
}
/***************************写入LCD***************************/
//向LCD中写入命令
void write_LCD_cmd(char value)
{
read_busy(); //每次读写都要进行忙判断
RS = 0; //选择命令
RW = 0; //写操作
LCD_databus = value;
E = 1; //E由1->0锁存有效数据
_nop_(); //空操作,用作延时一个机械周期1us
_nop_(); //同上
E = 0;
}
/*可以写成一个函数简便一点,
但是为了让大家好理解就先这样吧*/
//向LCD中写入数据
void write_LCD_data(char value)
{
read_busy(); //每次读写都要进行忙判断
RS = 1; //选择数据
RW = 0; //写操作
LCD_databus = value;
E = 1; //E由1->0锁存有效数据
_nop_(); //空操作,用作延时一个机械周期1us
_nop_(); //同上
E = 0;
}
/**************************************************************/
/***************************设置*******************************/
//设置“页”,LCD12864共8页,一页是8行
void set_page(char page)
{
page = 0xB8|page; //页的首地址0xB8
write_LCD_cmd(page);
}
//设置显示的起始行
void set_line(char startline)
{
startline = 0xC0|startline; //起始地址0xC0
write_LCD_cmd(startline);
//设置从哪行开始:共0-63;一般从0行开始显示
}
//设置显示的列
void set_column(char column)
{
column = column & 0x3F; //列的最大值为64
column = 0x40|column; //列的首地址0x40
write_LCD_cmd(column); //列位置
}
//显示开、关函数,0x3E是关闭显示,0x3F是开启显示
void set_on_or_off(char choose)
{
choose = 0x3E|choose; //0011 111x, choose只能为0或者1
write_LCD_cmd(choose);
}
/**************************************************************/
/**************************屏幕选择***************************/
//选屏
void select_screen(char screen)
{
switch(screen){
case 0: CS1=0;CS2=0;break; //全屏
case 1: CS1=0;CS2=1;break; //左半屏
case 2: CS1=1;CS2=0;break; //右半屏
default:break;
}
}
//清屏
void clear_screen(char screen)
{
char i,j;
select_screen(screen);
for(i=0;i<8;i++){ //控制页数0-7,共8页
set_page(i);
set_column(0);
for(j=0;j<64;j++){ //控制列数0-63,共64列
write_LCD_data(0x00); //写入0,地址指针自加1
}
}
}
//清最后一行屏
void clear_bottom_screen()
{
char i;
select_screen(0);
set_page(6); //最后一行
set_column(0); //从第一列开始
for(i=0;i<64;i++){ //控制列数0-63,共64列
write_LCD_data(0x00); //写入0,地址指针自加1
}
set_page(7);
set_column(0); //从第一列开始
for(i=0;i<64;i++){ //控制列数0-63,共64列
write_LCD_data(0x00); //写入0,地址指针自加1
}
}
/**************************************************************/
//LCD的初始化
void init_LCD()
{
read_busy();
select_screen(0); //全屏
set_on_or_off(0); //关闭显示
select_screen(0); //全屏
set_on_or_off(1); //开显示
select_screen(0); //全屏
clear_screen(0); //清屏
set_line(0); //开始行:0
}
//显示汉字
void display(char screen,char page,char column,char *p)
{
char i;
select_screen(screen); //选屏
set_page(page); //控制页
set_column(column); //控制列
for(i=0;i<16;i++){ //控制16列的数据输出
write_LCD_data(p[i]);
//汉字的上半部分
}
set_page(page+1); //写下半页
set_column(column);
for(i=0;i<16;i++){
write_LCD_data(p[i+16]);
//汉字的下半部分
}
}
//显示字符
void display_charactars(char screen,char page,char column,char datacode)
{
char i;
select_screen(screen); //选屏
set_page(page); //控制页
set_column(column); //控制列
for(i=0;i<16;i++){ //控制16列的数据输出
write_LCD_data(datacode);
}
}
/**************************************************************/
//初始化屏幕显示
void init_sys()
{
clear_screen(0); //清屏
display(1,3,2*16,huan);
display(1,3,3*16,ying);
display(2,3,0*16,guang);
display(2,3,1*16,lin);
while(1){
if(key_press){ //有按键按下
if(key == 0x77){ //按下确认键
key_press = 0;
break;
}
}
}
input_passwd();
}
//提示语:超出长度
void tip_overlength()
{
clear_bottom_screen();
display(1,6,2*16,zuokuohao);
display(1,6,3*16,chao);
display(2,6,0*16,chu);
display(2,6,1*16,chang);
display(2,6,2*16,du);
display(2,6,3*16,youkuohao);
}
//提示语:请输入四位
void tip_lesslength()
{
clear_bottom_screen();
display(1,6,1*16,zuokuohao);
display(1,6,2*16,qing);
display(1,6,3*16,shu);
display(2,6,0*16,ru);
display(2,6,1*16,si);
display(2,6,2*16,wei);
display(2,6,3*16,youkuohao);
}
//提示语:密码错误
void tip_pwderror()
{
clear_bottom_screen();
display(1,6,2*16,zuokuohao);
display(1,6,3*16,mi);
display(2,6,0*16,ma);
display(2,6,1*16,cuo);
display(2,6,2*16,wu);
display(2,6,3*16,youkuohao);
}
//输入密码界面
void input_passwd()
{
//竖线每个半秒闪烁
char flag=0;
//四位密码
char pwd[4] = {0};
//当前输入密码的长度
char pwd_length = 0;
clear_screen(0); //清屏
display(1,0,0*16,qing);
display(1,0,1*16,shu);
display(1,0,2*16,ru);
display(1,0,3*16,si);
display(2,0,0*16,wei);
display(2,0,1*16,mi);
display(2,0,2*16,ma);
display(2,0,3*16,maohao);
while(1){
if(key_press){ //有按键按下
if(key == 0xEE){ //当按下1
//已输入4位密码
if(pwd_length >= 4){
//清底部屏幕,显示提示语
tip_overlength();
}
else{
clear_bottom_screen();
display(1,2,pwd_length*16,yi);
pwd[pwd_length] = 1;
pwd_length++;
}
}
else if(key == 0xDE){ //当按下2
//已输入4位密码
if(pwd_length >= 4){
//清底部屏幕,显示提示语
tip_overlength();
}
else{
clear_bottom_screen();
display(1,2,pwd_length*16,er);
pwd[pwd_length] = 2;
pwd_length++;
}
}
else if(key == 0xBE){ //当按下3
//已输入4位密码
if(pwd_length >= 4){
//清底部屏幕,显示提示语
tip_overlength();
}
else{
clear_bottom_screen();
display(1,2,pwd_length*16,san);
pwd[pwd_length] = 3;
pwd_length++;
}
}
else if(key == 0xED){ //当按下4
//已输入4位密码
if(pwd_length >= 4){
//清底部屏幕,显示提示语
tip_overlength();
}
else{
clear_bottom_screen();
display(1,2,pwd_length*16,si);
pwd[pwd_length] = 4;
pwd_length++;
}
}
else if(key == 0xDD){ //当按下5
//已输入4位密码
if(pwd_length >= 4){
//清底部屏幕,显示提示语
tip_overlength();
}
else{
clear_bottom_screen();
display(1,2,pwd_length*16,wu1);
pwd[pwd_length] = 5;
pwd_length++;
}
}
else if(key == 0xBD){ //当按下6
//已输入4位密码
if(pwd_length >= 4){
//清底部屏幕,显示提示语
tip_overlength();
}
else{
clear_bottom_screen();
display(1,2,pwd_length*16,liu);
pwd[pwd_length] = 6;
pwd_length++;
}
}
else if(key == 0xEB){ //当按下7
//已输入4位密码
if(pwd_length >= 4){
//清底部屏幕,显示提示语
tip_overlength();
}
else{
clear_bottom_screen();
display(1,2,pwd_length*16,qi);
pwd[pwd_length] = 7;
pwd_length++;
}
}
else if(key == 0xDB){ //当按下8
//已输入4位密码
if(pwd_length >= 4){
//清底部屏幕,显示提示语
tip_overlength();
}
else{
clear_bottom_screen();
display(1,2,pwd_length*16,ba);
pwd[pwd_length] = 8;
pwd_length++;
}
}
else if(key == 0xBB){ //当按下9
//已输入4位密码
if(pwd_length >= 4){
//清底部屏幕,显示提示语
tip_overlength();
}
else{
clear_bottom_screen();
display(1,2,pwd_length*16,jiu);
pwd[pwd_length] = 9;
pwd_length++;
}
}
else if(key == 0xD7){ //当按下0
//已输入4位密码
if(pwd_length >= 4){
//清底部屏幕,显示提示语
tip_overlength();
}
else{
clear_bottom_screen();
display(1,2,pwd_length*16,ling);
pwd[pwd_length] = 0;
pwd_length++;
}
}
else if(key == 0xE7){ //当按下#
}
else if(key == 0xB7){ //当按下*
}
else if(key == 0x7E){ //当按下返回
init_sys();
}
else if(key == 0x7D){ //当按下清空
clear_bottom_screen();
display(1,2,0*16,kongbai);
display(1,2,1*16,kongbai);
display(1,2,2*16,kongbai);
display(1,2,3*16,kongbai);
display(2,2,0*16,kongbai);
pwd_length = 0;
}
else if(key == 0x7B){ //当按下退位
clear_bottom_screen();
if(pwd_length > 0){
if(pwd_length == 4){
display(2,2,(pwd_length-4)*16,kongbai);
}
else if(pwd_length < 4){
display(1,2,pwd_length*16,kongbai);
}
pwd_length--;
}
}
else if(key == 0x77){ //当按下确定
//已输入4位密码
if(pwd_length < 4){
//清底部屏幕,显示提示语
tip_lesslength();
}
else if(pwd_length == 4){
if(pwd[0]==0&&pwd[1]==7&&pwd[2]==1&&pwd[3]==8){
enter_sys();
}
else{
tip_pwderror();
BU = 1;
delay(50);
BU = 0;
}
}
}
key_press = 0; //按下状态还原
}
//闪烁竖线
if(flag <= 50){
if(pwd_length >= 4){
//右半屏
display(2,2,(pwd_length-4)*16,shuxian);
}
else{
//左半屏
display(1,2,pwd_length*16,shuxian);
}
flag++;
}
else if(flag < 200){
if(pwd_length >= 4){
//右半屏
display(2,2,(pwd_length-4)*16,kongbai);
}
else{
//左半屏
display(1,2,pwd_length*16,kongbai);
}
flag++;
if(flag == 200){
flag = 0;
}
}
}
}
//密码正确进入系统
void enter_sys()
{
LED = 1;
clear_screen(0); //清屏
display(1,3,2*16,mi);
display(1,3,3*16,ma);
display(2,3,0*16,zheng);
display(2,3,1*16,que);
while(1){
if(key_press){ //有按键按下
if(key == 0x7E){ //按下返回键
LED = 0;
key_press = 0;
break;
}
}
}
init_sys();
}
/**************************************************************/
//键盘扫描
void key_scan() interrupt 0
{
char value_h,value_l;
P2 = 0xF0;
if(P2 != 0xF0){
P2 = 0xF0;
value_l = P2;
delay(10); //按键消抖
P2 = 0x0F;
value_h = P2;
key = value_l+value_h; //得到键值
}
P2 = 0xF0;
key_press = 1;
}
void main()
{
LED = BU = 0; // 小灯和蜂鸣器处于不工作状态
P1 = 0xF0;
P2 = 0xF0;
EA = 1; // 中断总允许
EX0 = 1; // 外部中断0
IT0 = 1; // 下降沿触发
/*
一个汉字16x16大小
2页表示32行开始,8页共128行
每个半屏(64/2=32列)只能显示四个汉字
32/16=2
*/
init_sys();
while(1);
}