找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机矩阵键盘程序在长按时会有短按动作功能后才执行长按,谁知道如何解决?

[复制链接]
跳转到指定楼层
楼主
ID:41347 发表于 2023-2-9 16:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*==================硬件电路===============================      
*
*说明:矩阵键盘为4*4,数据口为P2,行线为P2.0-P2.3,列线为P2.4-P2.7
*==========================================================*/
#include<reg52.h>
#include"Define.h"
#include"matrixkeyscan.h"

#define key P1                        //矩阵键盘的数据口
#define no_key  0xff    //无按键按下
#define key_state0  0   //状态0,此时无按键按下
#define key_state1  1          //状态1,此时处于确定按键是否按下
#define key_state2  2          //状态2,此时判断按键是否释放
uchar key_value;                //键值返回
/*==========================================================   
*函数名称:Keyscan()
*功    能:对矩阵键盘进行扫描,扫描方式为状态机+定时器中断
*入口参数:
*出口参数:key_value,代表具体的键值
*说    明:有个缺陷,刚开始数码管就亮,还没找到是哪里出了问题
*==========================================================*/
uchar Keyscan()
{
        uchar key_temp;
         uchar key1,key2;
  uchar keyRetu=0;    //返回的按键值
  static uchar s_keyState=0;
  static uint keyTime=0; //按键状态,按键按下的时间计数器
  //key_temp=no_key;
         key=0xf0;
        key1=key;
         key1=key&0xf0;                  //确定哪一行的按键按下
         key=0x0f;
        key2=key;
         key2=key&0x0f;                  //确定哪一列的按键按下
        key_temp=key1|key2;          //确定按键位置

         switch(s_keyState)              //检测当前状态
         {
                  case 0:                                                        //之前无按键被按下
                           if(key_temp!=no_key)                                        //说明有按键按下或者抖动
                           {
                            s_keyState=1;                                //转换为状态1,然后去判断是否真的按下
                           }
                           break;
                  case 1:                                                        //状态1,说明之前已经有按键按下或者抖动
                           if(key_temp!=no_key)                                        //有按键按下
                           {
                                          keyTime++;                     //  一次10ms
            if(keyTime>=3)   //  消抖时间为:SINGLE_KEY_TIME*10ms = 30ms;
                {
                   s_keyState=2;                                //跳到状态2,进而判断是否被释放   //  如果按键时间超过 消抖时间,即判定为按下的按键有效。按键有效包括两种:单击或者长按,进入 按键状态2, 继续判定到底是那种有效按键
                }
                           }else                                                                        //确实有按键被按下
                           {
                      s_keyState=0;                                //返回到状态0,
                          }
                           break;

                  case 2:                                                        //状态2,判断是否被释放
                 if(key_temp==no_key)   //检测到按键松开
                                {        
          s_keyState=0; //状态转到状态0
                                       
                                }else
                                {
                  keyRetu=1;   //输出1  
                                                s_keyState=3; //状态转到状态3
              }
                                break;
                                case 3:
                                        if(key_temp==no_key)   //检测到按键松开
                                    {        
              s_keyState=0; //状态转到状态0
                                            keyRetu=1;
                                    }else
                                    {
                  
                                    //keyTime++;
               if(++keyTime>200)
                                                      {
                                                                         keyTime=0;
                                     keyRetu=2;    // 输出2
                                                                         s_keyState=4;
                                          }
                 }
                                case 4:
                                 if(key_temp==no_key)    //检测到按键松开
                                                {
                                                 s_keyState=0; //状态转到状态0,完成
                                                 //keyTime=0;
                                                }  
               break;
                                   default:                                //  特殊情况:key_state是其他值得情况,清零key_state。这种情况一般出现在 没有初始化key_state,第一次执行这个函数的时候
            s_keyState=0; //状态转到状态0,
            break;
         }
       if(keyRetu==1)
                                {
         switch(key_temp)                    //当确定按键按下后,列举所有的按键情况
                            {
                                     case 0xee: key_value=0;break;//1110 1110
                                     case 0xde: key_value=1;break;//1101 1110
                                     case 0xbe: key_value=2;break;
                                     case 0x7e: key_value=3;break;
                                     case 0xed: key_value=4;break;
                                     case 0xdd: key_value=5;break;
                                     case 0xbd: key_value=6;break;
                                     case 0x7d: key_value=7;break;
                                     case 0xeb: key_value=8;break;
                                     case 0xdb: key_value=9;break;
                                     case 0xbb: key_value=10;break;
                                     case 0x7b: key_value=11;break;
                                     case 0xe7: key_value=12;break;
                                     case 0xd7: key_value=13;break;
                                     case 0xb7: key_value=14;break;
                                     case 0x77: key_value=15;break;
                            }
                                }
                        if(keyRetu==2)
                        {
         switch(key_temp)                    //当确定按键按下后,列举所有的按键情况
                            {
                                     case 0xee: key_value=100;break;//1110 1110
                                     case 0xde: key_value=101;break;//1101 1110
                                     case 0xbe: key_value=102;break;
                                     case 0x7e: key_value=103;break;
                                     case 0xed: key_value=104;break;
                                     case 0xdd: key_value=105;break;
                                     case 0xbd: key_value=106;break;
                                     case 0x7d: key_value=107;break;
                                     case 0xeb: key_value=108;break;
                                     case 0xdb: key_value=109;break;
                                     case 0xbb: key_value=110;break;
                                     case 0x7b: key_value=111;break;
                                     case 0xe7: key_value=112;break;
                                     case 0xd7: key_value=113;break;
                                     case 0xb7: key_value=114;break;
                                     case 0x77: key_value=115;break;
                            }
                        }
        return key_value;
}
/*==========================================================
* 开发人员:laowang
* 当前版本:V1.0
* 创建时间:11/26/2013
* 修改时间:
* 功能说明:对4*4矩阵键盘扫描,用8位数码管进行显示,刚开始时不亮,依次按下按键时
                          数码管依次显示0-F,扫描方法为状态机方法+定时器中断
*==========================================================*/
#include<reg52.h>
#include"Define.h"
#include"display.h"
#include"matrixkeyscan.h"

