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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3390|回復(fù): 22
打印 上一主題 下一主題
收起左側(cè)

單片機按鍵狀態(tài)檢測程序問題,不能雙擊

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:566214 發(fā)表于 2021-9-23 22:17 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
/*      雙擊不行,10ms掃描一次,Key_Double_Period=30,不是Key_Double_Period時間的問題
         現(xiàn)在的問題是:第一次按下的時間大于Key_Double_Period,再快速按一下,就可以識別為雙擊
         但是這樣子太別扭了,雙擊應(yīng)該是再Key_Double_Period時間內(nèi),再次按下,就認(rèn)為是雙擊
         調(diào)了快一個禮拜,還是同樣的問題

*/
uchar Key_Read(void)
{
        static uchar key_state_buffer=key_state_0;
        static uchar key_timer_cnt=0;
        static uchar key_temp=Key_Null;
        uchar key_return=Key_Null;
        uchar key=Key_Null;
        key=Key_Null|Key_Driver();
        switch(key_state_buffer)
        {
                case key_state_0:
                        if(key!=Key_Null)
                        {
                                key_temp=key;
                                key_timer_cnt=0;
                                key_state_buffer=key_state_1;
                        }
                        else
                        {
                                key_return=key;
                        }
                        break;
                case key_state_1:
                        if(key!=Key_Null)
                        {
                                key_return=key|Key_Double;
                                key_state_buffer=key_state_0;
                        }
                        else if(++key_timer_cnt>=Key_Double_Period)
                        {
                                key_return=key_temp;
                                key_state_buffer=key_state_0;
                                key_timer_cnt=0;
                        }
                        break;
        }
        return key_return;
}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:566214 發(fā)表于 2021-9-23 22:21 | 只看該作者
Key_Null=0x00;Key_Driver()這個函數(shù)返回值是單擊的值和長按得值
回復(fù)

使用道具 舉報

板凳
ID:190577 發(fā)表于 2021-9-24 06:48 | 只看該作者
#include<stc15w202s.h>
#include<stdio.h>
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
#define key_state_3 3
#define key_no 0
#define key_click 1
#define key_double 2
#define key_long 3
sbit KEY = P3^3;
sbit LED_E1P = P3^1;
sbit LED_G1 = P3^2;
sbit LED2 = P5^5;        //W2OUT
sbit LED3 = P5^4;  
unsigned char flag;
unsigned char cnt = 0;


static unsigned char key_driver(void)
{
        static unsigned char key_state_buffer1 = key_state_0;
        static unsigned char key_timer_cnt1 = 0;
        unsigned char key_return = key_no;
        unsigned char key;
        
        key = KEY;  //read the I/O states
        
        switch(key_state_buffer1)
        {
                case key_state_0:
                        if(key == 0)
                                key_state_buffer1 = key_state_1;
                                //按鍵被按下,狀態(tài)轉(zhuǎn)換到按鍵消抖和確認(rèn)狀態(tài)//
                        break;
                case key_state_1:
                        if(key == 0)
                        {
                                key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                //按鍵仍然處于按下狀態(tài)
                                //消抖完成,key_timer開始準(zhǔn)備計時
                                //狀態(tài)切換到按下時間計時狀態(tài)
                        }
                        else
                                key_state_buffer1 = key_state_0;
                                //按鍵已經(jīng)抬起,回到按鍵初始狀態(tài)
                        break;  //完成軟件消抖
                case key_state_2:
                        if(key == 1)
                        {
                                key_return = key_click;  //按鍵抬起,產(chǎn)生一次click操作
                                key_state_buffer1 = key_state_0;  //轉(zhuǎn)換到按鍵初始狀態(tài)
                        }
                        else if(++key_timer_cnt1 >= 100)  //按鍵繼續(xù)按下,計時超過1000ms
                        {
                                key_return = key_long;  //送回長按事件
                                key_state_buffer1 = key_state_3;  //轉(zhuǎn)換到等待按鍵釋放狀態(tài)
                        }
                        break;
                case key_state_3:  //等待按鍵釋放
                        if(key == 1)  //按鍵釋放
                                key_state_buffer1 = key_state_0;  //切回按鍵初始狀態(tài)
                        break;
        }
        return key_return;
}

