討論區快速選單
知識庫快速選單
傑米的攝影旅遊筆記 網路投保旅行平安險 政府補助!學嵌入式+物聯網
[ 回上頁 ] [ 討論區發言規則 ]
請教按鍵彈跳現象的程式撰寫問題
更改我的閱讀文章字型大小
作者 : 520pose(韓靜秀) 人氣指數超過10000點
[ 貼文 77 | 人氣 15279 | 評價 0 | 評價/貼文 0 | 送出評價 47 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2008/4/12 下午 09:19:02
小妹在學校使用80x86組語撰寫按鍵的驅動程式,從鍵盤輸入數字顯示於7段顯示器上,然後按+或-鍵可以將顯示的數值增減!
小妹是已寫好程式了,只是有個疑問請想教那些有寫過單晶片這類控制程式的大大們的經驗!

按鍵彈跳現象就是本來按鍵按一下,正常的情況下只送出1個clock的信號出去,但因為按鍵本身有彈跳現象,所以clock的前後緣會產生連續極短時間的clock,那麼本來明明只是按一下按鍵卻會送出一堆clock,於是可以在clock的前後緣彈跳現象的這段時間,利用delay程式來消除。

但是小妹寫這程式時,乃是寫每讀到+或-鍵,第1步是利用軟體消除彈跳現象後,才將顯示值加1並顯示。
只是不知為何小妹+鍵若一直壓著不放,顯示值卻不斷的+1並顯示?
小妹在程式中判斷按鍵是否一直壓著的部份,這片段並沒寫將資料+並顯示的程式,只是單純判斷是否一直壓著。
-----------------------------------------------
本來功能要求是+鍵按一下就加1下並顯示出來,而我寫的卻變成同時也可以一直壓著+鍵令其不斷+1並顯示,這樣比動手連續按+1還更快。就像手錶調整時間可以一下一下按,也可以一直壓著調較較快!
-------------------------------------------------
我現在是認為可能是因為在利用delay消除彈跳現象的過程中並沒徹底的將前緣所有的極短時間的clock給全部消除。
可能前緣的部份剛好漏掉1個短時間的clock,而我讀取+鍵是否放開的程式片段正巧讀到了它,於是以為我按鍵已放開,便往下執行將資料+1並顯示,然後因為+鍵一直壓著,程式就一直迴圈重覆跑一直執行。
-------------------------------------------------
我想問這想法對嗎?
我消除按鍵彈跳故意只要漏掉1個clock沒消除,那麼我的按鍵功能就可以像手錶調整時間一樣手動按或一直壓著按鈕的功效?

麻煩大大提供 控制程式的經驗 謝謝^^

作者 : 520pose(韓靜秀) 人氣指數超過10000點
[ 貼文 77 | 人氣 15279 | 評價 0 | 評價/貼文 0 | 送出評價 47 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2008/4/12 下午 10:04:28
我仔細想了一下,如果要寫1個像手錶按鍵調整時間可以一下一下的按或是一直壓著讓它自動快速調整的功能,其正確的程式寫法應該為:

當讀取到按鍵壓下後,便輪流判斷 按鍵是否壓著?是則送出資料 ,直到放開便結束!
這樣我的資料送出時間乃在按鍵壓著時才送出,所以我若一直壓著就可以遲續送出!
而我先前所提的正巧只是因為漏掉1個clock這個小bug使得程式也具有這樣的功能,但那不是正確的寫法,可能還會發生其它問題!


麻煩大大指教,我這2篇的想法有錯的話請告訴我3q
作者 : jevoswang(jevos wang) 貼文超過200則
[ 貼文 379 | 人氣 3351 | 評價 880 | 評價/貼文 2.32 | 送出評價 4 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人520pose註記此篇回應為很有道理 2008/4/13 上午 11:16:28
我處理按鍵彈跳的做法是,當捉到按下某個鍵訊號後,再連續捉10筆都是該按鍵值,才表示按了該鍵

放開也是要連續10筆都是放開值,才能代表放開

可以把10筆這個連續值,調為其它的數字

原理是有彈跳,就不可能連續
作者 : hkln(HKLN.net) Perl卓越專家Oracle卓越專家資訊類作業求救優秀好手一般優秀好手程式設計甘苦談優秀好手C#卓越專家貼文超過2000則人氣指數超過100000點
[ 貼文 2135 | 人氣 122272 | 評價 14600 | 評價/貼文 6.84 | 送出評價 7 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人520pose註記此篇回應為很有道理 2008/4/13 下午 02:19:08
假設:所有按鍵都不會彈跳超過 0.5秒,而且使用者放開鍵後超過0.5s才再按

每隔 0.5秒才去讀一次按鍵,用一個變數儲存按鍵狀態,
如果沒有按下,就把它設 0,有按就把它加一,直至加到 10。

如果變數是 1 ,就把讀數加一,
如果變數是 2 至 9,讀數不變,
如果變數是 10 ,代表使用者已經連續按下超過 5 秒,
就以特定的重覆頻率去把讀數加一。

用秒數而不用 clock ,好處是程式比較直觀,
而且容易移植到其它不同 clock rate 的環境。

keyword: software debouncing

(以上我沒實作過)
作者 : liaoo(liaoo) Assembly優秀好手貼文超過500則人氣指數超過10000點
[ 貼文 507 | 人氣 27127 | 評價 1140 | 評價/貼文 2.25 | 送出評價 17 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人520pose註記此篇回應為很有道理 2008/4/13 下午 05:38:07
你所使用的 "鍵" 是哪一種 ? 有沒有辦法用 "硬體電路" 就消除掉開關的 bounce ? 記得textbook上都有 debounce 的電路...

F.Y.I
作者 : 520pose(韓靜秀) 人氣指數超過10000點
[ 貼文 77 | 人氣 15279 | 評價 0 | 評價/貼文 0 | 送出評價 47 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2008/4/13 下午 07:38:53
學校實習的那種4*4小鍵盤,本身硬體部份沒有消除按鍵彈跳。
有消除按鍵彈跳的鍵盤也較貴!
不過我正討論的是本身硬體方面沒消除的。
作者 : 520pose(韓靜秀) 人氣指數超過10000點
[ 貼文 77 | 人氣 15279 | 評價 0 | 評價/貼文 0 | 送出評價 47 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2008/4/13 下午 09:20:47
另一方面若以軟體方式來消除彈跳現象是不是以delay程式來消除是最好的寫法? 因為程式最好寫?
作者 : balor(balor)
[ 貼文 36 | 人氣 5 | 評價 200 | 評價/貼文 5.56 | 送出評價 0 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人520pose註記此篇回應為很有道理 2008/4/13 下午 09:26:33
Hi,
     你可以考慮一下下面的作法(keyboard matrix on notebook)
     (pseudo code)::

     keyscan(void) // timebase is 100ms
     {
     Flag = IsAnyKeyOnMatrix(); // Any key is now pressed.
     if(Flag == true) // Yes.
     {
     KeyXY=GetKeyXYFromMatrix(); // Get the key XY from matrix
     if(IsANewKey(KeyXY))
     {
     PutKeyToBuf(KeyXY); // Put it to keyboard buffer
     }
     else
     {
     if(IsDeBouncedKey(KeyXY)) // 確認debounce 完成了嗎?
     {
     SendMackCodeToHost(KeyXY);
     }
     else
     {
     KeyXY.Time++;
     if(Key.Time >= 30)
     KeyXY.DeBounceFlag=true; // if time > 0.3s, debounce 結束.
     }
     }
     }
     else
     {
     SendBreakCode(KeyXY);
     }
     }

    For example, 當你按下了enter key.
    KBC 會先做debounce (about 0.3s) 然後0.5s 後會送第一個make code 0x1c
    之後如果還是按著的話, 每0.3s 會再送一次make code.
    放掉後會送break code 0x9c to host.

    希望對你有點幫助...

Balor
作者 : jevoswang(jevos wang) 貼文超過200則
[ 貼文 379 | 人氣 3351 | 評價 880 | 評價/貼文 2.32 | 送出評價 4 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人520pose註記此篇回應為很有道理 2008/4/14 上午 10:42:26
delay 表面上是好寫,但僅限於範例在練習用,真正的實作電路,按鍵掃描都是用定時中斷來掃描,如果用delay 的話 8051 就要卡死在那裡一段 delay 的時間 .

善用中斷副程式,如上文的做法
作者 : 520pose(韓靜秀) 人氣指數超過10000點
[ 貼文 77 | 人氣 15279 | 評價 0 | 評價/貼文 0 | 送出評價 47 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2008/4/14 下午 05:25:40
因為我志在從事單晶片的工作,所以想問樓上的大大您是指利用8051提供的int中斷就可消除彈跳現象嗎? 因為上一段大大的程式介紹 我並不懂那樣寫是作什麼的?
作者 : jevoswang(jevos wang) 貼文超過200則
[ 貼文 379 | 人氣 3351 | 評價 880 | 評價/貼文 2.32 | 送出評價 4 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人520pose註記此篇回應為很有道理 2008/4/14 下午 05:49:43
jevos_wang@hotmail.com
直接找我比較快,如果你是用 8051c 寫的,就傳給我,我抽個空幫你改一改測一測,問題就解決了
作者 : 520pose(韓靜秀) 人氣指數超過10000點
[ 貼文 77 | 人氣 15279 | 評價 0 | 評價/貼文 0 | 送出評價 47 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2008/4/14 下午 08:15:14
抱歉! 我不是用單晶片寫,而是用80x86組合語言透過8255撰寫i/o元件驅動程式寫的
作者 : balor(balor)
[ 貼文 36 | 人氣 5 | 評價 200 | 評價/貼文 5.56 | 送出評價 0 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人520pose註記此篇回應為很有道理 2008/4/14 下午 08:52:41

>抱歉! 我不是用單晶片寫,而是用80x86組合語言透過8255撰寫i/o元件驅動程式寫的

Hi,
     我好像寫得有點複雜... 改一種做法吧...

     int KBCState = 0;
     int DBTime=0;

     KeyScan() // 100ms
     {
    
     switch(KBCState)
     case 0: // Waiting for a key.
     if(AnyKeyIsPressed)
     KBCState++; // advance to next state.
     case 1: // debounce state
     if(KeyStillBeingPressed)
     {
     DBTime++; // increase the debounce timer
     if (DBTime >= 30)
     KBCState++;
     }
     else
     KBCState = 0; // Debounce faile back to wait state
     case 2: // Send Scan code to Host state.
     SendMakeCode(); // send code to host
     DBTime=0; // reset timer
     KBCState=1; // check repart key after 0.3s
     default:
     KBCState=0;
     }
     }

   希望可以幫到你....

   Balor
作者 : 520pose(韓靜秀) 人氣指數超過10000點
[ 貼文 77 | 人氣 15279 | 評價 0 | 評價/貼文 0 | 送出評價 47 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2008/4/14 下午 11:18:44
你好!

你的程式其資料處理的演算法是在寫您所提的:
KBC 會先做debounce (about 0.3s) 然後0.5s 後會送第一個make code 0x1c
    之後如果還是按著的話, 每0.3s 會再送一次make code.
    放掉後會送break code 0x9c to host.

---------------------------------------
我想問debounce應該是消除按鍵彈跳其clock前緣部份的程式吧?
而按鍵從壓下後不放的過程中就一直產生0x1c這個code,但產生這個code的用意是什麼?
然後按鍵放開後中斷code送0x9c這個code來消除彈跳又是為了什麼?

想請問這送code動作是提出中斷副程式,利用它來消除彈跳現象嗎? 謝謝!
作者 : liaoo(liaoo) Assembly優秀好手貼文超過500則人氣指數超過10000點
[ 貼文 507 | 人氣 27127 | 評價 1140 | 評價/貼文 2.25 | 送出評價 17 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人520pose註記此篇回應為很有道理 2008/4/15 上午 09:39:37

>你好!
>
>你的程式其資料處理的演算法是在寫您所提的:
>KBC 會先做debounce (about 0.3s) 然後0.5s 後會送第一個make code 0x1c
> 之後如果還是按著的話, 每0.3s 會再送一次make code.
> 放掉後會送break code 0x9c to host.
>
>---------------------------------------
>我想問debounce應該是消除按鍵彈跳其clock前緣部份的程式吧?
>而按鍵從壓下後不放的過程中就一直產生0x1c這個code,但產生這個code的用意是什麼?
>然後按鍵放開後中斷code送0x9c這個code來消除彈跳又是為了什麼?
>
>想請問這送code動作是提出中斷副程式,利用它來消除彈跳現象嗎? 謝謝!

我想是這樣的:
1. 在一般的電腦鍵盤上,其按鍵的運作是:按下去產生了 make code,放掉則產生了break code. 由這兩者的組合 host 就知道 user按了什麼鍵.所以,make-break pair就代表了一次的 "按->放" for one key.
2. 當user按了之後不放,則 break code無法送出,只有 make code...此時,可以:
a. 一定要等到 break code產生才做事情,或
b. 即使 break code沒有,在這段期間(壓著不放)持續送 make code,而且也做事情

以上為一般電腦的鍵盤的運作....只是,這似乎不能用在你的 4x4 鍵盤上...當然,觀念可以用 !


妳的程式最終要達到什麼目的呢 ? 是只有偵測 4x4 key然後 加減一 ? 還是會擴充成其他應用 ? 或許大家就可以就妳所需提供適合的建議...

若是只是前者,那大可以不必利用中斷的方式,而用 polling 的方式達到妳的需求....

妳已經有寫一套出來了嗎 ? 先求有在來求發展吧....假如進度很趕...若是自己玩的就可以多方研究了...
作者 : 520pose(韓靜秀) 人氣指數超過10000點
[ 貼文 77 | 人氣 15279 | 評價 0 | 評價/貼文 0 | 送出評價 47 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2008/4/15 下午 02:20:07
我的意思是指如何撰寫 按鍵按一下放開及即使一直壓著 也仍然作同一件事情的程式!
像我一開始僅只是撰寫4*4小鍵盤按+-鍵能進行加1減1的動作,並且程式也寫好了,因可能因為利用delay消除彈跳現象的過程中漏了1個clock沒消除完,使得我按鍵即使只是壓著也會連續進行加1減1的動作,那麼我的按鍵功能不就變成了按鍵放開後及一直壓著 都會做事情的功能了.....

但是我覺得這應該不是正確的寫法,應該是bug,所以想請教正確的寫法?
而大大您剛才提到的電腦鍵盤,我突然想到之前大大po的c程式應該是指電腦鍵盤掃描的程式,而電腦鍵盤本身並無機械彈跳現象吧?

作者 : liaoo(liaoo) Assembly優秀好手貼文超過500則人氣指數超過10000點
[ 貼文 507 | 人氣 27127 | 評價 1140 | 評價/貼文 2.25 | 送出評價 17 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人520pose註記此篇回應為最佳解答 2008/4/15 下午 04:02:09
* 之前的電腦鍵盤掃描的程式是其他人 po 的...and 我認為電腦鍵盤本身的的彈跳是用硬體解決的...


[前提/假設]
1. 妳的接線方式為坊間書上寫的一樣,都是: 4-bit 掃描線 + 4-bit 讀入線,利用週期性的掃描線+讀入線來判斷有無按鍵及按的是哪個鍵.而且,有按鍵得到的訊號 = 0 ; 沒按得到的是 1...
2. 先不考慮多個鍵一起按的情況

--------------------------------------------------------------------------
順著妳的想法,妳想做到的是:下面兩個 case 都做一樣的事情,且...只做一次:
case 1: user 按 -> 放
case 2: user 按 -> 壓 -> 放 ( 當然,壓的時間由 user決定 )

所以,不管 user 壓多久,上面的兩個 case 都有 "一個共同點",就是都得經歷 2 phase:
a. 訊號由 1->0
b. 訊號由 0->1

換句話說,只要妳看到 a && b 都成立了,才算一次完整的按鍵動作,也才做事情 !
這樣,妳擔心的 case 2 只做一次而已...right ?

也就是:
=> (看到 1-> 0) && (看到 0->1) then +/- 1

--------------------------------------------------------------------------
假如,有人質疑,假如在 case 2, user 長按 10 sec,那不是 10 sec後才看到七段顯示器 +1 ?

那麼,妳仍然可以改成下列的方式:
=> (看到 1-> 0) then +/-1 ; 但此時要多 set one flag,用以判斷要不要再做+/- 1的動作 ! 而 (看到 0->1) 可以 clear that flag.

此後,即使 user 壓著不放,因為 該 flag = 1,所以仍然不做 +/- 1動作.直到有人把它清掉 ( <- (看到 0->1) 這段 code 要負責清 fllag...)

---------------------------------------------------------------------------
現在,問題只有剩下: 如何 implement (看到 1-> 0) & (看到 0-> 1).....

1 現實狀況下的彈跳波型為: 111111010101010000000000000010101011111
(0表 low voltage, 1 表 high voltage)
2 查到的doc都說明: 這種機械式的彈跳,基本上不會 over 20ms. 所以,可以讀到值後,delay 20ms,再次 check value來判斷案件是否被按下.(當然,妳也可以用示波器看看到底 bounce 撐了多久來決定此 delay...)
3 所以,

   (看到 1-> 0)變成:
   - read value
   - if value = 0 then delay 20ms
     else continue to read
 
    (看到 0-> 1)變成:
   - read value
   - if value = 1 then delay 20ms
     else continue to read
-----------------------------------------------------------------------------

僅供參考...
   
作者 : balor(balor)
[ 貼文 36 | 人氣 5 | 評價 200 | 評價/貼文 5.56 | 送出評價 0 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人520pose註記此篇回應為很有道理 2008/4/15 下午 10:51:29

恕略...
>僅供參考...
>
>

這位高手寫的很詳細. 小弟就不班門弄斧了...

BTW, 在notebook上的KBC(keyboard controller) 就是需要做debounce 的動作.
除此之外, 還要做ghost key的檢查及考慮有多個按鍵的組合(for example, ALT+ESC)

所以我想最最簡易的方法就是, 當你發現有按鍵被按下後... 一直等到它被放開, 才認為有這個按鍵. 而去做相對應的動作.

Balor
 板主 : 徵求中
 > 組合語言 - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - 組合語言 - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
組合語言
1 H 2220 
2 liaoo 990 
3 青衫 970 
4 牧童哥 940 
5 史努比 920 
6 qq 480 
7 GHOST-JACKY 330 
8 ]CALL-151 310 
9 harrison 300 
10 掌握文武半邊天 280 
組合語言
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2019 程式設計俱樂部 http://www.programmer-club.com.tw/
0.09375