void Timer0_init();                        //定时器初始化函数
uint flag=0;                                  //按键扫描标志,每中断一次,扫描一次

//主函数
void main()
{
        uchar key_state=0;        
        uchar readkey;
        readkey=0xff;

        Timer0_init();
        Display_init();                        //使之不亮
        while(1)
         {
                  if(flag)
                  {
                           flag=0;

                           readkey=Keyscan();
                   //        Display(readkey);
                                switch(key_value)
                                    {
                               case 0: P2=0x66;break;
                                                 case 1: P2=0x02;break;
                                                 case 2: P2=0x04;break;
                                                 case 3: P2=0x08;break;
                                                 case 4: P2=0x10;break;
                                                 case 5: P2=0x20;break;
                                                 case 6: P2=0x40;break;
                                                 case 7: P2=0xff;break;
                                                
                                                 case 100: P2=0x00;break;
                                                 case 101: P2=0x0f;break;
                                                 case 102: P2=0xf0;break;
                                                 case 103: P2=0x88;break;
                                                 default:break;
                              }
                  }
         }
}

void Timer0() interrupt 1                     
{
        TH0=0xd8;          //10Ms产生一次中断
         TL0=0xf0;
         flag=1;
}

void Timer0_init()
{
        TMOD=0x01;
         TH0=0xd8;                          //12MHz  10Ms
         TL0=0xf0;
        EA=1;
        ET0=1;
         TR0=1;        
}


矩阵键盘调试.rar

88.91 KB, 下载次数: 3

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

使用道具 举报

沙发
ID:41347 发表于 2023-2-9 16:33 | 只看该作者
这是仿真图片

1675931455450.jpg (53.7 KB, 下载次数: 31)

1675931455450.jpg
回复

使用道具 举报

板凳
ID:161164 发表于 2023-2-10 22:33 | 只看该作者
  1.                 case 2:                                                        //状态2,判断是否被释放
  2.                         if(key_temp==no_key)   //检测到按键松开
  3.                         {
  4.                                 s_keyState=0; //状态转到状态0
  5.                         }
  6.                         else
  7.                         {
  8. //keyRetu=1;   //输出1
  9.                                 s_keyState=3; //状态转到状态3
  10.                         }
  11.                         break;
复制代码


回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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