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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5019|回復: 16
收起左側

單片機實用按鍵模塊,沒有延時語句、while()語句,可以直接復制使用與其他程序不沖突

  [復制鏈接]
ID:491577 發表于 2021-6-7 12:30 | 顯示全部樓層 |閱讀模式
本帖最后由 hhh402 于 2021-6-13 12:55 編輯

單片機實用按鍵模塊,沒有延時語句、while()語句,資源占用小。可以直接復制使用與其他程序不沖突。
使用時只需要直接引用全局變量key1和key2就可以。舉例:
1、k1按鍵按下LED1亮,再次按下LED1滅,
if(key1==1)        //k1按鍵按下
{
   key1=0;//必須軟件清零!!!
   LED1=~LED1;
}

2、k2按鍵按下LED1亮,K2長按LED1滅,
if(key1==2) //k2按鍵按下
{
   key1=0;//必須軟件清零!!!
   LED1=0; //0開1關
}
if(key1==20) //k按鍵長按
{
   key1=0;//必須軟件清零!!!
   LED1=1; //0開1關
}

3、k3按鍵按下LED1亮,K4按下LED1滅,
if(key1==3) //k3按鍵按下
{
   key1=0;//必須軟件清零!!!
   LED1=0; //0開1關
}
if(key1==4) //k4按鍵按下
{
   key1=0;//必須軟件清零!!!
   LED1=1; //0開1關
}

4、K3按下一次,數據m 增加1,長按k3兩秒以上每隔500ms數據m 增加10;K4按下一次,數據m 減少1,長按k4兩秒以上每隔500ms數據m 減少10;
if(key1==3) //k3按鍵按下
{
   key1=0;//必須軟件復位
   m++; //數據m 增加1
}
if(key2==3) //k3按鍵按下兩秒以上,注意key2不需要清零,key1必須清零!!!
{
   if(ms1>2000&&ms1%500==0) m=m+10; //長按k3兩秒以上每隔500ms數據m 增加10,ms1是毫秒變量,需要放在定時器1ms中斷中自加,ms1++;
}
else ms1=0;        //復位

if(key1==4) //k4按鍵按下
{
   key1=0;//必須軟件復位
   m--; //數據m -1
}
if(key2==4) //k4按鍵按下兩秒以上 ,注意key2不需要清零,key1必須清零!!!
{
   if(ms2>2000&&ms2%500==0)  m=m-10; //長按k4兩秒以上每隔500ms,ms2是毫秒變量,需要放在定時器1ms中斷中自加,ms2++;
}
else ms2=0;//復位

//下面是完整程序代碼:
#include "stc8.h"
#include "intrins.h"
#define u8  unsigned char
#define u16 unsigned int
sbit k1=P0^0;//按鍵1,四個按鍵可以是任意I/O口。按鍵按下時k1=0,按鍵釋放k1=1
sbit k2=P0^1;//按鍵2
sbit k1=P0^2;//按鍵3
sbit k1=P0^3;//按鍵4
sbit LED1=P1^0;//LED1

