作业讲解
第三题:
先用定时器0把流水灯的写出来,再写定时器1的数码管显示,用变量存储765432,再定时器中断函数里自减,当到达7654398时,关闭定时器就不会变化了,这里765是不变的,偷懒,只管432。写完数码管停止和流水灯停止都试验后再写剩下的。改变定时器计时时间这里要记住。
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uchar unsigned char
5 #define uint unsigned int
6
7 void Delay1ms();
8 void delay(int n);
9 void display(uchar a,uchar b,uchar c,uchar bai,uchar shi,uchar ge);
10 void init();
11 sbit WEI=P2^7;
12 sbit DUAN=P2^6;
13
14 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x76,0x79,0x38,0x3f};
15 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示 H E L O
16 uchar flag=0,flag1=0;
17 uchar t0=0,t1=0;
18 uint number=432;
19 uchar bai=0,shi=0,ge=0;
20 void main()
21 {
22 init();
23 bai=number/100;
24 shi=number/10%10;
25 ge=number%10;
26 while(1)
27 {
28 if(flag1!=1)
29 {
30 display(7,6,5,bai,shi,ge);
31 }
32 else
33 {
34 display(17,18,19,19,20,16);
35 }
36 }
37 }
38
39 void delay(int n)
40 {
41 while(n--)
42 {
43 Delay1ms();
44 }
45 }
46 void Delay1ms() //@12.000MHz
47 {
48 unsigned char i, j;
49
50 i = 2;
51 j = 239;
52 do
53 {
54 while (--j);
55 } while (--i);
56 }
57 void init()
58 {
59 P1=0xfe;
60 TMOD=0x11;//两个定时器都设置为方式1
61 TH0=(65536-50000)/256;
62 TL0=(65536-50000)%256;
63 TH1=(65536-50000)/256;
64 TL1=(65536-50000)%256;
65 EA=1;
66 ET0=1;
67 TR0=1;
68 ET1=1;
69 TR1=1;
70 }
71 void timer1() interrupt 3
72 {
73 TH1=(65536-50000)/256;
74 TL1=(65536-50000)%256;
75 t1++;
76 if(t1==2)
77 {
78 t1=0;
79 number--;
80 bai=number/100;
81 shi=number/10%10;
82 ge=number%10;
83 if(number==398)
84 {
85 //定时器0到这个位置还在运行,且TH0和TL0不知道是多少,所以要重新赋值
86 TR0=0;
87
88 TH0=(65536-50000)/256;
89 TL0=(65536-50000)%256;
90 TR0=1;
91 flag=1;
92 t0=0;
93 P1=0xff;
94 TR1=0;
95 }
96 }
97 }
98 void timer0() interrupt 1
99 {
100 TH0=(65536-50000)/256;
101 TL0=(65536-50000)%256;
102 t0++;
103 if(flag!=1)
104 {
105 if(t0==10)
106 {
107 t0=0;
108 P1=_crol_(P1,1);
109 }
110 }
111 else
112 {
113 if(t0%4==0)
114 {
115 P1=~P1;
116 if(t0==60)
117 {
118 TR0=0;
119 P1=0xff;
120 flag1=1;
121 }
122 }
123 }
124 }
125 void display(uchar a,uchar b,uchar c,uchar bai,uchar shi,uchar ge)
126 {
127 DUAN=1;
128 P0=Table[a];
129 DUAN=0;
130
131 P0=0xff;
132 WEI=1;
133 P0=0xfe;
134 WEI=0;
135 delay(1);
136
137 DUAN=1;
138 P0=Table[b];
139 DUAN=0;
140
141 P0=0xff;
142 WEI=1;
143 P0=0xfd;
144 WEI=0;
145 delay(1);
146
147 DUAN=1;
148 P0=Table[c];
149 DUAN=0;
150
151 P0=0xff;
152 WEI=1;
153 P0=0xfb;
154 WEI=0;
155 delay(1);
156
157 DUAN=1;
158 P0=Table[bai];
159 DUAN=0;
160
161 P0=0xff;
162 WEI=1;
163 P0=0xf7;
164 WEI=0;
165 delay(1);
166
167 DUAN=1;
168 P0=Table[shi];
169 DUAN=0;
170
171 P0=0xff;
172 WEI=1;
173 P0=0xef;
174 WEI=0;
175 delay(1);
176
177 DUAN=1;
178 P0=Table[ge];
179 DUAN=0;
180
181 P0=0xff;
182 WEI=1;
183 P0=0xdf;
184 WEI=0;
185 delay(1);
186 }
中断函数不能太长,我们每50ms进入一次中断,如果中断函数长达50ms,那么当下一次中断进入函数时,上一次中断没退出,就会把下一次的丢失,程序就会出错。如何看这个时间呢,一个机器周期1us,指令有单周期指令和双周期指令,一般指令都是单周期指令,一个单周期指令1us,双周期2us,如果函数有1000条指令也才1ms,所以没问题,只要不加延时函数一般没事。
键盘
计算机键盘是ps2型的接口,键盘每按下一个值,内部有一个编码器,编码完后发给计算机,计算机有专门给键盘开的中断,优先级比较高,外接的任何响应计算机会立马从中断中收到数据,看出是按得哪一个按键。
单片机的是非编码键盘。非编码键盘又分为独立键盘和行列式(又称为矩阵式)键盘。
独立键盘的典型接法。32个IO口都可以作为输入输出,所以在哪个口接键盘都可以,检测按下:P1~P3IO口线内均有固定的上拉电阻,当这三个准双向IO口作输入口使用时,要向该口先写1,然后才能读取这个口的状态。原本P3.4=1,当键盘按下,P3.4接地了,TTL电路中IO口不是高阻态、没有三态状态,它与和它相连的线是线与的关系。如果P3.4变为低电平了就说明按下了。
类似这两根线,只要有一根线为0,那么整个线路就是低电平。还有一种是线或的关系,当某一根线和具有三态功能的线相连,当三态IO口处于高阻态状态,和它连接的线产生线或的关系,跟他连接的线是高电平,高阻态就会变为高电平。
单片机中独立键盘和矩阵键盘的接法。
接下来写个代码试试独立键盘
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit led0=P1^0;
7 sbit key0=P3^0;
8
9 void main()
10 {
11 while(1)
12 {
13 if(key0==0)
14 led0=0;
15 else
16 led0=1;
17 }
18 }
这就是单片机的输入了,之前学的全都是单片机的输出。
但这个代码其实是有毛病的,这样你可能看不出来,接下来再写一个程序看看,数码管初始0,按一下键盘+1,到10归0;
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit WEI=P2^7;
7 sbit DUAN=P2^6;
8
9 sbit led0=P1^0;
10 sbit key0=P3^0;
11
12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
13 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
14 uchar num=0;
15
16 void main()
17 {
18 WEI=1;
19 P0=0xfe;
20 WEI=0;
21 while(1)
22 {
23 if(key0==0)
24 {
25 led0=0;
26 num++;
27 if(num>9)
28 {
29 num=0;
30 }
31 }
32 else
33 {
34 led0=1;
35 }
36 DUAN=1;
37 P0=Table[num];
38 DUAN=0;
39 }
40 }
你会发现按下键盘,数码管不是+1,而是随机的。
原因如下:
右侧为硬件消抖,所以不需要看,有时软件消抖不方便或者不想浪费资源就用硬件消抖
抖动时就会检测你按了很多次。
你可能会说上面的代码可能就是按了一下,但是很长时间没抬起,所以进入了很多次if,从而num++许多次,那么我们加上松手检测。
按键按下时key0=0,那么只要当key0==0时为死循环就可以了
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit WEI=P2^7;
7 sbit DUAN=P2^6;
8
9 sbit led0=P1^0;
10 sbit key0=P3^0;
11
12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
13 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
14 uchar num=0;
15 void Delay1ms();
16 void delay(int n);
17
18 void main()
19 {
20 WEI=1;
21 P0=0xfe;
22 WEI=0;
23 while(1)
24 {
25 if(key0==0)
26 {
27 led0=0;
28 num++;
29 if(num>9)
30 {
31 num=0;
32 }
33 while(!key0);
34 }
35 else
36 {
37 led0=1;
38 }
39 DUAN=1;
40 P0=Table[num];
41 DUAN=0;
42 }
43 }
44
45 void delay(int n)
46 {
47 while(n--)
48 {
49 Delay1ms();
50 }
51 }
52 void Delay1ms() //@12.000MHz
53 {
54 unsigned char i, j;
55
56 i = 2;
57 j = 239;
58 do
59 {
60 while (--j);
61 } while (--i);
62 }
这样就能证明存在抖动的现象。
我们只去除按下时的抖动,松开时的不需要,如何去呢?用延时函数,当按下去时我们延时10ms,按键按下抖动大约5ms左右,那么为了稳定我们可以写10ms,低电平保持的时间大约有20ms,所以消抖用掉5ms,还剩15ms,我们完全可以侧得到。
下面是消抖的代码:
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit WEI=P2^7;
7 sbit DUAN=P2^6;
8
9 sbit led0=P1^0;
10 sbit key0=P3^0;
11
12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
13 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
14 uchar num=0;
15 void Delay1ms();
16 void delay(int n);
17
18 void main()
19 {
20 WEI=1;
21 P0=0xfe;
22 WEI=0;
23 while(1)
24 {
25 if(key0==0)
26 {
27 delay(10);
28 if(key0==0)
29 {
30 led0=0;
31 num++;
32 if(num>9)
33 {
34 num=0;
35 }
36 }
37 while(!key0);
38 }
39 else
40 {
41 led0=1;
42 }
43 DUAN=1;
44 P0=Table[num];
45 DUAN=0;
46 }
47 }
48
49 void delay(int n)
50 {
51 while(n--)
52 {
53 Delay1ms();
54 }
55 }
56 void Delay1ms() //@12.000MHz
57 {
58 unsigned char i, j;
59
60 i = 2;
61 j = 239;
62 do
63 {
64 while (--j);
65 } while (--i);
66 }
这样就没有问题了,这里最后的松手检测放在第二层if(key0==0)里面和外面都一样。
有时为了更加稳定会在末尾再加上一次消抖,如下:
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit WEI=P2^7;
7 sbit DUAN=P2^6;
8
9 sbit led0=P1^0;
10 sbit key0=P3^0;
11
12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
13 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
14 uchar num=0;
15 void Delay1ms();
16 void delay(int n);
17
18 void main()
19 {
20 WEI=1;
21 P0=0xfe;
22 WEI=0;
23 while(1)
24 {
25 if(key0==0)
26 {
27 delay(10);
28 if(key0==0)
29 {
30 led0=0;
31 num++;
32 if(num>9)
33 {
34 num=0;
35 }
36 }
37 while(!key0);
38 delay(10);
39 while(!key0);
40 }
41 else
42 {
43 led0=1;
44 }
45 DUAN=1;
46 P0=Table[num];
47 DUAN=0;
48 }
49 }
50
51 void delay(int n)
52 {
53 while(n--)
54 {
55 Delay1ms();
56 }
57 }
58 void Delay1ms() //@12.000MHz
59 {
60 unsigned char i, j;
61
62 i = 2;
63 j = 239;
64 do
65 {
66 while (--j);
67 } while (--i);
68 }
延时去抖改为5ms也是可以的,尽量不要让cpu有过多的等待。
接下来是矩阵键盘
这是典型的矩阵键盘的接法(总线方式):
你也可以自己仿照做成2*2,3*3,甚至4*5的,这时一组IO口不够用,那就接到别的IO口,检测的原理都是一样的。
检测原理:
其实和独立键盘都是一样的,都是检测低电平,但是四行四列全部连得IO口,没有接地的,所以低电平由你写程序给予。
先给P3.0~3.3这样赋值,然后读取P3.4~3.7的数据,如果第一个键按下去了,那么P3.4就是0(线与的关系,没忘吧?),同一时刻你只能按下一个键,检测时都是有先后顺序的。那么P3的值就是如下:
如果是按下的第1行第2列的键,那么就会如下:
以此类推。如果都没按下去,那么P3.4~P3.7都是1。我们就根据每一次读取的值判断按下去的是哪一个键。这就是第一行的检测,矩阵键盘的检测要依次对四行进行扫描,第一次P3.0=0,然后读取四列,如果没有按下去,那么下一次就是把P3.1=0,其它三个为1,也是这样判断。只要有任何一个键被按下,就跳出整个大循环,直接退出扫描程序。如果你是两个一起按下去的,也是有先后顺序的,那么后面的也检测不到。
先让P3=0xfe,在定义一个变量temp,保存P3的值(temp=P3),接下来我们要读的实际上是P3的高4位,只想知道高4位什么状态,然后再让temp&0xf0(按位与),如果一个都没按下,那么高4位全是1,低4位不管(任何数和0与都是0),那么temp&0xf0的结果还是0xf0,如果不是0xf0就是有键按下,如果第一个键按下了,那么P3.7~3.4就是1110,后面低4位不管,那么和0xf0与的时候就是1110 0000,不等于0xf0(1111 0000),就知道有键按下了,之后延时一下,再检测一遍,如果还是这个数,0xe0,那么就知道第一个键按下去了,用一个变量num,num=1,标记第一个键。一共扫描16次(第一行赋值0,扫描4列,第二行0,扫描4列......)。
再举一下例子:
例如按下去的是第一行第二列的键。
那么第一次赋值P3=1111 1110后,temp就会为1101 1110,temp&0xfe=1101 0000,然后和0xfe比较即可,之后num=按下去的键的值。
写程序看看,按下键盘,数码管显示对应的值,键盘的值分别为,第一行:0123,只检测第一行的。
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit WEI=P2^7;
7 sbit DUAN=P2^6;
8
9 sbit led0=P1^0;
10 sbit key0=P3^0;
11
12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
13 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
14 uchar num=0,temp;
15 void Delay1ms();
16 void delay(int n);
17
18 void main()
19 {
20 DUAN=1;
21 P0=0x00;
22 DUAN=0;
23 WEI=1;
24 P0=0xfe;
25 WEI=0;
26 while(1)
27 {
28 P3=0xfe;
29 temp=P3;
30 temp=temp&0xf0;
31 while(temp!=0xf0)
32 {
33 delay(5);
34 temp=P3;
35 temp=temp&0xf0;
36 while(temp!=0xf0)
37 {
38 temp=P3;
39 switch(temp)
40 {
41 case 0xee:num=1;break;
42 case 0xde:num=2;break;
43 case 0xbe:num=3;break;
44 case 0x7e:num=4;break;
45 }
46 DUAN=1;
47 P0=Table[num-1];
48 DUAN=0;
49 }
50 }
51 }
52 }
53
54 void delay(int n)
55 {
56 while(n--)
57 {
58 Delay1ms();
59 }
60 }
61 void Delay1ms() //@12.000MHz
62 {
63 unsigned char i, j;
64
65 i = 2;
66 j = 239;
67 do
68 {
69 while (--j);
70 } while (--i);
71 }
明明用if更简单,郭天祥竟然用while
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit WEI=P2^7;
7 sbit DUAN=P2^6;
8
9 sbit led0=P1^0;
10 sbit key0=P3^0;
11
12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
13 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
14 uchar num=0,temp;
15 void Delay1ms();
16 void delay(int n);
17
18 void main()
19 {
20 DUAN=1;
21 P0=0x00;
22 DUAN=0;
23 WEI=1;
24 P0=0xfe;
25 WEI=0;
26 while(1)
27 {
28 P3=0xfe;
29 temp=P3;
30 temp=temp&0xf0;
31 if(temp!=0xf0)
32 {
33 delay(5);
34 temp=P3;
35 temp=temp&0xf0;
36 if(temp!=0xf0)
37 {
38 switch(temp)
39 {
40 case 0xe0:num=1;break;
41 case 0xd0:num=2;break;
42 case 0xb0:num=3;break;
43 case 0x70:num=4;break;
44 }
45 DUAN=1;
46 P0=Table[num-1];
47 DUAN=0;
48 }
49 }
50 }
51 }
52
53 void delay(int n)
54 {
55 while(n--)
56 {
57 Delay1ms();
58 }
59 }
60 void Delay1ms() //@12.000MHz
61 {
62 unsigned char i, j;
63
64 i = 2;
65 j = 239;
66 do
67 {
68 while (--j);
69 } while (--i);
70 }
然后我们再把剩下四行也加上看看
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit WEI=P2^7;
7 sbit DUAN=P2^6;
8
9 sbit led0=P1^0;
10 sbit key0=P3^0;
11
12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
13 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
14 uchar num=0,temp;
15 void Delay1ms();
16 void delay(int n);
17
18 void main()
19 {
20 DUAN=1;
21 P0=0x00;
22 DUAN=0;
23 WEI=1;
24 P0=0xfe;
25 WEI=0;
26 while(1)
27 {
28 //第一行
29 P3=0xfe;
30 temp=P3;
31 temp=temp&0xf0;
32 while(temp!=0xf0)
33 {
34 delay(5);
35 temp=P3;
36 temp=temp&0xf0;
37 while(temp!=0xf0)
38 {
39 temp=P3;
40 switch(temp)
41 {
42 case 0xee:num=1;break;
43 case 0xde:num=2;break;
44 case 0xbe:num=3;break;
45 case 0x7e:num=4;break;
46 }
47
48 /*没有这里的话,如果按下某一行,就会一直进入上面这个while循环,即使松手也出不来,
49 有了它,不松手就一直在下面的循环,松手后就会改变temp的值,变为0xf0*/
50 while(temp!=0xf0)
51 {
52 temp=P3;
53 temp=temp&0xf0;
54 }
55 DUAN=1;
56 P0=Table[num-1];
57 DUAN=0;
58 }
59 }
60
61 //第二行
62 P3=0xfd;
63 temp=P3;
64 temp=temp&0xf0;
65 while(temp!=0xf0)
66 {
67 delay(5);
68 temp=P3;
69 temp=temp&0xf0;
70 while(temp!=0xf0)
71 {
72 temp=P3;
73 switch(temp)
74 {
75 case 0xed:num=5;break;
76 case 0xdd:num=6;break;
77 case 0xbd:num=7;break;
78 case 0x7d:num=8;break;
79 }
80 while(temp!=0xf0)
81 {
82 temp=P3;
83 temp=temp&0xf0;
84 }
85 DUAN=1;
86 P0=Table[num-1];
87 DUAN=0;
88 }
89 }
90
91 //第三行
92 P3=0xfb;
93 temp=P3;
94 temp=temp&0xf0;
95 while(temp!=0xf0)
96 {
97 delay(5);
98 temp=P3;
99 temp=temp&0xf0;
100 while(temp!=0xf0)
101 {
102 temp=P3;
103 switch(temp)
104 {
105 case 0xeb:num=9;break;
106 case 0xdb:num=10;break;
107 case 0xbb:num=11;break;
108 case 0x7b:num=12;break;
109 }
110 while(temp!=0xf0)
111 {
112 temp=P3;
113 temp=temp&0xf0;
114 }
115 DUAN=1;
116 P0=Table[num-1];
117 DUAN=0;
118 }
119 }
120
121 //第四行
122 P3=0xf7;
123 temp=P3;
124 temp=temp&0xf0;
125 while(temp!=0xf0)
126 {
127 delay(5);
128 temp=P3;
129 temp=temp&0xf0;
130 while(temp!=0xf0)
131 {
132 temp=P3;
133 switch(temp)
134 {
135 case 0xe7:num=13;break;
136 case 0xd7:num=14;break;
137 case 0xb7:num=15;break;
138 case 0x77:num=16;break;
139 }
140 while(temp!=0xf0)
141 {
142 temp=P3;
143 temp=temp&0xf0;
144 }
145 DUAN=1;
146 P0=Table[num-1];
147 DUAN=0;
148 }
149 }
150 }
151 }
152
153 void delay(int n)
154 {
155 while(n--)
156 {
157 Delay1ms();
158 }
159 }
160 void Delay1ms() //@12.000MHz
161 {
162 unsigned char i, j;
163
164 i = 2;
165 j = 239;
166 do
167 {
168 while (--j);
169 } while (--i);
170 }
我们可以把扫描改为函数,方便移植到别的程序
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit WEI=P2^7;
7 sbit DUAN=P2^6;
8
9 sbit led0=P1^0;
10 sbit key0=P3^0;
11
12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
13 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
14 uchar num=17,temp;//num一开始为17,这样-1后就是不显示,用于最初没有按键按下时的情况
15 void Delay1ms();
16 void delay(int n);
17 uchar keyscan();
18 void main()
19 {
20 DUAN=1;
21 P0=0x00;
22 DUAN=0;
23 WEI=1;
24 P0=0xfe;
25 WEI=0;
26 while(1)
27 {
28 DUAN=1;
29 P0=Table[keyscan()-1];
30 DUAN=0;
31 }
32 }
33
34 void delay(int n)
35 {
36 while(n--)
37 {
38 Delay1ms();
39 }
40 }
41 void Delay1ms() //@12.000MHz
42 {
43 unsigned char i, j;
44
45 i = 2;
46 j = 239;
47 do
48 {
49 while (--j);
50 } while (--i);
51 }
52
53 uchar keyscan()
54 {
55 //第一行
56 P3=0xfe;
57 temp=P3;
58 temp=temp&0xf0;
59 while(temp!=0xf0)
60 {
61 delay(5);
62 temp=P3;
63 temp=temp&0xf0;
64 while(temp!=0xf0)
65 {
66 temp=P3;
67 switch(temp)
68 {
69 case 0xee:num=1;break;
70 case 0xde:num=2;break;
71 case 0xbe:num=3;break;
72 case 0x7e:num=4;break;
73 }
74
75 /*没有这里的话,如果按下某一行,就会一直进入上面这个while循环,即使松手也出不来,
76 有了它,不松手就一直在下面的循环,松手后就会改变temp的值,变为0xf0*/
77 while(temp!=0xf0)
78 {
79 temp=P3;
80 temp=temp&0xf0;
81 }
82 //放入函数里有就不需要这个显示了
83 // DUAN=1;
84 // P0=Table[num-1];
85 // DUAN=0;
86 }
87 }
88
89 //第二行
90 P3=0xfd;
91 temp=P3;
92 temp=temp&0xf0;
93 while(temp!=0xf0)
94 {
95 delay(5);
96 temp=P3;
97 temp=temp&0xf0;
98 while(temp!=0xf0)
99 {
100 temp=P3;
101 switch(temp)
102 {
103 case 0xed:num=5;break;
104 case 0xdd:num=6;break;
105 case 0xbd:num=7;break;
106 case 0x7d:num=8;break;
107 }
108 while(temp!=0xf0)
109 {
110 temp=P3;
111 temp=temp&0xf0;
112 }
113 // DUAN=1;
114 // P0=Table[num-1];
115 // DUAN=0;
116 }
117 }
118
119 //第三行
120 P3=0xfb;
121 temp=P3;
122 temp=temp&0xf0;
123 while(temp!=0xf0)
124 {
125 delay(5);
126 temp=P3;
127 temp=temp&0xf0;
128 while(temp!=0xf0)
129 {
130 temp=P3;
131 switch(temp)
132 {
133 case 0xeb:num=9;break;
134 case 0xdb:num=10;break;
135 case 0xbb:num=11;break;
136 case 0x7b:num=12;break;
137 }
138 while(temp!=0xf0)
139 {
140 temp=P3;
141 temp=temp&0xf0;
142 }
143 // DUAN=1;
144 // P0=Table[num-1];
145 // DUAN=0;
146 }
147 }
148
149 //第四行
150 P3=0xf7;
151 temp=P3;
152 temp=temp&0xf0;
153 while(temp!=0xf0)
154 {
155 delay(5);
156 temp=P3;
157 temp=temp&0xf0;
158 while(temp!=0xf0)
159 {
160 temp=P3;
161 switch(temp)
162 {
163 case 0xe7:num=13;break;
164 case 0xd7:num=14;break;
165 case 0xb7:num=15;break;
166 case 0x77:num=16;break;
167 }
168 while(temp!=0xf0)
169 {
170 temp=P3;
171 temp=temp&0xf0;
172 }
173 // DUAN=1;
174 // P0=Table[num-1];
175 // DUAN=0;
176 }
177 }
178 return num;
179 }
同样的也可以把显示用函数封装起来。这里就不给代码了。
接下来我们看下用if不用while的。(末尾加上松手检测比while好多了)
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit WEI=P2^7;
7 sbit DUAN=P2^6;
8
9 sbit led0=P1^0;
10 sbit key0=P3^0;
11
12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
13 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
14 uchar num=0,temp;
15 void Delay1ms();
16 void delay(int n);
17
18 void main()
19 {
20 DUAN=1;
21 P0=0x00;
22 DUAN=0;
23 WEI=1;
24 P0=0xfe;
25 WEI=0;
26 while(1)
27 {
28 //第一行
29 P3=0xfe;
30 temp=P3;
31 temp=temp&0xf0;
32 if(temp!=0xf0)
33 {
34 delay(5);
35 temp=P3;
36 temp=temp&0xf0;
37 if(temp!=0xf0)
38 {
39 temp=P3;
40 switch(temp)
41 {
42 case 0xee:num=1;break;
43 case 0xde:num=2;break;
44 case 0xbe:num=3;break;
45 case 0x7e:num=4;break;
46 }
47
48 // /*没有这里的话,如果按下某一行,就会一直进入上面这个while循环,即使松手也出不来,
49 // 有了它,不松手就一直在下面的循环,松手后就会改变temp的值,变为0xf0*/
50 // while(temp!=0xf0)
51 // {
52 // temp=P3;
53 // temp=temp&0xf0;
54 // }
55 DUAN=1;
56 P0=Table[num-1];
57 DUAN=0;
58 }
59 }
60
61 //第二行
62 P3=0xfd;
63 temp=P3;
64 temp=temp&0xf0;
65 if(temp!=0xf0)
66 {
67 delay(5);
68 temp=P3;
69 temp=temp&0xf0;
70 if(temp!=0xf0)
71 {
72 temp=P3;
73 switch(temp)
74 {
75 case 0xed:num=5;break;
76 case 0xdd:num=6;break;
77 case 0xbd:num=7;break;
78 case 0x7d:num=8;break;
79 }
80 // while(temp!=0xf0)
81 // {
82 // temp=P3;
83 // temp=temp&0xf0;
84 // }
85 DUAN=1;
86 P0=Table[num-1];
87 DUAN=0;
88 }
89 }
90
91 //第三行
92 P3=0xfb;
93 temp=P3;
94 temp=temp&0xf0;
95 if(temp!=0xf0)
96 {
97 delay(5);
98 temp=P3;
99 temp=temp&0xf0;
100 if(temp!=0xf0)
101 {
102 temp=P3;
103 switch(temp)
104 {
105 case 0xeb:num=9;break;
106 case 0xdb:num=10;break;
107 case 0xbb:num=11;break;
108 case 0x7b:num=12;break;
109 }
110 // while(temp!=0xf0)
111 // {
112 // temp=P3;
113 // temp=temp&0xf0;
114 // }
115 DUAN=1;
116 P0=Table[num-1];
117 DUAN=0;
118 }
119 }
120
121 //第四行
122 P3=0xf7;
123 temp=P3;
124 temp=temp&0xf0;
125 if(temp!=0xf0)
126 {
127 delay(5);
128 temp=P3;
129 temp=temp&0xf0;
130 if(temp!=0xf0)
131 {
132 temp=P3;
133 switch(temp)
134 {
135 case 0xe7:num=13;break;
136 case 0xd7:num=14;break;
137 case 0xb7:num=15;break;
138 case 0x77:num=16;break;
139 }
140 // while(temp!=0xf0)
141 // {
142 // temp=P3;
143 // temp=temp&0xf0;
144 // }
145 DUAN=1;
146 P0=Table[num-1];
147 DUAN=0;
148 }
149 }
150 }
151 }
152
153 void delay(int n)
154 {
155 while(n--)
156 {
157 Delay1ms();
158 }
159 }
160 void Delay1ms() //@12.000MHz
161 {
162 unsigned char i, j;
163
164 i = 2;
165 j = 239;
166 do
167 {
168 while (--j);
169 } while (--i);
170 }
不过这个矩阵键盘方法太麻烦了,浪费资源,看看清翔的或者别人的,都比这个简洁。
评论(0)
您还未登录,请登录后发表或查看评论