[资料分享] 【蓝桥杯单片机06】矩阵键盘的基本控制

[复制链接]
 楼主| ohy3686 发表于 2018-1-28 16:37 | 显示全部楼层 |阅读模式
【蓝桥杯单片机06】矩阵键盘的基本控制
广东职业技术学院  欧浩源

    掌握了独立按键的处理思路之后,也不是那么轻易的能够学会矩阵键盘的,两者的处理思路有很大的不同,不过,只要把矩阵键盘的本质思想搞清楚了,不过是4X4的还是8X8的,都能够很轻松的处理。

1、矩阵键盘的扫描思想
    与独立按键不同的是,按键的两个引脚都分别连接的单片机的I/O端口,一个作为行信号,另外一个作为列信号。我们以4X4的矩阵键盘为例,试着探讨其工作方式和扫描思路。
矩阵键盘.PNG
    在上面的矩阵键盘中,要识别出黄色按键的按下状态,应该怎么做呢?
    对与矩阵键盘,我们只能逐行扫描,然后读取列的状态信号。如果R3行输出低电平,那么黄色按键如果有按下动作的话,那读取C2列信号也应该为低电平,而该行上其他没有按下动作的按键的列信号则为高电平。因此,我们可以得到矩阵键盘的基本扫描步骤:
    <1> R1输出点电平,R2、R3、R4输出高电平,逐个读取判断列信号,如果都为高电平则R1行上没有按键按下。
    <2> R2输出点电平,R1、R3、R4输出高电平,逐个读取判断列信号。
    <3> R3输出点电平,R1、R2、R4输出高电平,发现C2列信号为低电平,那么可以判断得R3行的C2列的按键有按下动作。
    <4> R4输出点电平,R1、R3、R4输出高电平,逐个读取判断列信号。
    如此循环往复,扫描的按键的状态。
    我们知道有按键按下动作,那么又怎么知道是哪一个按键按下呢?这时,我们最好定义一个键值全局变量,给矩阵行列上的每一个的按键编一个唯一的号码。当扫描的某一行某一列的按键动作后,把对应的编号复制给键值变量,这样我们判断这个键值,就知道是那个按键有触发动作了。
    说得再多,不如一练,看题。