//u8 key1[4];//按鍵變量數組,4個按鍵互不影響,如果用key1,一次只能夠按一個按鍵,不允許同時按鍵。
u8 key1;//按鍵變量1,輸出按鍵單擊,長按。每單擊或長按一次只輸出一次,由調用函數清零。//key1=1/2/3/4是對應的按鍵單擊,key1=10、20、30、40是對應的按鍵長按。key1=0表示沒有按鍵按下。
//key1主要用途是:判斷某一個按鍵是單擊還是長按.注意調用函數需要將key1清零!!!
//u8 key2[4];//按鍵變量數組,4個按鍵互不影響,如果用key2,一次只能夠按一個按鍵,不允許同時按鍵。
u8 key2;//按鍵變量2,輸出按鍵單擊,每10ms輸出一次,key1=1/2/3/4是對應的按鍵單擊。
//key2主要用途是:長按按鍵時快速增加或減少數值。
u16 ms1,ms2;//毫秒計時
u16 m;//
void key() //按鍵處理模塊,需要放在10ms中斷中運行!!!
/* 說明:1、按鍵單擊,指按下100-1000ms內釋放,加入時間限制是為了防止干擾。
             2、按鍵長按,指按下3-10s內釋放,加入時間限制是為了防止干擾。
              3、函數運行后,按鍵值保存在key1、key2。用戶直接調用key1、key2即可。

*/
{
  //靜態變量,必須要static
  u16 static kgr[4];    //必須要static,抗干擾時間數組
  u8  static kanggr[4]; //中間變量1
  u8  static anjtem[4]; //按鍵釋放中間變量。
  u8 i;
  u8 L_anj[4];
  L_anj[0]=k1;
  L_anj[1]=k2;
  L_anj[2]=k3;
  L_anj[3]=k4;
  for(i=0;i<3;i++)  //4個按鍵處理,key1,
   {
         if(L_anj[ i]==0)        //按鍵按下                                       
          { if(kanggr[ i]==0)        //中間變量1,與下面互鎖
             { kgr[ i]=0;                //抗干擾時間清零,每次按鍵只寫1次。
               kanggr[ i]=1;         //中間變量1
               anjtem[ i]=1;         //按鍵釋放中間變量。與下面互鎖
             }

           if(anjtem[ i]==1)
           {
                  kgr[ i]++;//10毫秒計時。
                  if(kgr[ i]>1000) //按鍵按下大于10秒,強制復位,防止誤按。
                   { anjtem[ i]=0; //按鍵釋放中間變量。與上面互鎖
                     kgr[ i]=0;
//                  key1[ i]=0;//數組,4個按鍵獨立
                   }
           }
         }

     else    //按鍵釋放
     { kanggr[ i]=0;           //中間變量1,與上面互鎖
           if(kgr[ i]>9&&kgr[ i]<99) //按鍵間隔100--1000毫秒才有效,防止電磁干擾。時間可以修改
                 key1=i+1;   //單擊,按鍵間隔100--1000毫秒,每次釋放只寫1次。一次只能夠按一個按鍵,不允許同時按鍵。
           //key1[ i]=i+1;//數組,4個按鍵獨立
           else if(kgr[ i]>300&&kgr[ i]<1000) //按鍵間隔3000--10000毫秒才有效,防止電磁干擾。時間可以修改
                 key1=(i+1)*10;//長按,按鍵間隔3--10秒,每次釋放只寫1次。
           //key1[ i]=(i+1)*10;//數組,4個按鍵獨立
     }
  }

//下面是處理:key2是有按鍵按下就輸出鍵值。        
    for(i=0;i<3;i++)
         { if(L_anj[ i]==0)
           key2=i+1;//一次只能夠按一個按鍵,不允許同時按鍵。
         //key2[ i]=i+1;//數組,4個按鍵獨立.
         }
}


void timer0() interrupt 1                 //計時器T0中斷1ms。
{
  //靜態變量,必須要static
  u8  static time=0;   //毫秒變量。
  time++;//毫秒計時。
  if(time>9) //10ms運行一次按鍵處理函數,不需要防抖程序。
  {
       time=0;
        key();//按鍵處理模塊,需要放在10ms中斷中運行!!!
  }
//下面的語句不是按鍵模塊需要的,可以刪除。
    ms1++;ms2++;//毫秒計時
}

void main()
{
//1毫秒@12.000MHz,下面是STC單片機定時器0代碼,如果是別的單片機請根據手冊修改
        AUXR |= 0x80;                //定時器時鐘1T模式
        TMOD &= 0xF0;                //設置定時器模式
        TL0 = 0x20;                //設置定時初值,1毫秒@12.000MHz
        TH0 = 0xD1;                //設置定時初值,1毫秒@12.000MHz
        TF0 = 0;                //清除TF0標志        
        ET0 = 1;        //使能定時器中斷
       EA = 1;                    //打開總中斷
        TR0 = 1;                //定時器0開始計時
while(1)
  {
//1、k1按鍵按下LED1亮,再次按下LED1滅,
    if(key1==1)        //k1按鍵按下
     {
       key1=0;//必須軟件清零!!!
       LED1=~LED1;
     }

//2、k2按鍵按下LED1亮,K2長按LED1滅,
    if(key1==2) //k2按鍵按下
     {
       key1=0;//必須軟件清零!!!
       LED1=0; //0開1關
     }
   if(key1==20) //k按鍵長按
     {
       key1=0;//必須軟件清零!!!
       LED1=1; //0開1關
     }

//3、k3按鍵按下LED1亮,K4按下LED1滅,
   if(key1==3) //k3按鍵按下
    {
      key1=0;//必須軟件清零!!!
      LED1=0; //0開1關
    }
   if(key1==4) //k4按鍵按下
    {
      key1=0;//必須軟件清零!!!
      LED1=1; //0開1關
    }

//4、K3按下一次,數據m 增加1,長按k3兩秒以上每隔500ms數據m 增加10;K4按下一次,數據m 減少1,長按k4兩秒以上每隔500ms數據m 減少10;
//m的范圍:0-60000
   if(key1==3) //k3按鍵按下
    {
      key1=0;//必須軟件清零!!!
      if(m<60000) m++; //數據m 增加1
    }
   if(key2==3) //k3按鍵按下兩秒以上,注意key2不需要清零,key1必須清零!!!
    {
      if(ms1>2000&&ms1%500==0)
           {if(m<=59990) m=m+10;} //長按k3兩秒以上每隔500ms數據m 增加10,ms1是毫秒變量,需要放在定時器1ms中斷中自加,ms1++;
    }
   else ms1=0;        //復位

   if(key1==4) //k4按鍵按下
    {
      key1=0;//必須軟件復位
      if(m>0) m--; //數據m -1
    }
   if(key2==4) //k4按鍵按下兩秒以上 ,注意key2不需要清零,key1必須清零!!!
    {
      if(ms2>2000&&ms2%500==0)
          {if(m>9)  m=m-10;} //長按k4兩秒以上每隔500ms,ms2是毫秒變量,需要放在定時器1ms中斷中自加,ms2++;
    }
   else ms2=0;//復位
}
}


