找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1692|回复: 6
打印 上一主题 下一主题
收起左侧

请大家帮忙分析一下这段键盘扫描单片机程序的执行过程

[复制链接]
跳转到指定楼层
楼主
ID:476725 发表于 2019-5-21 19:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 Neighbor_John 于 2019-5-22 00:21 编辑

我学习到的键盘扫描是逐行或逐列扫描,而这段程序确不需要这么繁琐。但是我感觉这段程序有很大的逻辑错误,因为假设按得第一个键,P1应为0xee,然而※那一段代码得出的P1为0xfe,因此这段程序不可能实现,可我用仿真软件实验后证实程序是可行的,而且这段程序也没有检测按键是否放开的部分,可仿真出来没有任何问题,求大神看看这程序究竟怎么解释。

单片机源程序如下:
  1. void key()         //独立按键程序
  2. {
  3.         static uchar key_new = 0,key_l;
  4.         key_can = 20;                   //按键值还原
  5.         P1 = 0x0f;                                       
  6.         if((P1 & 0x0f) != 0x0f)      
  7.         {
  8.                 delay_1ms(1);                     //按键消抖动
  9.                 if(((P1 & 0x0f) != 0x0f) && (key_new == 1))
  10.                 {                                                //确认是按键按下
  11.                         key_new = 0;
  12.                         key_l= (P1 | 0xf0);
  13.                 ※      P1 = key_l ;  
  14.                         switch(P1)
  15.                         {
  16.                                 case 0xee:  key_can = 1;  break;  //得到按键值
  17.                                 case 0xde:  key_can = 4;  break;   //得到按键值
  18.                                 case 0xbe:  key_can = 7;  break;   //得到按键值
  19.                                 case 0x7e:  key_can = 10;  break;   //得到按键值        

  20.                                 case 0xed:  key_can = 2;  break;  //得到按键值
  21.                                 case 0xdd:  key_can = 5;  break;   //得到按键值
  22.                                 case 0xbd:  key_can = 8;  break;   //得到按键值
  23.                                 case 0x7d:  key_can = 0;  break;   //得到按键值

  24.                                 case 0xeb:  key_can = 3;  break;  //得到按键值
  25.                                 case 0xdb:  key_can = 6;  break;   //得到按键值
  26.                                 case 0xbb:  key_can = 9;  break;   //得到按键值
  27.                                 case 0x7b:  key_can = 11;  break;   //得到按键值
  28.       
  29.                                 case 0xe7:  key_can = 15;  break;  //得到按键值
  30.                                 case 0xd7:  key_can = 14;  break;  //得到按键值
  31.                                 case 0xb7:  key_can = 13;  break;   //得到按键值
  32.                                 case 0x77:  key_can = 12;  break;  //得到按键值  
  33.                         }                       
  34.                                 beep = 0;
  35.                                 delay_1ms(20);
  36.                                 beep = 1;
  37.                  }
  38.         }
  39.                 else
  40.                 {
  41.                         key_new = 1;
  42.                  }                       
  43.       
  44. }
复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2019-5-22 07:57 | 只看该作者
void key()         //不是独立按键程序,是4*4矩阵按键扫描程序
{
        static uchar key_new = 0,key_l;
        key_can = 20;                   //按键值还原
        P1 = 0x0f;  
        if((P1 & 0x0f) != 0x0f)
        {
                delay_1ms(1);                     //按键消抖动
                //key_new是按键自锁变量,防止按键重复响应,并做松手检测
                if(((P1 & 0x0f) != 0x0f) && (key_new == 1))
                {                                 //确认是按键按下
                        key_new = 0;
                        //假设按下第1键,此时读取P1状态是0000 1110
                        //P1|0xf0 逻辑运算后保留低4位不变,高4位置1
                        key_l= (P1 | 0xf0);//将结果保存在临时变量中1111 1110
                        P1 = key_l ;  //将1111 1110赋值P1
                        switch(P1)        //此时读取P1值为1110 1110 即0xee,其它键以此类推
                        {//提示:端口寄存器由于接受外部控制信号,读取的状态不一定是赋值的状态!
                                case 0xee:  key_can = 1;  break;  //得到按键值
                                case 0xde:  key_can = 4;  break;   //得到按键值
                                case 0xbe:  key_can = 7;  break;   //得到按键值
                                case 0x7e:  key_can = 10;  break;   //得到按键值
                                ......
回复

使用道具 举报

板凳
ID:476725 发表于 2019-5-25 14:07 | 只看该作者
wulin 发表于 2019-5-22 07:57
void key()         //不是独立按键程序,是4*4矩阵按键扫描程序
{
        static uchar key_new = 0,key_l;

感谢解答。意思就是SWITCH语句判断P1时不是根据P1的赋值是吧,那key_l的存在是不是没什么意义,而且最后是怎么得到0xee的呢(如果按第一个键),我就是对这里很不明白。
回复

使用道具 举报

地板
ID:511890 发表于 2019-5-25 16:03 | 只看该作者
Neighbor_John 发表于 2019-5-25 14:07
感谢解答。意思就是SWITCH语句判断P1时不是根据P1的赋值是吧,那key_l的存在是不是没什么意义,而且最后 ...

key_l是用来保持P1口的值的。按键一般是按下后就放开,也就是一瞬间的值。如果想要在按键松开后还要用到这个值的话,就要用一个变量来保存。
回复

使用道具 举报

5#
ID:155507 发表于 2019-5-26 10:04 | 只看该作者
Neighbor_John 发表于 2019-5-25 14:07
感谢解答。意思就是SWITCH语句判断P1时不是根据P1的赋值是吧,那key_l的存在是不是没什么意义,而且最后 ...

4*4矩阵按键
       4  5  6  7
       |  |  |  |
3------+--+--+--+---
2------+--+--+--+---
1------+--+--+--+---
0------+--+--+--+---
       1  4  7  10 键

如果按第一个键, P1.0与P1.4连接,将1111 1110赋值P1,此时读取P1值为1110 1110 即0xee,  因为P1.0与P1.4已经连接。
回复

使用道具 举报

6#
ID:476725 发表于 2019-5-29 15:15 | 只看该作者
angmall 发表于 2019-5-26 10:04
4*4矩阵按键
       4  5  6  7
       |  |  |  |

明白了,谢谢
回复

使用道具 举报

7#
ID:476725 发表于 2019-5-29 15:16 | 只看该作者
幻剑心 发表于 2019-5-25 16:03
key_l是用来保持P1口的值的。按键一般是按下后就放开,也就是一瞬间的值。如果想要在按键松开后还要用到 ...

明白了,谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表