2、单元训练题目
05-矩阵键盘的基本操作.PNG
3、实现源码参考
  1. #include "reg52.h"  

  2. sfr P4   = 0xC0;        

  3. sbit HC138_A = P2^5;        
  4. sbit HC138_B = P2^6;        
  5. sbit HC138_C = P2^7;        

  6. sbit R1 = P3^0;  
  7. sbit R2 = P3^1;
  8. sbit R3 = P3^2;
  9. sbit R4 = P3^3;

  10. sbit C1 = P4^4;
  11. sbit C2 = P4^2;
  12. sbit C3 = P3^5;
  13. sbit C4 = P3^4;

  14. unsigned char keyNum = 0x10;
  15. unsigned char code SMG_NoDot[18] =
  16.     {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
  17.      0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
  18.      0xbf,0x7f};

  19. void Delay(unsigned char t)
  20. {
  21.         while(t--);
  22. }

  23. void Init74HC138(unsigned char n)
  24. {
  25.         switch(n)
  26.         {
  27.                 case 4:
  28.                         HC138_A = 0;
  29.                         HC138_B = 0;
  30.                         HC138_C = 1;
  31.                         break;
  32.                 case 5:
  33.                         HC138_A = 1;
  34.                         HC138_B = 0;
  35.                         HC138_C = 1;
  36.                         break;
  37.                 case 6:
  38.                         HC138_A = 0;
  39.                         HC138_B = 1;
  40.                         HC138_C = 1;
  41.                         break;
  42.                 case 7:
  43.                         HC138_A = 1;
  44.                         HC138_B = 1;
  45.                         HC138_C = 1;
  46.                         break;
  47.                 case 8:
  48.                         HC138_A = 0;
  49.                         HC138_B = 0;
  50.                         HC138_C = 0;
  51.                         break;
  52.         }
  53. }

  54. void ShowKeyNum(unsigned char value)
  55. {
  56.         Init74HC138(6);
  57.         P0 = 0x01;
  58.         Init74HC138(7);
  59.         P0 = value;
  60. }

  61. void ScanKeys()
  62. {
  63.         keyNum = 16;
  64.         R1 = 0;
  65.         R2 = R3 = R4 = 1;
  66.         C1 = C2 = C3 = C4 = 1;
  67.         if(C1 == 0)
  68.         {
  69.                 while(C1 == 0);
  70.                 keyNum = 0;
  71.                 ShowKeyNum(SMG_NoDot[keyNum]);
  72.         }
  73.         else if(C2 == 0)
  74.         {
  75.                 while(C2 == 0);
  76.                 keyNum = 1;
  77.                 ShowKeyNum(SMG_NoDot[keyNum]);
  78.         }
  79.         else if(C3 == 0)
  80.         {
  81.                 while(C3 == 0);
  82.                 keyNum = 2;
  83.                 ShowKeyNum(SMG_NoDot[keyNum]);
  84.         }
  85.         else if(C4 == 0)
  86.         {
  87.                 while(C4 == 0);
  88.                 keyNum = 3;
  89.                 ShowKeyNum(SMG_NoDot[keyNum]);
  90.         }
  91.         
  92.         R2 = 0;
  93.         R1 = R3 = R4 = 1;
  94.         C1 = C2 = C3 = C4 = 1;
  95.         if(C1 == 0)
  96.         {
  97.                 while(C1 == 0);
  98.                 keyNum = 4;
  99.                 ShowKeyNum(SMG_NoDot[keyNum]);
  100.         }
  101.         else if(C2 == 0)
  102.         {
  103.                 while(C2 == 0);
  104.                 keyNum = 5;
  105.                 ShowKeyNum(SMG_NoDot[keyNum]);
  106.         }
  107.         else if(C3 == 0)
  108.         {
  109.                 while(C3 == 0);
  110.                 keyNum = 6;
  111.                 ShowKeyNum(SMG_NoDot[keyNum]);
  112.         }
  113.         else if(C4 == 0)
  114.         {
  115.                 while(C4 == 0);
  116.                 keyNum = 7;
  117.                 ShowKeyNum(SMG_NoDot[keyNum]);
  118.         }
  119.         
  120.         R3 = 0;
  121.         R2 = R1 = R4 = 1;
  122.         C1 = C2 = C3 = C4 = 1;
  123.         if(C1 == 0)
  124.         {
  125.                 while(C1 == 0);
  126.                 keyNum = 8;
  127.                 ShowKeyNum(SMG_NoDot[keyNum]);
  128.         }
  129.         else if(C2 == 0)
  130.         {
  131.                 while(C2 == 0);
  132.                 keyNum = 9;
  133.                 ShowKeyNum(SMG_NoDot[keyNum]);
  134.         }
  135.         else if(C3 == 0)
  136.         {
  137.                 while(C3 == 0);
  138.                 keyNum = 10;
  139.                 ShowKeyNum(SMG_NoDot[keyNum]);
  140.         }
  141.         else if(C4 == 0)
  142.         {
  143.                 while(C4 == 0);
  144.                 keyNum = 11;
  145.                 ShowKeyNum(SMG_NoDot[keyNum]);
  146.         }
  147.         
  148.         R4 = 0;
  149.         R2 = R3 = R1 = 1;
  150.         C1 = C2 = C3 = C4 = 1;
  151.         if(C1 == 0)
  152.         {
  153.                 while(C1 == 0);
  154.                 keyNum = 12;
  155.                 ShowKeyNum(SMG_NoDot[keyNum]);
  156.         }
  157.         else if(C2 == 0)
  158.         {
  159.                 while(C2 == 0);
  160.                 keyNum = 13;
  161.                 ShowKeyNum(SMG_NoDot[keyNum]);
  162.         }
  163.         else if(C3 == 0)
  164.         {
  165.                 while(C3 == 0);
  166.                 keyNum = 14;
  167.                 ShowKeyNum(SMG_NoDot[keyNum]);
  168.         }
  169.         else if(C4 == 0)
  170.         {
  171.                 while(C4 == 0);
  172.                 keyNum = 15;
  173.                 ShowKeyNum(SMG_NoDot[keyNum]);
  174.         }
  175. }

  176. void main()
  177. {        
  178.         while(1)
  179.         {
  180.                 ScanKeys();
  181.         }
  182. }

评论

[url=home.php?mod=space&uid=3523446]@小机器人[/url] :已解决,将J5的跳帽放到1,2位置上为矩阵按键,放到2,3位置上S7,S6,S5,S4为独立按键。S7,S6,S5,S4有复用功能且由J5的跳帽控制  发表于 2025-2-22 16:07
老师,我将您的代码都复制到我的电脑上运行了,但按S7,S6,S5,S4S还是不能显示0,4,8,12,其他的可以显示,用其他的代码也是,会不会是板子的问题,谢谢老师了  发表于 2025-2-22 11:36
[url=home.php?mod=space&uid=3189194]@JasonSuitao[/url] :同学,尝试一下把LED初始化设置呢?  发表于 2024-8-8 20:12
老师,您的独立按键和矩阵键盘的训练我都做了,为什么仿真的时候S7和S6按下以后会报错说Connection to Target system lost呢,我查了一下说什么功能复用的问题,但是没找到解决方案,求解答  发表于 2024-3-18 14:58
[url=home.php?mod=space&uid=3189194]@JasonSuitao[/url] :哥们 这个问题解决了吗  发表于 2022-6-14 18:01
[url=home.php?mod=space&uid=3299970]@smileZking[/url] :while(t--)中 t每减一 花费4.5微秒 百度一下while(t--)就知道了  发表于 2022-6-14 18:01
这个代码里对138那段是起什么作用呢?  发表于 2022-5-12 23:44
老师 这个延时函数while(t--);是延时了多久啊  发表于 2022-3-31 15:42
[url=home.php?mod=space&uid=3320028]@ykl1372733172[/url] :低电平  发表于 2022-3-25 23:49
[url=home.php?mod=space&uid=3320028]@ykl1372733172[/url] :老师打错了,是低电平  发表于 2022-1-18 21:53
huwentong 发表于 2018-3-13 22:03 | 显示全部楼层
请问C1 C2的p4口是什么意思呢
 楼主| ohy3686 发表于 2018-3-14 10:46 | 显示全部楼层