unsigned char key_read(void)
{
        static unsigned char key_state_buffer2 = key_state_0;
        static unsigned char key_timer_cnt2 = 0;
        unsigned char key_return = key_no;
        unsigned char key;
        
        key = key_driver();
        
        switch(key_state_buffer2)
        {
                case key_state_0:
                        if(key == key_click)
                        {
                                key_timer_cnt2 = 0;  //第一次單擊,不返回,到下個狀態(tài)判斷是否會出現(xiàn)雙擊
                                key_state_buffer2 = key_state_1;
                        }
                        else
                                key_return = key;  //對于無鍵、長按,返回原事件
                        break;
                case key_state_1:
                        if(key == key_click)  //又一次單擊,時間間隔小于500ms
                        {
                                key_return = key_double;  //返回雙擊事件,回到初始狀態(tài)
                                key_state_buffer2 = key_state_0;
                        }
                        else if(++key_timer_cnt2 >= 50)
                        {   
                        //這里在下一次的按鍵來臨之前,并且時間是小于500ms的時候,就會一直執(zhí)行的是這個key_timer_cnt2++.直到下一次的按鍵到來,再判斷看是雙擊還是單擊。
                                //這里500ms內(nèi)肯定讀到的都是無鍵事件,因為長按大于1000ms
                                //在1s前底層返回的都是無鍵
                                                                        
                                key_return = key_click;  //500ms內(nèi)沒有再次出現(xiàn)單擊事件,返回單擊事件
                                key_state_buffer2 = key_state_0;  //返回初始狀態(tài)
                                       
                        }
                        break;
        }
        
        return key_return;
}

void Timer0Init(void)                //1毫秒@11.0592MHz
{
        AUXR |= 0x80;                //定時器時鐘1T模式
        TMOD &= 0xF0;                //設(shè)置定時器模式
        TL0 = 0xCD;                //設(shè)置定時初值
        TH0 = 0xD4;                //設(shè)置定時初值
        TF0 = 0;                //清除TF0標(biāo)志
        TR0 = 1;                //定時器0開始計時
        ET0 = 1;

}
void IO_init()
{
   
    P3M0 = 0x01;
    P3M1 = 0x01;
    P5M0 = 0x00;
    P5M1 = 0x00;
   
}


void main(void)
{         
       unsigned char key = 1;
             Timer0Init();
           IO_init();
           LED_E1P = 1;
           LED_G1 = 1;
           LED2 = 1;
           LED3 = 0;
                   EA = 1;
           while(1)
           {
             if(flag)
                 {
                   flag=0;
           key = key_read();
                   switch(key)
                   {
                            case key_click:LED2 = !LED2; break;
                         case key_double:LED2 = !LED2;LED3 = !LED3; break;
                         case key_long: LED2 = 1; LED3 = 1; LED_G1 = 0; LED_E1P = 0; break;
                         default : break;
                   }
                 }
           }
}

void Timr0_ISR() interrupt 1
{
   cnt++;
   if(cnt>=10)
   {
       cnt = 0;
              flag = 1;
   }
}
回復(fù)

使用道具 舉報

地板
ID:123289 發(fā)表于 2021-9-24 08:52 | 只看該作者
1、按鍵有彈動,如果沒有防彈動過慮則,則無法界定按了幾下(按一下,彈N次)。
2、防彈動的過慮時間,既要能慮除彈動時間,又不能錯將雙擊過慮掉。這就要求過慮時間設(shè)置適當(dāng)。
建議過慮時間設(shè)置為32ms。
3、為了能識別按了幾次,就需要有一個計數(shù)器JN。
4、JN何時起計,何時結(jié)束,也是有講究的。JN計數(shù)完成之前,你不要做界定,因為還不確定是連續(xù)按了幾次。
建議的做法是:雙擊的間隔時間定義為:0.08-0.6秒之間。
界定開始時間(JN計數(shù)結(jié)束時間):這個0.6秒就是JN界定的時間,它的意思是:當(dāng)按鍵彈起后0.6秒后,開始界定JN。這時JN=幾,就是連續(xù)擊鍵幾次。
如此:無論連續(xù)擊幾次都能識別。
短按:JN=1
雙擊:JN=2。
N擊:JN=N。
JN計時的開始時間(復(fù)0):JN被識別后,就清0,準(zhǔn)備下次使用。當(dāng)然,初始化也清0。
由于涉及多種計時,所以,建議做個定時中斷,如4ms中斷一次,中斷服務(wù)程序中做以下事件:
1、掃鍵:
彈動過慮計時器JT:
鍵按下時:+1,本次鍵值THIS_KEY與上次鍵值LAST_KEY不同時清0(不同,就是彈動),相同時+1。>8時(彈動過慮時間)不再增加。
彈起時界定:JT>=8時(32ms),鍵值有效(可以做個標(biāo)記:KEY_P=1),即認(rèn)為按了一次。
2、擊鍵次數(shù)界定計時器JC:
鍵按下時:+1,>150(0.6秒)時不再增加。
彈起時界定:JC>=150時(600ms),去界定JN。隨即將JC清0。
3、擊鍵次數(shù)JN:
鍵值被認(rèn)定有效(KEY_P=1)時+1,>多少時不再增加,自己去定。將KEY_P清0。





