daiya1981 发表于 2020-7-5 21:16:22

51单片机单按键多击程序遇到问题

本帖最后由 daiya1981 于 2020-7-6 08:31 编辑

写了一个响应单按键多击的程序,按键弹起大于0.5S后返回键值,有问题,无法运行。可是我才疏学浅,找不到问题出在哪里。请各位高人帮忙看看问题出在哪?

#include <reg52.h>

sbit LED0 = P1^0;
sbit LED1 = P1^1;
sbit LED2 = P1^2;

sbit KEY1 = P3^2;

unsigned int count = 0,ClickFlagCount = 0;
unsigned char i = 0,ClickFlag = 0,keynum = 0;

unsigned char keyscan(void)
{
        if(KEY1)
        {                                                
          if(count > 30 && count < 3000)
            {      
                ClickFlag = 1;
               keynum++;
            }
            count = 0;
         if(ClickFlag == 1)
         {               
                if(ClickFlagCount++ > 500)
                {
                  ClickFlag = 0;
                  return keynum;
                  keynum = 0;
                }
                else
                {
                  ClickFlag = 0;
                }      
            }
          else
            {
                ClickFlagCount = 0;
            }
        }   
        else   
        {
                count++;
                if(count > 3000)
                        count = 3001;   
        }
        return 0;
}