huwentong 发表于 2018-3-13 22:03
请问C1 C2的p4口是什么意思呢

现在蓝桥杯比赛使用的IAP单片机和89C52有点不同
IAP单片机没有P36和P37,换成了P42和P44
如果用89C52则不用改成P42和P44
一个拥抱 发表于 2018-3-18 17:00 | 显示全部楼层
楼主,按键检测不加延时检测么
 楼主| ohy3686 发表于 2018-3-18 19:33 | 显示全部楼层
一个拥抱 发表于 2018-3-18 17:00
楼主,按键检测不加延时检测么

实际应用是应该加延时的。
在这个题目中主要想说明键盘扫描原理,把去抖动省略了
大家可以把思路看得更清晰点。
一个拥抱 发表于 2018-3-20 16:04 | 显示全部楼层
ohy3686 发表于 2018-3-18 19:33
实际应用是应该加延时的。
在这个题目中主要想说明键盘扫描原理,把去抖动省略了
大家可以把思路看得更清 ...

OK谢谢
daage 发表于 2019-3-11 18:20 | 显示全部楼层
有错别字,应该是低电平
yzq13246068880 发表于 2019-5-22 16:01 | 显示全部楼层
200110ljh 发表于 2021-1-31 15:26 | 显示全部楼层
如果我案例一个数字后他显示1,后面我不进行其他操作为什么不会熄灭还是显示1
chenjian12138 发表于 2021-2-21 09:21 | 显示全部楼层
楼主,请问一下,矩阵键盘第一列无法显示是怎么回事呢?我自己编的代码和楼主发的代码都试过,但第一列无法显示,第二,三,四列都可以正常显示

评论

[url=home.php?mod=space&uid=3329960]@Draculaa[/url] :你看看你的J5跳线帽有没有放在12上边呢  发表于 2023-1-3 10:21
加一,怎么解决啊  发表于 2022-3-1 16:08
第一列是独立按键  发表于 2021-5-30 19:58
yzq13246068880 发表于 2021-4-30 17:11 | 显示全部楼层
tytughk 发表于 2022-1-18 09:31 | 显示全部楼层
chenjian12138 发表于 2021-2-21 09:21
楼主,请问一下,矩阵键盘第一列无法显示是怎么回事呢?我自己编的代码和楼主发的代码都试过,但第一列无法 ...

注意一下跳线帽接的对不对吧
lucky悦 发表于 2022-4-9 22:09 | 显示全部楼层
老师 请问第一列键盘没有办法显示是怎么回事呢?复制和您的代码也出现这个问题
22BS22 发表于 2022-4-10 23:05 | 显示全部楼层
chenjian12138 发表于 2021-2-21 09:21
楼主,请问一下,矩阵键盘第一列无法显示是怎么回事呢?我自己编的代码和楼主发的代码都试过,但第一列无法 ...

我也遇到这种情况了,是不是忘了跳线,就是J5模块KBD是矩阵键盘模式,BTN是独立按键,你换一下看看。
Shinyuchan 发表于 2023-12-2 00:50 | 显示全部楼层
我想问一下咱们怎么优化中间那部分啊,感觉太冗余了
sjqywt 发表于 2024-12-9 20:52 | 显示全部楼层
只能用col口来扫描吗,用row来扫描行不行老师
小机器人 发表于 2025-2-22 16:13 | 显示全部楼层
老师您好,我想问一下如何让单片机在加载和运行的时候都没有声音呢,看您在B站的视频上就很安静,但是自己运行的时候就很吵。尝试过将蜂鸣器初始化,但是在加载的时候还是会很吵。
谢谢老师了,祝身体健康,工作顺利!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:广东职业技术学院 欧浩源(ohy3686@foxmail.com)    [Zigbee技术&物联网应用] 群:168225322    [技术交流微信]:gzyohy (暗号:宝塔镇河妖)

322

主题

899

帖子

3548

粉丝
个人签名:广东职业技术学院 欧浩源(ohy3686@foxmail.com)    [Zigbee技术&物联网应用] 群:168225322    [技术交流微信]:gzyohy (暗号:宝塔镇河妖)

322

主题

899

帖子

3548

粉丝
快速回复 在线客服 返回列表 返回顶部