久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1923|回復: 2
收起左側

請教!這個單片機矩陣鍵盤程序不用外部中斷如何修改?

[復制鏈接]
ID:82098 發表于 2021-5-20 13:42 | 顯示全部樓層 |閱讀模式
請教!這個矩陣鍵盤不用外部中斷如何修改?/*程序功能:
K1單擊時num+1;長擊num+2;
K2單擊時num-1;長擊num-2;
K5連擊按鍵 按著num+1;
K6連擊按鍵 按著num-1;
無按鍵時間4s led亮;有按鍵,led滅。
*/
//支持單擊(短擊)、連擊,長擊,無擊
//長擊時間到后,立即執行;短擊釋放后執行
//按鍵方式(單擊,長擊)、(只支持單擊)、(連擊)
//連擊實際上包含了單擊
#include "reg51.h"
#include "intrins.h"

#define uchar unsigned char
#define uint unsigned int
#define NOP() _nop_()
#define KeyPIN P1
sbit led=P3^7;
uchar num;

uchar key_code[]= {0x7e,0x7d,0x7b,0x77,0xbe,0xbd,0xbb,0xb7,0xde,0xdd,0xdb,0xd7,0xee,0xed,0xeb,0xe7};

struct
{
    uchar state;//按鍵狀態 0-等待階段;1-閉合抖動階段;2-有效閉合階段;3-釋放階段
    uchar type;//0-無按鍵或者按鍵已經響應 ;1-單擊 ;2-連擊 ;3-長擊;4-無擊
    uchar detect;//按鍵檢測標志 1為檢測到按鍵
    uchar value;//當前鍵值
    uchar backvalue;//備份鍵值
    uchar disable;//按鍵禁止響應標志:按鍵執行過,則標志為1.主要用于長擊。
    uchar scan_en;//按鍵掃描標志 1為允許掃描
    uchar tmr_no;//無鍵計數器,用于無擊。
    uchar cnt_press;//按鍵閉合計數器,用于長擊。
    uchar delay_con;//連擊響應延時時間,用于連擊。
#define AN_XD_DL 2//AN_XD_DL*定時器中斷20ms
#define AN_LA_DL 10//AN_LA_DL*20ms
#define AN_CJ_DL 5//長擊所需時間:AN_CJ_DL*AN_LA_DL*20ms
#define KEY_IDLE 0//按鍵等待階段
#define KEY_IS_DOWN 1//閉合抖動階段
#define KEY_DOWN 2//有效閉合階段   
#define KEY_IS_UP 3//釋放階段
#define NoKey 0//無鍵
#define NoKeyTMR 200//無鍵所需時間:NoKeyTMR*20ms
} key;
unsigned char KeyScan(void);
void KeyInit(void);
void KeyProcess(void);
void KeyShortPress(void);//短擊 單擊
void KeyLongPress(void);//長擊
void KeyContinuePress(void);//連擊
void KeyNoPress(void);//無擊
void KeyAction(void);//根據按鍵類型動作 散轉程序
void main()
{
    TCON=0x00;
    IE=0x84;
    TMOD=0x01;
    TH0=0xB1;
    TL0=0xE0;
    ET0=1;
    TR0=1;
    EA = 1;
    while(1)
    {
        KeyPIN=0x0f;
        KeyProcess();
        KeyAction();
        P0=num/10;
        P2=num%10;
    }
}
//鍵盤掃描方法,反轉法
uchar KeyScan(void)
{
    uchar temp,keyval=0;
    KeyPIN = 0x0f;
    if (KeyPIN != 0x0f)
    {
        temp=KeyPIN;
        KeyPIN = 0xf0;
        temp|=KeyPIN;
        keyval=1;
        while (key_code[keyval-1] != temp)  //把特征碼轉換為鍵號
        {
            keyval++;
            if(keyval>0x0f)
            {
                break;
            }
        }
    }
    return keyval;
}
void KeyProcess()
{
    switch(key.state)
    {
    case KEY_IDLE://等待階段
    {
        key.disable=0;
        key.delay_con=AN_XD_DL;
        key.cnt_press=0;
        if(key.detect)//有按鍵才允許掃描
        {
            key.tmr_no=0;//有鍵按下,無鍵計數器清零
            key.type=0;
            key.detect=0;
            if(key.scan_en)
            {
                key.scan_en=0;
                key.state=KEY_IS_DOWN;
            }
        }
        else
        {
            if(key.tmr_no==NoKeyTMR)
            {
                key.type=4;
            }
        }
    }
    break;
    case KEY_IS_DOWN:
    {
        key.tmr_no=0;
        if(key.scan_en)
        {
            key.scan_en=0;
            key.value=KeyScan();
            if(key.value==key.backvalue)
            {
                key.state=KEY_DOWN;
            }
            else
            {
                key.backvalue=key.value;
            }
        }
    }
    break;
    case KEY_DOWN:
    {
        key.tmr_no=0;
        if(key.scan_en)
        {
            key.scan_en=0;
            key.backvalue=key.value;//備份當前鍵值供釋放后 單擊 使用
            key.value=KeyScan();
            key.delay_con--;
            if(key.delay_con==0)
            {
                key.delay_con=AN_LA_DL;
                key.cnt_press++;
                if(key.cnt_press>AN_CJ_DL)
                {
                    if(!key.disable)//長擊執行過一次后,如不釋放按鍵,不執行。
                    {
                        key.type=3;
                    }
                    else
                    {
                        key.type=0;
                    }
                }
                else
                {
                    key.type=2;
                }
            }
            if(key.value==NoKey)
            {
                key.state=KEY_IS_UP;
            }
        }
    }
    break;
    case KEY_IS_UP:
    {
        key.tmr_no=0;
        if(!key.disable)//避免長擊釋放后 繼續執行單擊
        {
            key.type=1;
        }
        key.state=KEY_IDLE;
    }
    break;
    }
}
void KeyAction(void)
{
    switch(key.type)
    {
    case 1:
    {
        KeyShortPress();
    }
    break;
    case 2:
    {
        KeyContinuePress();
        key.type=0;
    }
    break;
    case 3:
    {
        KeyLongPress();
    }
    break;
    case 4:
    {
        KeyNoPress();
    }
    break;
    }
}
void KeyNoPress(void)
{
    led=0;
}
void KeyShortPress(void)
{
    led=1;
    switch(key.backvalue)
    {
    case 1:
        num++;
        break;
    case 2:
        num--;
        break;
    }
}
void KeyContinuePress(void)
{
    led=1;
    switch(key.backvalue)
    {
    case 5:
        num++;
        break;
    case 6:
        num--;
        break;
    }
}
void KeyLongPress(void)
{
    led=1;
    switch(key.backvalue)
    {
    case 1:
        num+=2;
        key.disable=1;
        key.type=0;
        break;//此處key.disable和key.type必須這樣處理
    case 2:
        num-=2;
        key.disable=1;
        key.type=0;
        break;
    default:
        key.type=2;//因為長擊是在按下后時間足夠后就觸發的,所以為避免連擊和長擊沖突,必須加此句
    }
}
void timer0() interrupt 1 using 1       //12M晶振 20ms中斷
{
    TH0=0xB1;
    TL0=0xE0;
    key.tmr_no++;
    if(key.detect)
    {
        key.scan_en=1;    //有鍵按下才允許掃描
    }
}
void EXT_INT() interrupt 2 using 1
{
    key.detect=1;
}
回復

