当前位置:   article > 正文

蓝桥杯单片机备战(七)矩阵键盘的扫描原理及其应用_矩阵键盘扫描

矩阵键盘扫描

1.扫描原理

1.首先还是先观察电路图

我们知道要想控制独立按键的话首先要先使J5跳帽连接到1和2,这时P44和第一列键盘也就是S4~S7连上了

2.那要怎么来实现按键状态的读取呢?我们使用扫描的思想,也就是逐行逐列读取

这里我们选择逐行读取,先读取第一行(也就是S7、S11、S15、S19),先将P30口置低,P31P32P33置高,然后将代表四列的P34P35P42P44置高,此时检测P34P35P42P44口,如果P44是低电平,那么证明S7被按下了,如果P42是低电平,证明S11被按下了,以此类推就检测了所有的按键。


2.代码实现

注意事项!!!!

我们导入的头文件“reg52.h”中并没有对于P4口的定义

我们需要自行查找数据手册来得知P4口寄存器的地址

查找手册得知P4口的地址为C0H,我们需要在头文件或者用户编写的文件中添加这个定义:

这里再补充一个点:“sfr”

SFR全称为:special function register(翻译为:特殊功能寄存器)

在单片机的世界里,并不会识别所谓的“P1”,只会识别P1这个IO口的地址0x90,sfr是用来给这个地址赋予一个名字的,sfr P1 = 0x90,代表的意思就是给地址0x90赋予一个名字P1(有点类似与sbit、define这种东西,有机会会再写一篇笔记来充分认识51单片机bit、sbin、sfr、sfr_16的区别。

  1. #include "reg52.h"
  2. sbit R1 = P3^0;//第一行的P3^0口为R1,下面以此类推
  3. sbit R2 = P3^1;
  4. sbit R3 = P3^2;
  5. sbit R4 = P3^3;
  6. sbit C1 = P4^4;
  7. sbit C2 = P4^2;
  8. sbit C3 = P3^5;
  9. sbit C4 = P3^4;
  10. unsigned char KEY_number = 0;//按键按下标志位
  11. void Delay(unsigned char t) //延时函数
  12. {
  13. while(t--)
  14. {
  15. unsigned char i, j;
  16. i = 15;
  17. j = 90;
  18. do
  19. {
  20. while (--j);
  21. } while (--i);
  22. }
  23. }
  24. unsigned char code SMG_duanma[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
  25. 0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0x7f}; // 数码管的断码表
  26. void HC138Init(unsigned char n)
  27. {
  28. switch(n)
  29. {
  30. case 4:
  31. P2 = (P2 & 0x1f) | 0x80;//让Y4输出低电平,此时Y4C为高电平
  32. break;
  33. case 5:
  34. P2 = (P2 & 0x1f) | 0xa0;//让Y5输出低电平,此时Y5C为高电平
  35. break;
  36. case 6:
  37. P2 = (P2 & 0x1f) | 0xc0;//让Y6输出低电平,此时Y6C为高电平
  38. break;
  39. case 7:
  40. P2 = (P2 & 0x1f) | 0xe0;//让Y7输出低电平,此时Y7C为高电平
  41. break;
  42. }
  43. }
  44. void showSMG(unsigned char position,unsigned char number) //字符显示函数
  45. {
  46. HC138Init(6); // 选通Y6C
  47. switch(position)
  48. {
  49. case 1://第1个位置
  50. P0 = 0x01;
  51. break;
  52. case 2://第2个位置
  53. P0 = 0x02;
  54. break;
  55. case 3://第3个位置
  56. P0 = 0x04;
  57. break;
  58. case 4://第4个位置
  59. P0 = 0x08;
  60. break;
  61. case 5://第5个位置
  62. P0 = 0x10;
  63. break;
  64. case 6://第6个位置
  65. P0 = 0x20;
  66. break;
  67. case 7://第7个位置
  68. P0 = 0x40;
  69. break;
  70. case 8://第8个位置
  71. P0 = 0x80;
  72. break;
  73. }
  74. HC138Init(7); // 选通Y7C
  75. if(number == '0') //下面是显示各个字符
  76. P0 = SMG_duanma[0];
  77. else if(number == '1')
  78. P0 = SMG_duanma[1];
  79. else if(number == '2')
  80. P0 = SMG_duanma[2];
  81. else if(number == '3')
  82. P0 = SMG_duanma[3];
  83. else if(number == '4')
  84. P0 = SMG_duanma[4];
  85. else if(number == '5')
  86. P0 = SMG_duanma[5];
  87. else if(number == '6')
  88. P0 = SMG_duanma[6];
  89. else if(number == '7')
  90. P0 = SMG_duanma[7];
  91. else if(number == '8')
  92. P0 = SMG_duanma[8];
  93. else if(number == '9')
  94. P0 = SMG_duanma[9];
  95. else if(number == 'a')
  96. P0 = SMG_duanma[10];
  97. else if(number == 'b')
  98. P0 = SMG_duanma[11];
  99. else if(number == 'c')
  100. P0 = SMG_duanma[12];
  101. else if(number == 'd')
  102. P0 = SMG_duanma[13];
  103. else if(number == 'e')
  104. P0 = SMG_duanma[14];
  105. else if(number == 'f')
  106. P0 = SMG_duanma[15];
  107. else if(number == '-')
  108. P0 = SMG_duanma[16];
  109. else if(number == '.')
  110. P0 = SMG_duanma[17];
  111. }
  112. unsigned char KEYscan()//矩阵键盘扫描函数,该函数将返回一个KEY_number,这个变量代表被按下的按键,若KEY_number=4,则代表S4被按下
  113. {
  114. /*扫描第一行*/
  115. R1 = 0;//先将第一行置低
  116. R2 = R3 = R4 = 1;//再将第二三四行置高
  117. if(C1 == 0)//第一行第一列按键S7被按下
  118. {
  119. Delay(20);//按键消抖
  120. if(C1 == 0)
  121. {
  122. while(C1 == 0);//松手检测,松手时C1重新变成高阻态,向下执行
  123. Delay(20);//按键消抖
  124. KEY_number = 7;//标志位置7
  125. }
  126. }
  127. else if(C2 == 0)//第一行第二列按键S11被按下
  128. {
  129. Delay(20);//按键消抖
  130. if(C2 == 0)
  131. {
  132. while(C2 == 0);//松手检测,松手时C2重新变成高阻态,向下执行
  133. Delay(20);//按键消抖
  134. KEY_number = 11;//标志位置11
  135. }
  136. }
  137. else if(C3 == 0)//第一行第三列按键S15被按下
  138. {
  139. Delay(20);//按键消抖
  140. if(C3 == 0)
  141. {
  142. while(C3 == 0);//松手检测,松手时C3重新变成高阻态,向下执行
  143. Delay(20);//按键消抖
  144. KEY_number = 15;//标志位置15
  145. }
  146. }
  147. else if(C4 == 0)//第一行第四列按键S19被按下
  148. {
  149. Delay(20);//按键消抖
  150. if(C4 == 0)
  151. {
  152. while(C4 == 0);//松手检测,松手时C4重新变成高阻态,向下执行
  153. Delay(20);//按键消抖
  154. KEY_number = 19;//标志位置19
  155. }
  156. }
  157. /*扫描第二行*/
  158. R2 = 0;//先将第二行置低
  159. R1 = R3 = R4 = 1;//再将第一三四行置高
  160. if(C1 == 0)//第二行第一列按键S6被按下
  161. {
  162. Delay(20);//按键消抖
  163. if(C1 == 0)
  164. {
  165. while(C1 == 0);//松手检测,松手时C1重新变成高阻态,向下执行
  166. Delay(20);//按键消抖
  167. KEY_number = 6;//标志位置6
  168. }
  169. }
  170. else if(C2 == 0)//第二行第二列按键S10被按下
  171. {
  172. Delay(20);//按键消抖
  173. if(C2 == 0)
  174. {
  175. while(C2 == 0);//松手检测,松手时C2重新变成高阻态,向下执行
  176. Delay(20);//按键消抖
  177. KEY_number = 10;//标志位置10
  178. }
  179. }
  180. else if(C3 == 0)//第二行第三列按键S14被按下
  181. {
  182. Delay(20);//按键消抖
  183. if(C3 == 0)
  184. {
  185. while(C3 == 0);//松手检测,松手时C3重新变成高阻态,向下执行
  186. Delay(20);//按键消抖
  187. KEY_number = 14;//标志位置14
  188. }
  189. }
  190. else if(C4 == 0)//第二行第四列按键S18被按下
  191. {
  192. Delay(20);//按键消抖
  193. if(C4 == 0)
  194. {
  195. while(C4 == 0);//松手检测,松手时C4重新变成高阻态,向下执行
  196. Delay(20);//按键消抖
  197. KEY_number = 18;//标志位置18
  198. }
  199. }
  200. /*扫描第三行*/
  201. R3 = 0;//先将第三行置低
  202. R1 = R2 = R4 = 1;//再将第一二四行置高
  203. if(C1 == 0)//第三行第一列按键S5被按下
  204. {
  205. Delay(20);//按键消抖
  206. if(C1 == 0)
  207. {
  208. while(C1 == 0);//松手检测,松手时C1重新变成高阻态,向下执行
  209. Delay(20);//按键消抖
  210. KEY_number = 5;//标志位置5
  211. }
  212. }
  213. else if(C2 == 0)//第三行第二列按键S9被按下
  214. {
  215. Delay(20);//按键消抖
  216. if(C2 == 0)
  217. {
  218. while(C2 == 0);//松手检测,松手时C2重新变成高阻态,向下执行
  219. Delay(20);//按键消抖
  220. KEY_number = 9;//标志位置9
  221. }
  222. }
  223. else if(C3 == 0)//第三行第三列按键S13被按下
  224. {
  225. Delay(20);//按键消抖
  226. if(C3 == 0)
  227. {
  228. while(C3 == 0);//松手检测,松手时C3重新变成高阻态,向下执行
  229. Delay(20);//按键消抖
  230. KEY_number = 13;//标志位置13
  231. }
  232. }
  233. else if(C4 == 0)//第三行第四列按键S17被按下
  234. {
  235. Delay(20);//按键消抖
  236. if(C4 == 0)
  237. {
  238. while(C4 == 0);//松手检测,松手时C4重新变成高阻态,向下执行
  239. Delay(20);//按键消抖
  240. KEY_number = 17;//标志位置17
  241. }
  242. }
  243. /*扫描第四行*/
  244. R4 = 0;//先将第四行置低
  245. R1 = R2 = R3 = 1;//再将第一二三行置高
  246. if(C1 == 0)//第四行第一列按键S4被按下
  247. {
  248. Delay(20);//按键消抖
  249. if(C1 == 0)
  250. {
  251. while(C1 == 0);//松手检测,松手时C1重新变成高阻态,向下执行
  252. Delay(20);//按键消抖
  253. KEY_number = 4;//标志位置4
  254. }
  255. }
  256. else if(C2 == 0)//第四行第二列按键S8被按下
  257. {
  258. Delay(20);//按键消抖
  259. if(C2 == 0)
  260. {
  261. while(C2 == 0);//松手检测,松手时C2重新变成高阻态,向下执行
  262. Delay(20);//按键消抖
  263. KEY_number = 8;//标志位置8
  264. }
  265. }
  266. else if(C3 == 0)//第四行第三列按键S12被按下
  267. {
  268. Delay(20);//按键消抖
  269. if(C3 == 0)
  270. {
  271. while(C3 == 0);//松手检测,松手时C3重新变成高阻态,向下执行
  272. Delay(20);//按键消抖
  273. KEY_number = 12;//标志位置12
  274. }
  275. }
  276. else if(C4 == 0)//第四行第四列按键S16被按下
  277. {
  278. Delay(20);//按键消抖
  279. if(C4 == 0)
  280. {
  281. while(C4 == 0);//松手检测,松手时C4重新变成高阻态,向下执行
  282. Delay(20);//按键消抖
  283. KEY_number = 16;//标志位置16
  284. }
  285. }
  286. //四行都扫描完之后判断一下,如果所有按键都没有按下将标志位置为0
  287. if(KEY_number != 4 & KEY_number != 5 & KEY_number != 6 & KEY_number != 7 & KEY_number != 8 &
  288. KEY_number != 9 & KEY_number != 10 & KEY_number != 11 & KEY_number != 12 & KEY_number != 13 &
  289. KEY_number != 14 & KEY_number != 15 & KEY_number != 16 & KEY_number != 17 & KEY_number != 18 & KEY_number != 19)
  290. {
  291. KEY_number = 0;
  292. }
  293. return KEY_number;//返回扫描结果
  294. }
  295. void main()
  296. {
  297. unsigned char KEYnumber = 0;
  298. while(1)
  299. {
  300. KEYnumber = KEYscan();
  301. if(KEYnumber == 4)
  302. {
  303. showSMG(1,'0');
  304. Delay(1);
  305. showSMG(2,'4');
  306. Delay(1);
  307. }
  308. else if(KEYnumber == 5)
  309. {
  310. showSMG(1,'0');
  311. Delay(1);
  312. showSMG(2,'5');
  313. Delay(1);
  314. }
  315. else if(KEYnumber == 6)
  316. {
  317. showSMG(1,'0');
  318. Delay(1);
  319. showSMG(2,'6');
  320. Delay(1);
  321. }
  322. else if(KEYnumber == 7)
  323. {
  324. showSMG(1,'0');
  325. Delay(1);
  326. showSMG(2,'7');
  327. Delay(1);
  328. }
  329. else if(KEYnumber == 8)
  330. {
  331. showSMG(1,'0');
  332. Delay(1);
  333. showSMG(2,'8');
  334. Delay(1);
  335. }
  336. else if(KEYnumber == 9)
  337. {
  338. showSMG(1,'0');
  339. Delay(1);
  340. showSMG(2,'9');
  341. Delay(1);
  342. }
  343. else if(KEYnumber == 10)
  344. {
  345. showSMG(1,'1');
  346. Delay(1);
  347. showSMG(2,'0');
  348. Delay(1);
  349. }
  350. else if(KEYnumber == 11)
  351. {
  352. showSMG(1,'1');
  353. Delay(1);
  354. showSMG(2,'1');
  355. Delay(1);
  356. }
  357. else if(KEYnumber == 12)
  358. {
  359. showSMG(1,'1');
  360. Delay(1);
  361. showSMG(2,'2');
  362. Delay(1);
  363. }
  364. else if(KEYnumber == 13)
  365. {
  366. showSMG(1,'1');
  367. Delay(1);
  368. showSMG(2,'3');
  369. Delay(1);
  370. }
  371. else if(KEYnumber == 14)
  372. {
  373. showSMG(1,'1');
  374. Delay(1);
  375. showSMG(2,'4');
  376. Delay(1);
  377. }
  378. else if(KEYnumber == 15)
  379. {
  380. showSMG(1,'1');
  381. Delay(1);
  382. showSMG(2,'5');
  383. Delay(1);
  384. }
  385. else if(KEYnumber == 16)
  386. {
  387. showSMG(1,'1');
  388. Delay(1);
  389. showSMG(2,'6');
  390. Delay(1);
  391. }
  392. else if(KEYnumber == 17)
  393. {
  394. showSMG(1,'1');
  395. Delay(1);
  396. showSMG(2,'7');
  397. Delay(1);
  398. }
  399. else if(KEYnumber == 18)
  400. {
  401. showSMG(1,'1');
  402. Delay(1);
  403. showSMG(2,'8');
  404. Delay(1);
  405. }
  406. else if(KEYnumber == 19)
  407. {
  408. showSMG(1,'1');
  409. Delay(1);
  410. showSMG(2,'9');
  411. Delay(1);
  412. }
  413. }
  414. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/563806
推荐阅读
相关标签
  

闽ICP备14008679号