回復(fù)

使用道具 舉報

5#
ID:332444 發(fā)表于 2021-9-24 14:36 | 只看該作者
現(xiàn)在認(rèn)為不用雙擊,用組合鍵更簡單靈活,程序設(shè)計也相對容易實現(xiàn).
回復(fù)

使用道具 舉報

6#
ID:566214 發(fā)表于 2021-9-24 14:51 | 只看該作者
bbxyliyang 發(fā)表于 2021-9-24 06:48
#include
#include
#define key_state_0 0

感謝回復(fù),這個程序是觸摸按鍵的,機械按鍵是可以正常識別雙擊事件的,觸摸按鍵的庫是別提供的,只有一個接口函數(shù)
回復(fù)

使用道具 舉報

7#
ID:566214 發(fā)表于 2021-9-24 14:52 | 只看該作者
xianfajushi 發(fā)表于 2021-9-24 14:36
現(xiàn)在認(rèn)為不用雙擊,用組合鍵更簡單靈活,程序設(shè)計也相對容易實現(xiàn).

觸摸按鍵
回復(fù)

使用道具 舉報

8#
ID:566214 發(fā)表于 2021-9-24 14:52 | 只看該作者
yzwzfyz 發(fā)表于 2021-9-24 08:52
1、按鍵有彈動,如果沒有防彈動過慮則,則無法界定按了幾下(按一下,彈N次)。
2、防彈動的過慮時間,既 ...

感謝回復(fù),我試一下
回復(fù)

使用道具 舉報

9#
ID:332444 發(fā)表于 2021-9-24 15:36 | 只看該作者

只要是按鍵,不論是何種,都是可以實現(xiàn)組合鍵,有什么不能實現(xiàn)的理由?
回復(fù)

使用道具 舉報

10#
ID:332444 發(fā)表于 2021-9-24 15:44 | 只看該作者

設(shè)定一個比較時間,可以實現(xiàn)組合,當(dāng)然,雙擊也是.
回復(fù)

使用道具 舉報

11#
ID:624769 發(fā)表于 2021-9-24 15:47 | 只看該作者
一般情況下, 長按短按, 單擊雙擊。
這兩種區(qū)分按鍵的模式,在沒有必要的前提下,不同時使用。
因為,會給你的按鍵判斷復(fù)雜程度提高一個級別,如果你采取了 單擊雙擊,還嫌不夠可以增加三擊四擊,沒必要再去搞長按。一個鍵也就算了,鍵多了,你的按鍵判斷邏輯會變得及其混亂,因為一旦牽涉到長按和雙擊,那么你必須考慮,第二擊你達到了長按標(biāo)準(zhǔn)的話,到底算,長按,還是雙擊。諸如此類各種麻煩。
回復(fù)

使用道具 舉報

12#
ID:566214 發(fā)表于 2021-9-24 19:16 | 只看該作者
xianfajushi 發(fā)表于 2021-9-24 15:44
設(shè)定一個比較時間,可以實現(xiàn)組合,當(dāng)然,雙擊也是.

狀態(tài)機的邏輯可以實現(xiàn)嗎?我同時檢測5顆按鍵
回復(fù)

使用道具 舉報

13#
ID:566214 發(fā)表于 2021-9-24 19:19 | 只看該作者
188610329 發(fā)表于 2021-9-24 15:47
一般情況下, 長按短按, 單擊雙擊。
這兩種區(qū)分按鍵的模式,在沒有必要的前提下,不同時使用。
因為, ...

邏輯不會很亂,因為一次只能檢測一個按鍵
回復(fù)

使用道具 舉報

14#
ID:566214 發(fā)表于 2021-9-24 19:24 | 只看該作者
yzwzfyz 發(fā)表于 2021-9-24 08:52
1、按鍵有彈動,如果沒有防彈動過慮則,則無法界定按了幾下(按一下,彈N次)。
2、防彈動的過慮時間,既 ...

每次單擊都可以檢測到,就是雙擊不行
回復(fù)

使用道具 舉報

15#
ID:332444 發(fā)表于 2021-9-24 19:25 | 只看該作者
dcjdcj 發(fā)表于 2021-9-24 19:16
狀態(tài)機的邏輯可以實現(xiàn)嗎?我同時檢測5顆按鍵

可以,在一定時間范圍內(nèi)對按鍵進行計算得值即可實現(xiàn)組合,計數(shù)可實現(xiàn)雙擊,也可實現(xiàn)按次數(shù),這樣寫起來很方便。
回復(fù)

使用道具 舉報

