1、矩阵式键盘扫描原理 在矩阵式键盘中,行、列线分别连接到按键开关的两端,行线通过上拉电阻接到+5V上。当无键按下时,行线处于高电平状态;当有键按下时,行、列线将导通,此时,行线电平将由与此行线相连的列线电平决定。这一点是识别矩阵按键是否被按下的关键。然而,矩阵键盘中的行线、列线和多个键相连,各按键按下与否均影响该键所在行线和列线的电平,各按键间将相互影响,因此,必须将行线、列线信号配合起来作适当处理,才能确定闭合键的位置。 扫描方式是利用CPU完成其他工作的空余调用键盘扫描子程序来响应键盘输入的要求。在执行键功能程序时,CPU不再响应键输入要求,直到CPU重新扫描键盘为止。键盘扫描程序一般应包括以下内容: (1)判别有无键按下。 (2)键盘扫描取得闭合键的行、列值。 (3)用计算法或查表法得到键值。 (4)判断闭合键是否释放,如没释放则继续等待。 (5)将闭合键键号保存,同时转去执行该闭合键的功能。 本实验的扫描原理是:先置某列线为0,(比如C1=0[P40 == 0],其他为1),然后判断行线那个为0,即若P4.4为0,则按下的键为S17,若P4.5为0,则按下的键为S13,若P4.6为0,则按下的键为S9,若P4.7为0,则按下的键为S5;以此类推,可以得到其他各列线上的键。 2、去抖概念: 按键是机械器件,按下或者松开时有固定的机械抖动,抖动图如图3.28所示。 图3.28 按键被按下时的电压变化 图3.28看出按键按下和松开的瞬间出现机械抖动,这个抖动时间虽然很短,一般10~15ms,不同按键抖动不同,但对应单片机来说,很轻松就能检测到,单片机是us 级别。但这个结果并不是我们需要的,实际上只进行一次按键操作,但有可能执行了多次按键结果,这就是抖动造成的,所以大多数产品实际使用中都使用了按键去抖功能。 按键去抖分为硬件去抖和软件去抖,硬件去抖最简单的就是按键 2 端并联电容,容量根据实验而定。软件去抖使用方便不增加硬件成本,容易调试,所以现在大都使用软件去抖。 软件去抖原理: (1) 检测到按键按下后进行 10~15ms 延时,用于跳过这个抖动区域 (2) 延时后再检测按键状态,如果没有按下表明是抖动或者干扰造成,如果仍旧按下,可以 认为是真正的按下。并进行对应的操作。 (3) 同样按键释放后也要进行去抖延时,延时后检测按键是否真正释放。 程序样例中没有使用按键释放去抖程序,用户可以参考按下去抖程序自行添加。多数时候按键需要在释放时才起作用,像电脑鼠标一样,这个时候需要检测按键是否释放,如果没有释放则一直等待。 3、主控系统板矩阵键盘的硬件连接
例如:LED1为指示灯,常量;
按键由S17---->>>S8按下显示0-F数码
单片机代码:
1. /*****
2. STC15单片机开发系统演示程序
3. LED1为指示灯,常量;
4. 按键又S17---->>>S8按下显示0-F,顺序暂时没调
5. MCU:STC15W4K56S4 ,晶体频率:11.0592MHz
6. ****/
7. #include <stc15.h>
8. #include <intrins.h>
9. //行端口定义
10. sbit R1=P4^4;
11. sbit R2=P4^5;
12. sbit R3=P4^6;
13. sbit R4=P4^7;
14. //列端口定义
15. sbit C1=P4^0;
16. sbit C2=P4^1;
17. sbit C3=P4^2;
18. sbit C4=P4^3;
19. //共阴极0-f
20. unsigned char code SMG_DuanMa[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //通过code将断码值设置为表格的形式
21. unsigned char num =0;
22. void Delay(unsigned char t)
23. {
24. while(t--);
25. while(t--);
26. while(t--);
27. }
28. void Delay100ms() //@11.0592MHz
29. {
30. unsigned char i, j, k;
31.
32. _nop_();
33. _nop_();
34. i = 5;
35. j = 52;
36. k = 195;
37. do
38. {
39. do
40. {
41. while (--k);
42. } while (--j);
43. } while (--i);
44. }
45.
46. void HC138_Y(unsigned char n) //138译码器控制使能端口
47. {
48. switch(n)
49. {
50. case 1: //数码管---位码--控制输出Y1
51. P0 = ((P0&0xF8)|0x04);
52. break;
53. case 2: //数码管---断码--控制输出Y2
54. P0 = ((P0&0xF8)|0x02);
55. break;
56. case 3: //LED灯--控制输出Y3--控制输出Y3
57. P0 = ((P0&0xF8)|0x06);
58. break;
59. case 4: //ULN2003--电机--继电器--控制输出Y4
60. P0 = ((P0&0xF8)|0x01);
61. break;
62. }
63. }
64. void SMG_Display(unsigned char value)//数码管第一位显示数值
65. {
66. HC138_Y(1);
67. P2 = 0xFE;
68. P0 &= 0xF8;
69. Delay100ms();
70. HC138_Y(2);
71. P2 = value;
72. P0 &= 0xF8;
73. Delay100ms();
74. }
75. void Key(void)//矩阵键盘扫描函数,逐行逐列扫描
76. {
77. /***扫描第一列***/
78. //再进行逐行扫描
79. C1 = 0;
80. R1 = R2 = R3 = R4 = 1;
81. C2 = C3 = C4 = 1;
82. if(R1 == 0)
83. {
84. Delay100ms(); //消抖
85. while(R1 == 0);
86. num = 0;
87. }
88. else if(R2 == 0)
89. {
90. Delay100ms();
91. while(R2 == 0);
92. num = 4;
93. }
94. else if(R3 == 0)
95. {
96. Delay100ms();
97. while(R3 == 0);
98. num = 8;
99. }
100. else if(R4 == 0)
101. {
102. Delay100ms();
103. while(R4 == 0);
104. num = 12;
105. }
106. /***扫描第二列***/
107. C2 = 0;
108. R1 = R2 = R3 = R4 = 1;
109. C1 = C3 = C4 = 1;
110. if(R1 == 0)
111. {
112. Delay100ms();
113. while(R1 == 0);
114. num = 1;
115. }
116. else if(R2 == 0)
117. {
118. Delay100ms();
119. while(R2 == 0);
120. num = 5;
121. }
122. else if(R3 == 0)
123. {
124. Delay100ms();
125. while(R3 == 0);
126. num = 9;
127. }
128. else if(R4 == 0)
129. {
130. Delay100ms();
131. while(R4 == 0);
132. num = 13;
133. }
134. /***扫描第三列***/
135. C3 = 0;
136. R1 = R2 = R3 = R4 = 1;
137. C1 = C2 = C4 = 1;
138. if(R1 == 0)
139. {
140. Delay100ms();
141. while(R1 == 0);
142. num = 2;
143. }
144. else if(R2 == 0)
145. {
146. Delay100ms();
147. while(R2 == 0);
148. num = 6;
149. }
150. else if(R3 == 0)
151. {
152. Delay100ms();
153. while(R3 == 0);
154. num = 10;
155. }
156. else if(R4 == 0)
157. {
158. Delay100ms();
159. while(R4 == 0);
160. num = 14;
161. }
162. /***扫描第四列***/
163. C4 = 0;
164. R1 = R2 = R3 = R4 = 1;
165. C1 = C2 = C3 = 1;
166. if(R1 == 0)
167. {
168. Delay100ms();
169. while(R1 == 0);
170. num = 3;
171. }
172. else if(R2 == 0)
173. {
174. Delay100ms();
175. while(R2 == 0);
176. num = 7;
177. }
178. else if(R3 == 0)
179. {
180. Delay100ms();
181. while(R3 == 0);
182. num = 11;
183. }
184. else if(R4 == 0)
185. {
186. Delay100ms();
187. while(R4 == 0);
188. num = 15;
189. }
190. }
191.
192. void main()
193. {
194. P0M1=0;P0M0=0;
195. P1M1=0;P1M0=0;
196. P2M1=0;P2M0=0;
197. P3M1=0;P3M0=0;
198. P4M1=0;P4M0=0; //按键用到P4端口,记得设置P4端口模式
199. while(1)
200. {
201. Key();
202. if(num>=0)
203. {
204. HC138_Y(1);
205. P2 = 0xFE;
206. P0 &= 0xF8;
207. Delay100ms();
208.
209. HC138_Y(2);
210. P2 = SMG_DuanMa[num];
211. P0 &= 0xF8;
212. Delay100ms();
213. }
214. Delay100ms();
215. HC138_Y(3);
216. P2 = 0x01;
217. Delay100ms();
218. }
}
|