void main()
{
   EA = 1;       //使能总中断
    TMOD = 0x01;//设置T0为模式1
    TH0= 0xFC;//为T0赋初值0xFC67,定时1ms
    TL0= 0x67;
    ET0= 1;   //使能T0中断
    TR0= 1;   //启动T0

    while (1)
    {
        switch (i)
      {
            case 1:      
                LED0 = ~LED0;
                break;
            case 2:
                LED1 = ~LED1;
                break;
            case 3:
                LED2 = ~LED2;
                break;                  
            default:
                break;
        }       
}

/* 定时器0中断服务函数 */
void InterruptTimer0() interrupt 1
{
    TH0 = 0xFC;//重新加载初值
    TL0 = 0x67;
        i = keyscan();
}

flash3g 发表于 2020-7-5 23:55:39

有什么问题不说清楚一点,看下定时器中断函数能进去不。

daiya1981 发表于 2020-7-6 08:26:25

本帖最后由 daiya1981 于 2020-7-6 08:28 编辑

定时器中断函数肯定进得去,我测试过了。这个程序是响应单按键多击,只要在按键抬起0,5秒之内按下均有效,可以响应1~N击,是个通用程序,可是由于我水平限制,里面肯定有错误,自己找不出来,请大家帮忙

daiya1981 发表于 2020-7-6 11:26:01

我添加了注释,不知道可不可以看清楚逻辑了?

unsigned char keyscan(void)
{
    if(KEY1)
    {                                                
      if(count > 30 && count < 3000)    //如果按下时间30ms~3s,认为是单击
      {      
                ClickFlag = 1;    //按键抬起标志置1
                keynum++;    //键号加1
      }
      count = 0;    // 键按下时间计数器清0
      if(ClickFlag == 1)    //如果按键抬起标志为1
      {               
            if(ClickFlagCount++ > 500)    //按键抬起时间大于0.5s
            {
                ClickFlag = 0;    //按键抬起标志清0
                return keynum;    //返回键号
                keynum = 0;    //键号清0
            }
            else    //按键抬起时间小于0.5s
            {
                ClickFlag = 0;
            }      
      }
      else    //如果按键抬起标志为0
      {
            ClickFlagCount = 0;    //清0按键抬起时间计数器
      }
    }   
    else   
    {
      count++;    //按键按下时间计数器加1
      if(count > 3000)    //防止数据溢出
            count = 3001;   
    }
    return 0;
}

armok. 发表于 2020-7-6 12:04:42

打赏!

庆祝论坛“打赏”功能实施, 现在开始发技术主题,可以获得打赏
https://www.amobbs.com/thread-5735948-1-1.html

mon51 发表于 2020-7-6 19:54:02

我们一般将键盘设计成一个独立模块,产生单击、延时击、延时后的快击,几种状态码,然后到相应的任务模块里调看键值,简单可靠。尽量不用定时器去延时,只用主程序执行的周期做计时,对于按键的去抖延时20-40毫秒,均无防。这样可以减少定时器的支出。
给你一段代码:
#include "Use.h"
#include "Ver.H"


#define Timer20ms        (80/TK_MAIN)                 //ÑÓʱʱ¼ä20mS
#define Timer3S                (1500/TK_MAIN)                 //ÑÓʱʱ¼ä2S
#define Timer100ms        (200/TK_MAIN)                //ÑÓʱʱ¼ä100mS
//**********************************************************
KEY                                KeyDat;                //¶¨ÒåÊý¾Ý½á¹¹
//**********************************************************
sbit KeyIn=P1^6;
sbit Clk_Key595=P2^7;
sbit Rck_Key595=P0^2;
sbit Dat_Key595=P0^3; //
//*********************************************
void SenDat_Key595(unsigned char Dat){
        unsigned char j=8;

        Rck_Key595=0;
        for (j=0;j<8;j++){
                Clk_Key595=0;
                Dat_Key595=(bit)(Dat & 0x80);
                Clk_Key595=1;       
                Dat<<=1;                          //×óÒÆÊäÈë
        }
        Rck_Key595=1;
}
//*********************************************
unsigned char ReadKey(void){
        unsigned char i,j=0;
       
        j =~HMLCtrl;
        j &=0x0f;
        j<<=1;
        if (fBZ==0) j |=0x01;
        //*****************************************

        i =0x60 | j;        // 0111,1111=7f 2005-3-22

        KeyIn=1;
        SenDat_Key595(i);
        if (!KeyIn) return 1; //Ka

        i=0xa0 | j;        //1011,1111 =bf
        SenDat_Key595(i);
        if (!KeyIn) return 2; //kb

        i=0xc0 | j;        //1101,1111=df
        SenDat_Key595(i);
        if (!KeyIn) return 3; //kc
        //***************************** KFo KFs
        return 0;
}

/************************************
ÅбðÊÇ·ñÓмü
*************************************/
void GetKey (void){
        if (ReadKey()!=0)        {
                KeyDat.KeyDog=Timer20ms;
                KeyDat.KeyPower++;
        }
}       
/**************************************
ÑÓʱȥ¶¶¶¯
***************************************/
void KeyDog(void){
        if (--KeyDat.KeyDog== 0){
                KeyDat.KeyData=ReadKey();        //¶Á¼üÅÌ               
                if (KeyDat.KeyData!=0){
                       KeyDat.KeyPower++;
                        KeyDat.KeyDog=Timer3S;
                }else{
                        KeyDat.KeyPower=0;
                        KeyDat.KeyData=0;                //·µ»Ø
                   }
        }
}
/*********************************
ÅбðÊÇ·ñËÉ¿ª
**********************************/
void KeyOff1(void){
        unsigned char i;
        i=ReadKey();
        if (i==0){                                                        //ËÉ¿ª°´¼ü
                KeyDat.KeyPower=0;
                KeyDat.KeyData |=HaveKey;        //¶¨Òå±êÖ¾               
//*****************************************                                               
                Beep_Start(0);                                        //·äÃùÆ÷¶ÌÃù
//******************************************
        }else{
                if (--KeyDat.KeyDog == 0){                 //3ÃëÑÓʱµ½
        //*****************************************                                               
                        Beep_Start(0);//·äÃùÆ÷¶ÌÃù
        //******************************************
                        KeyDat.KeyData |=HaveKey | DubClick;        //3SºóËÉ¿ªµÃµ½³¤ÑÓʱ¼ä¶¨Òå±êÖ¾               
                        KeyDat.KeyDog=3*Timer100ms;
                        KeyDat.KeyPower++;
                }
        }
}
/**********************************
Á¬»÷ÊÇ·ñËÉ¿ª
**********************************/
void KeyOff2(void){
        unsigned char i;
        i=ReadKey();
        if (i!=0){
                if (--KeyDat.KeyDog == 0){
                        KeyDat.KeyData =i | HaveKey | AddClick;        //¼ÓËÙ»÷±êÖ¾
                        KeyDat.KeyDog=Timer100ms;
//*****************************************                                               
                        Beep_Start(0);//·äÃùÆ÷¶ÌÃù
//******************************************
                }
        }else{
                KeyDat.KeyData =0;       
                KeyDat.KeyPower =0;
        }
}
/**********************************
º¯ÊýÖ¸Õ붨Òå
***********************************/
code void (code *SubKey[])()={
        GetKey,KeyDog,KeyOff1,KeyOff2       
};
/*****************************
¼ü´¦Àí³ÌÐò
******************************/
void KeyBord(void){
        (*SubKey)();

}
/**************************************
¼ü´¦ÀíºóÇå³ý¼üÖµ
***************************************/
unsigned char JB_KeyData(void){
        unsigned char i=0;

        if (KeyDat.KeyData > DubClick){
                i=KeyDat.KeyData;
                KeyDat.KeyData=0;
        }
        return i;
}       

mon51 发表于 2020-7-6 19:54:32

奇怪了中文变成乱码。

mon51 发表于 2020-7-6 19:56:40

/*****************************************************
¼üÅ̵ļüÖµ¶¨Òå
******************************************************/
#define AddClick                0x20                                //Á¬»÷
#define DubClick                0x40                                //µ¥»÷
#define HaveKey                        0x80                                //Óмü

#define        Ka                (0x01|HaveKey)
#define        Kb                (0x02|HaveKey)
#define        Kc                (0x03|HaveKey)
#define        Ko                (0x04|HaveKey)
#define        Ks                (0x05|HaveKey)
#define        Kos                (0x06|HaveKey)


#define Ka_Dub        (Ka| DubClick | HaveKey)        //Ë«»÷       
#define Kb_Dub        (Kb| DubClick | HaveKey)
#define Kc_Dub        (Kc| DubClick | HaveKey)
#define        Ko_Dub        (Ko       | DubClick | HaveKey)
#define        Ks_Dub        (Ks| DubClick | HaveKey)
#define        Kos_Dub        (Kos | DubClick | HaveKey)

#define Ka_Add         (Ka| HaveKey | AddClick)        // ¼ÓËÙ       
#define Kb_Add         (Kb| HaveKey | AddClick)
#define Kc_Add         (Kc| HaveKey | AddClick)
#define        Ko_Add         (Ko       | HaveKey | AddClick)
#define        Ks_Add         (Ks| HaveKey | AddClick)
#define        Kos_Add (Kos | HaveKey | AddClick)

//*******************************************************************
//ºìÍâ¼üÅ̶¨Òå
//*******************************************************************
#define K0_IR        0
#define K1_IR        1
#define K2_IR        2
#define K3_IR        3
#define K4_IR        4
#define K5_IR        5
#define K6_IR        6
#define K7_IR        7
#define K8_IR        8
#define K9_IR        9
//*********************************************************************
#define Ka_IR        1
#define Kb_IR        1
#define Kc_IR        1
#define Kd_IR        1
#define Ke_IR        1
#define Kf_IR        1
//*********************************************************************
#define K_up_IR                1
#define K_down_IR        1
#define K_left_IR        1
#define K_right_IR        1
#define K_ok_IR                1
#define K_esc_IR        1

mon51 发表于 2020-7-6 19:57:23



mon51 发表于 2020-7-6 19:58:25

//---------------------------------------
typedef struct{
        unsigned char KeyPower;        //ÃüÁî×Ö
        unsigned intKeyDog;        //ÑÓʱ
        unsigned char KeyData;        //¼üÖµ
}KEY;

mon51 发表于 2020-7-6 19:59:19

采用状态机,将键译程序分解成几个工作状态。

lijianxing 发表于 2020-7-8 17:26:05

学习了,谢谢
页: [1]
查看完整版本: 51单片机单按键多击程序遇到问题