評分

參與人數 2黑幣 +60 收起 理由
x84s09t28 + 10 贊一個!
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

ID:491577 發表于 2021-6-7 15:52 | 顯示全部樓層
本帖最后由 hhh402 于 2021-6-13 12:56 編輯

這是按鍵檢測模塊函數:要認真看才能夠理解。
void key() //按鍵處理模塊,需要放在10ms中斷中運行!!!
/* 說明:1、按鍵單擊,指按下100-1000ms內釋放,加入時間限制是為了防止干擾。
             2、按鍵長按,指按下3-10s內釋放,加入時間限制是為了防止干擾。
             3、函數運行后,按鍵值保存在key1、key2。用戶直接調用key1、key2即可。
*/
{
  u16 static kgr[4];    //必須要static,抗干擾時間數組
  u8  static kanggr[4]; //中間變量1
  u8  static anjtem[4]; //按鍵釋放中間變量。
  u8 i;
  u8 L_anj[4];
  L_anj[0]=k1;
  L_anj[1]=k2;
  L_anj[2]=k3;
  L_anj[3]=k4;
  for(i=0;i<3;i++)  //4個按鍵處理,key1,
   {
         if(L_anj[ i]==0)        //按鍵按下                                       
          { if(kanggr[ i]==0)        //中間變量1,與下面互鎖
             { kgr[ i]=0;                //抗干擾時間清零,每次按鍵只寫1次。
               kanggr[ i]=1;         //中間變量1
               anjtem[ i]=1;         //按鍵釋放中間變量。與下面互鎖
            }

           if(anjtem[ i]==1)
           {
                  kgr[ i]++;//10毫秒計時。
                  if(kgr[ i]>1000) //按鍵按下大于10秒,強制復位,防止誤按。
                   { anjtem[ i]=0; //按鍵釋放中間變量。與上面互鎖
                     kgr[ i]=0;
                   }
           }
         }

     else    //按鍵釋放
     { kanggr[ i]=0;           //中間變量1,與上面互鎖
           if(kgr[ i]>9 && kgr[ i]<99) //按鍵間隔100--1000毫秒才有效,防止電磁干擾。時間可以修改
                 key1=i+1;   //單擊,按鍵間隔100--1000毫秒,每次釋放只寫1次。一次只能夠按一個按鍵,不允許同時按鍵。
           else if(kgr[ i]>300 && kgr[ i]<1000) //按鍵間隔3000--10000毫秒才有效,防止電磁干擾。時間可以修改
                 key1=(i+1)*10;//長按,按鍵間隔3--10秒,每次釋放只寫1次。
     }
  }

//下面是處理:key2是有按鍵按下就輸出鍵值。        
    for(i=0;i<3;i++)
         { if(L_anj[ i]==0)
           key2=i+1;//一次只能夠按一個按鍵,不允許同時按鍵。
         }
}

評分

參與人數 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

ID:299626 發表于 2021-6-7 17:15 | 顯示全部樓層
本帖最后由 nqwang 于 2021-6-7 17:46 編輯

mark下,好東西,節省資源的按鍵處理,但是建議做個完整的工程這樣好些。
回復

使用道具 舉報

ID:229641 發表于 2021-6-7 23:30 來自手機 | 顯示全部樓層
有完整的沒我白嫖一下…
回復

使用道具 舉報

ID:820198 發表于 2021-6-8 08:18 | 顯示全部樓層
感謝分享, 有完整工程例子學習嗎
回復

使用道具 舉報

ID:491577 發表于 2021-6-8 09:55 | 顯示全部樓層
最上面就是完整的程序,只需要改一下IO口設置,直接復制就可以用,與別的程序沒有沖突,沒有延時語句,while語句,資源占用很小。
回復

使用道具 舉報

ID:491577 發表于 2021-6-8 09:58 | 顯示全部樓層
注意:1、必須定義全局變量key1、key2。
          2、按鍵處理模塊,需要放在10ms中斷中運行!!!
          3、直接調用key1、key2就好。
回復

使用道具 舉報

ID:914666 發表于 2021-6-10 04:57 | 顯示全部樓層
要是客戶一起按了按鍵怎么辦啊?
回復