16#
ID:566214 發(fā)表于 2021-9-24 20:14 | 只看該作者
xianfajushi 發(fā)表于 2021-9-24 19:25
可以,在一定時間范圍內(nèi)對按鍵進行計算得值即可實現(xiàn)組合,計數(shù)可實現(xiàn)雙擊,也可實現(xiàn)按次數(shù),這樣寫起來很 ...

比如,在一段時間內(nèi),第一次按下的鍵值是0x80,第二次按下的鍵值是0x01,然后將這兩個值相或,得到0x81,用0x81區(qū)判斷是不是組合鍵嗎?
回復(fù)

使用道具 舉報

17#
ID:332444 發(fā)表于 2021-9-24 20:45 | 只看該作者
dcjdcj 發(fā)表于 2021-9-24 20:14
比如,在一段時間內(nèi),第一次按下的鍵值是0x80,第二次按下的鍵值是0x01,然后將這兩個值相或,得到0x81, ...

回復(fù)

使用道具 舉報

18#
ID:566214 發(fā)表于 2021-9-24 21:13 | 只看該作者

還有一個問題,一個無源蜂鳴器,比如4k頻率,定時器中斷125us,要怎么驅(qū)動,可否來個例程,謝謝了
回復(fù)

使用道具 舉報

19#
ID:624769 發(fā)表于 2021-9-24 21:28 | 只看該作者
dcjdcj 發(fā)表于 2021-9-24 21:13
還有一個問題,一個無源蜂鳴器,比如4k頻率,定時器中斷125us,要怎么驅(qū)動,可否來個例程,謝謝了

中斷里面一句話

Beep_IO = !Beep_IO;
回復(fù)

使用道具 舉報

20#
ID:566214 發(fā)表于 2021-9-24 21:52 | 只看該作者
188610329 發(fā)表于 2021-9-24 21:28
中斷里面一句話

Beep_IO = !Beep_IO;

Beep_IO = ~Beep_IO;不是這個嗎?那么響一聲要怎么寫,要多久才算一聲
回復(fù)

使用道具 舉報

21#
ID:624769 發(fā)表于 2021-9-24 22:12 | 只看該作者
dcjdcj 發(fā)表于 2021-9-24 21:52
Beep_IO = ~Beep_IO;不是這個嗎?那么響一聲要怎么寫,要多久才算一聲

一般,習(xí)慣上,  字節(jié) 用  ~ 取反, 位 用 !取反。 至少 別人看到我寫的那一行一眼就能知道 Beep_IO 是個位地址。

最后,響一聲,看你打算 長響還是短響, 長響一般 1.5 秒, 短響一般 0.3 秒,(習(xí)慣上)。
回復(fù)

使用道具 舉報

22#
ID:566214 發(fā)表于 2021-9-24 23:16 | 只看該作者
188610329 發(fā)表于 2021-9-24 22:12
一般,習(xí)慣上,  字節(jié) 用  ~ 取反, 位 用 !取反。 至少 別人看到我寫的那一行一眼就能知道 Beep_IO 是 ...

好的,謝謝指教,我試一下
回復(fù)

使用道具 舉報

23#
ID:566214 發(fā)表于 2021-9-25 19:50 | 只看該作者
bbxyliyang 發(fā)表于 2021-9-24 06:48
#include
#include
#define key_state_0 0

觸摸按鍵的,不行,波動按鍵就可以
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 毛片黄片免费看 | 中文字幕一区二区不卡 | 超碰精品在线 | 国产日韩欧美中文字幕 | 正在播放国产精品 | 中文字幕一区在线观看视频 | 情侣酒店偷拍一区二区在线播放 | 国产91av视频 | 欧美13videosex性极品 | 狠狠操狠狠干 | 毛片网在线观看 | 欧美嘿咻 | 午夜精品在线 | 国产一区二区三区欧美 | 国产在线精品一区二区 | 成人免费观看男女羞羞视频 | 久久九精品 | 一本色道精品久久一区二区三区 | 蜜桃免费一区二区三区 | 欧美激情综合 | 亚洲欧美日本在线 | 视频一区在线播放 | 日韩毛片| 精精国产xxxx视频在线 | 日本三级电影免费 | 一a一片一级一片啪啪 | 91免费在线播放 | 久久久久久网 | 欧美成人一区二区三区 | 欧美亚洲视频 | 中文字幕乱码一区二区三区 | 日韩视频免费看 | 综合九九| 午夜看电影在线观看 | 精品粉嫩aⅴ一区二区三区四区 | www网站在线观看 | 一区欧美| 欧美精品一区二区三区在线播放 | 99re视频这里只有精品 | 91精品国产92 | 欧美激情在线一区二区三区 |