使用道具 舉報

ID:844772 發表于 2021-5-20 15:10 | 顯示全部樓層
EXT_INT()只是相當于最開始鎖鍵盤的作用,可以不用,鍵盤初始化時直接 key.detect=1就行;void timer0() 這個功能有點麻煩,如果你不需要雙擊等功能,就比較好改,否則會改的面部全非了。但源程序誰寫的,寫的不錯啊。
回復

使用道具 舉報

ID:275826 發表于 2021-5-20 21:48 | 顯示全部樓層
enum st{Nkey,Skey,Ckey,Lkey};
unsigned char kstate;
#define S_cnt 100
#define C_cnt 400
bit flag_down;
unsigned  char        kpadscan_turn_S_L_C(void)       
{ unsigned        char i,tmp,tmp1;
   static uchar keyv;
   keyport=0x0f;
   tmp=~keyport&0x0f;
   if(tmp)
      {if(++kpadcnt>5)
              {
                     keyport=0xf0;
                   tmp1=~keyport&0xf0;
                      tmp=tmp|tmp1;
                   for(i=0;i<16;i++)
                     {
                          if(tmp==keycode[i])
                            {keyv=i+1;
                                 break;
                                }
                         }
                        flag_down=1;
                   }
      }       

                 
   
        if(flag_down)
          {
           keyport=0x0f;
       tmp=~keyport&0x0f;
           if(tmp==0)
                  {if(kpadcnt<S_cnt)kstate=Skey;
                   else if((kpadcnt>=S_cnt)&&(kpadcnt<C_cnt))kstate=Ckey;
                   else kstate=Lkey;
                   flag_down=0;
               kpadcnt=0;
                  }
          }                 
                          
   return        keyv;                       
}                       
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲一区二区三区免费观看 | 成人在线视频观看 | 日韩免费视频一区二区 | 久久99精品视频 | 亚洲视屏 | 国产日韩欧美二区 | 久久久免费精品 | 免费看爱爱视频 | 亚洲小说图片 | 看片wwwwwwwwwww| 中文字幕一区二区在线观看 | 日韩福利在线 | www.玖玖玖| 亚洲精品视频在线观看免费 | 日日日色| 亚洲 日本 欧美 中文幕 | 国产 欧美 日韩 一区 | 99在线免费观看视频 | 久久精品一区二区视频 | 亚洲一区二区免费看 | 高清国产一区二区 | 欧美在线一区二区视频 | 欧美成人免费在线 | 成人精品视频在线观看 | 亚洲一区久久 | 精品国产一区二区三区观看不卡 | 国产一级大片 | 99在线免费观看视频 | 亚洲3p | 韩日一区 | 国产成人免费视频网站高清观看视频 | 国产一区 | 日本高清中文字幕 | 青青久草 | 成人在线视频观看 | 国产成人精品一区二区三区在线 | 黄视频欧美 | 亚洲黄色一级毛片 | 亚洲欧美一区二区在线观看 | 成人精品一区二区三区中文字幕 | 日韩中文字幕一区二区 |