使用道具 舉報

ID:491577 發表于 2021-6-10 10:13 | 顯示全部樓層
用key1傳遞鍵值是不支持同時按鍵的,如果同時按鍵了會返回最后釋放按鍵的鍵值,如果想四個按鍵獨立互不影響可以使用數組key1[],程序里面有代碼,已經注銷了,自己修改一下就可以用。這個程序最大的特點是沒有延時語句,while語句,不會阻塞別的程序,直接復制粘貼就可以使用了。
回復

使用道具 舉報

ID:428114 發表于 2021-6-10 14:09 | 顯示全部樓層
放在中斷里,是一種手法,當然不再需要延時語句了,和程序沒有關系.
回復

使用道具 舉報

ID:162733 發表于 2021-6-12 21:38 | 顯示全部樓層
上面的程序只有key2可以讀出數值,key1始終無法讀出數值
回復

使用道具 舉報

ID:491577 發表于 2021-6-13 12:59 | 顯示全部樓層
本帖最后由 hhh402 于 2021-6-15 12:16 編輯
x84s09t28 發表于 2021-6-12 21:38
上面的程序只有key2可以讀出數值,key1始終無法讀出數值

程序有點錯誤,按鍵檢測程序中,ket1=0;這一句要去掉就可以了,最上面的程序我已經改好了,你再試試。其實原程序也是可以用的,key1的值只保存10ms就會變為0了,人眼是看不到key1的變化,但是10ms時間足夠了,程序不會出錯。
回復

使用道具 舉報

ID:162733 發表于 2021-7-1 23:34 | 顯示全部樓層
hhh402 發表于 2021-6-13 12:59
程序有點錯誤,按鍵檢測程序中,ket1=0;這一句要去掉就可以了,最上面的程序我已經改好了,你再試試。其 ...

剛試過了程序,在你的key()程序中,else //按鍵釋放,這個地方需要改成else if(kanggr[i ]==1)  //按鍵釋放;否則的話,按鍵只有第一次按下有用,后面就不能用了
回復

使用道具 舉報

ID:491577 發表于 2021-7-10 11:53 | 顯示全部樓層
“按鍵只有第一次按下有用,后面就不能用了”,就是要這樣的效果。等到按鍵釋放后才會歸位。每一次按鍵按下、釋放只會輸出一次鍵值,這樣才方便程序調用。
回復

使用道具 舉報

ID:579174 發表于 2021-8-4 14:20 | 顯示全部樓層
程序小白,下來學習了,感謝分享!
回復

使用道具 舉報

ID:845675 發表于 2021-8-11 19:08 來自手機 | 顯示全部樓層
樓主,你這個模塊怎么在我的AT89S51上不能正常使用啊
回復

使用道具 舉報

ID:491577 發表于 2021-8-12 10:00 | 顯示全部樓層
這是STC8單片機的程序,用在其他單片機需要修改定時器0部分。按照手冊修改。
void main()
{
//1毫秒@12.000MHz,下面是STC單片機定時器0代碼,如果是別的單片機請根據手冊修改
        AUXR |= 0x80;                //定時器時鐘1T模式
        TMOD &= 0xF0;                //設置定時器模式
        TL0 = 0x20;                //設置定時初值,1毫秒@12.000MHz
        TH0 = 0xD1;                //設置定時初值,1毫秒@12.000MHz
        TF0 = 0;                //清除TF0標志        
        ET0 = 1;        //使能定時器中斷
       EA = 1;                    //打開總中斷
        TR0 = 1;                //定時器0開始計時
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩在线视频免费观看 | 91亚洲国产精品 | 成年人免费在线视频 | 亚洲午夜网 | 免费在线看a | 久久com| 一区二区三区免费 | 青青草在线播放 | 中文字幕精品一区久久久久 | 91在线成人| 亚洲国产精品日本 | 黄视频免费 | 狠狠狠干 | 人人玩人人添人人澡欧美 | 麻豆久久久9性大片 | 久久久九九 | 天天精品在线 | 成人夜晚看av | 一区二区三区久久 | japan25hdxxxx日本| 成人免费一区二区三区牛牛 | www.国产视频| 欧美日日 | 麻豆精品一区二区三区在线观看 | 秋霞av国产精品一区 | 亚洲精品乱码8久久久久久日本 | 国产精品久久 | 高清不卡毛片 | 亚洲女人的天堂 | 国产人成精品一区二区三 | 精品免费视频 | 亚洲综合中文字幕在线观看 | 一区二区av | www国产亚洲精品久久网站 | 天堂网av在线 | 久久亚洲综合 | 日韩国产高清在线观看 | 国产永久免费 | 日日操日日干 | 欧美激情国产精品 | 成人性生交大片免费看中文带字幕 |