色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

單片機中按鍵消抖程序

0BFC_eet_china ? 來源:未知 ? 作者:李倩 ? 2018-06-19 08:55 ? 次閱讀

寫在前面:

按鍵去抖:由上圖可以看出理想波形與實際波形之間是有區別的,實際波形在按下和釋放的瞬間都有抖動的現象,抖動時間的長短和按鍵的機械特性有關,一般為5~10ms。通常我們手動按鍵然后釋放,這個動作中穩定閉合的時間超過了20ms。因此單片機檢測鍵盤是否按下時都要加上去抖動操作,有專用的去抖動電路,也有專門的去抖動芯片,但通常我們采用軟件延時的方法就可以解決抖動問題。

1、單片機中按鍵消抖程序

1.1 單片機中,比如STM32中,一般的方法(最簡單的方法)

軟件消抖程序:

if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14)==1){delay_ms(20);//延時20ms再去檢測按鍵值if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14)==0) // 相當于下降沿

{

KEY1 = 1; //表示KEY1被按下

}

}

1.2 比較全面的按鍵消抖程序及按鍵狀態檢測程序

第一步:初始化全局時間戳的定時器,一般采用SysTick定時器來產生,每ms一次tick即可。

第二步:初始化按鍵對應的IO,復用為邊沿觸發的外部中斷。

第三步:在外部中斷函數中添加按鍵事件處理函數。

代碼部分:

typedef struct _Key_t

{

u32 last_time;

enum

{

May_Press,

Release,

}private_state;

enum

{

No_Press,

Short_Press,

Long_Press,

}state;

}Key_t;

#define Is_ShortPress_Threshold 1500

簡單定義一個按鍵狀態的結構體,用于管理每個按鍵的狀態。順便再定義一個長短按的識別閾值,用于區分按鍵的長短按。

if(key_state.private_state==Release)

{

if(KEY==0)

{

key_state.private_state=May_Press;

key_state.last_time=course_ms();

}

}

else if(key_state.private_state==May_Press)

{

if(KEY==1)

{

if((course_ms()-key_state.last_time>10)&&(course_ms()-key_state.last_time

{

key_state.state=Short_Press;

key_state.private_state=Release;

}

else if(course_ms()-key_state.last_time>Is_ShortPress_Threshold)

{

key_state.state=Long_Press;

key_state.private_state=Release;

}

else

key_state.private_state=Release;

}

}

以上為需要添加到中斷處理函數的按鍵事件處理函數,算法的核心是一個狀態機。在本例中,按鍵被默認上拉,按下接地。course_ms()為獲取全局時間戳的函數。

思路解釋如下:按鍵狀態結構體有一個用于識別的狀態位,默認處于Release,也就是釋放的狀態。一旦按鍵被按下,中斷觸發,此時檢查是否是Relase狀態,如果是就檢查按鍵是否被拉低,如果是,此時進入May_Press狀態,也就是可能是按下的,并且記錄此時的時間戳,這一步是消抖的關鍵。當按鍵被釋放,由于是邊沿觸發,會再次進行處理,此時檢查和上一次觸發之間的時間戳之差,如果小于10ms我們就認為是抖動,此時不會對按鍵輸出狀態進行修改,而是直接將按鍵狀態置回Relase狀態,反之檢查差值和長短按閾值之間的關系,將state置位為對應的狀態。消抖的核心在于記錄時間戳,而這只是一個簡單的賦值操作,并不耗費時間。

效率上來說,延時消抖花費時間在無意義延時上,而相對較好的定時輪詢還是不可避免的在輪詢,而現在這種方式完全是中斷性質的。唯一多出的開銷(全局時間戳)并不是只可以用于按鍵消抖,另外在HAL庫中存在直接獲取tick的函數,這樣實現就更方便了。經實際測試,消抖效果可以達到其他兩種消抖算法的水平。

2、FPGA按鍵消抖程序

首先,做兩個假定,以方便后面的描述:

假定按鍵的默認狀態為0,被按下后為1

假定按鍵抖動時長小于20ms,也即使用20ms的消抖時間

核心:方案

最容易想到的方案

在按鍵電平穩定的情況下,當第一次檢測到鍵位電平變化,開始20ms計時,計時時間到后將按鍵電平更新為當前電平。

或許這才是最容易想的方案

在20ms計時的過程中,有任何的電平變化都立即復位計時

消除按鍵反應延時抖方案

在有電平變化時立即改變按鍵輸出電平,并開始20ms計時,忽略這其中抖動

測試平臺設計(修改代碼以仿真的1us代替實際1ms)

無抖動 上升沿抖動5毫秒

下降沿抖動15毫秒

上升和下降沿均抖動19毫秒

附加測試(可以不通過)

抖動25毫秒

代碼

方案1

module debounce( input wire clk, nrst, input wire key_in, output reg key_out ); // 20ms parameter// localparam TIME_20MS = 1_000_000; localparam TIME_20MS = 1_000; // just for test // variable reg [20:0] cnt; reg key_cnt; // debounce time passed, refresh key state always @(posedge clk or negedge nrst) begin if(nrst == 0) key_out <= 0; ? ? ? ?else if(cnt == TIME_20MS - 1) ? ? ? ? ? ?key_out <= key_in; ? ?end // while in debounce state, count, otherwise 0 always @(posedge clk or negedge nrst) begin if(nrst == 0) ? ? ? ? ? ?cnt <= 0; ? ? ? ?else if(key_cnt) ? ? ? ? ? ?cnt <= cnt + 1'b1; else ? ? ? ? ? ?cnt <= 0; ? ?end // always @(posedge clk or negedge nrst) begin if(nrst == 0) ? ? ? ? ? ? ? ?key_cnt <= 0; ? ? ? ? ? ?else if(key_cnt == 0 && key_in != key_out) ? ? ? ? ? ? ? ?key_cnt <= 1; ? ? ? ? ? ?else if(cnt == TIME_20MS - 1) ? ? ? ? ? ? ? ?key_cnt <= 0; ? ? endendmodule

方案2

module debounce( input wire clk, nrst, input wire key_in, output reg key_out );// localparam TIME_20MS = 1_000_000; localparam TIME_20MS = 1_000; reg key_cnt; reg [20:0] cnt; always @(posedge clk or negedge nrst) begin if(nrst == 0) key_cnt <= 0; ? ? ? ?else if(cnt == TIME_20MS - 1) ? ? ? ? ? ?key_cnt <= 0; ? ? ? ?else if(key_cnt == 0 && key_out != key_in) ? ? ? ? ? ?key_cnt <= 1; ? ?end always @(posedge clk or negedge nrst) begin if(nrst == 0) ? ? ? ? ? ?cnt <= 0; ? ? ? ?else if(key_cnt) begin if(key_out == key_in) ? ? ? ? ? ? ? ?cnt <= 0; ? ? ? ? ? ?else ? ? ? ? ? ? ? ?cnt <= cnt + 1'b1; end else ? ? ? ? ? ?cnt <= 0; ? ?end always @(posedge clk or negedge nrst) begin if(nrst == 0) ? ? ? ? ? ? ? ?key_out <= 0; ? ? ? ? ? ?else if(cnt == TIME_20MS - 1) ? ? ? ? ? ? ? ?key_out <= key_in; ? ? endendmodule

方案3

module debounce( input wire clk, nrst, input wire key_in, output reg key_out );// localparam TIME_20MS = 1_000_000; localparam TIME_20MS = 1_000; // just for test reg key_cnt; reg [20:0] cnt; always @(posedge clk or negedge nrst) begin if(nrst == 0) key_cnt <= 0; ? ? ? ?else if(key_cnt == 0 && key_out != key_in) ? ? ? ? ? ?key_cnt <= 1; ? ? ? ?else if(cnt == TIME_20MS - 1) ? ? ? ? ? ?key_cnt <= 0; ? ?end always @(posedge clk or negedge nrst) begin if(nrst == 0) ? ? ? ? ? ?cnt <= 0; ? ? ? ?else if(key_cnt) ? ? ? ? ? ?cnt <= cnt + 1'b1; else ? ? ? ? ? ?cnt <= 0; ? ?end always @(posedge clk or negedge nrst) begin if(nrst == 0) ? ? ? ? ? ?key_out <= 0; ? ? ? ?else if(key_cnt == 0 && key_out != key_in) ? ? ? ? ? ?key_out <= key_in; ? ?endendmodule

測試代碼

// 按鍵消抖測試電路// 時間單位`timescale 1ns/10ps// modulemodule debounce_tb; // time period parameter localparam T = 20; // variable reg clk, nrst; reg key_in; wire key_out; // instantiate debounce uut( .clk (clk ), .nrst (nrst ), .key_in (key_in ), .key_out(key_out) ); // clock initial begin clk = 1; forever #(T/2) clk = ~clk; end // reset initial begin nrst = 1; @(negedge clk) nrst = 0; @(negedge clk) nrst = 1; end // key_in initial begin // initial value key_in = 0; // wait reset repeat(3) @(negedge clk); // no bounce // key down key_in = 1; // last 60ms repeat(3000) @(negedge clk); // key up key_in = 0; // wait 50ms repeat(2500) @(negedge clk); // down 5ms, up 15ms // key down, bounce 5ms repeat(251) @(negedge clk) key_in = ~key_in; // last 60ms repeat(3000) @(negedge clk); // key up, bounce 15ms repeat(751) @(negedge clk) key_in = ~key_in; // wait 50ms repeat(2500) @(negedge clk); // down 19ms, up 19ms // key down, bounce 19ms repeat(951) @(negedge clk) key_in = ~key_in; // last 60ms repeat(3000) @(negedge clk); // key up, bounce 19ms repeat(951) @(negedge clk) key_in = ~key_in; // wait 50ms repeat(2500) @(negedge clk); // additional, this situation shoud not ever happen // down 25ms, up 25ms // key down, bounce 25ms repeat(1251) @(negedge clk) key_in = ~key_in; // last 60ms repeat(3000) @(negedge clk); // key up, bounce 25ms repeat(1251) @(negedge clk) key_in = ~key_in; // wait 50ms repeat(2500) @(negedge clk); // stop $stop; endendmodule

放在最后的,并不一定是最不重要的

對于上面的三種方案,我比較喜歡第三種方案,它更貼合實際的按鍵狀態,以上的代碼我都做過modelsim仿真,但還沒有在實際的項目中驗證。在整理準備這個博客的時候,我又想到了一個感覺是更巧妙的方案,具體是這樣的:在第三個方案的基礎上,因為按鍵輸入有變化的第一時刻,輸出就已經改變了,在這種情況下,我可以把計時的時長改為一個很小的值,該值只要比抖動中的最長高低電平變化時間長即可。但想想也沒這個必要,且這個抖動的高低電平變化時長我也很難去給它界定一個值。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • FPGA
    +關注

    關注

    1629

    文章

    21729

    瀏覽量

    603013
  • 單片機
    +關注

    關注

    6035

    文章

    44554

    瀏覽量

    634668

原文標題:STM32單片機按鍵消抖和FPGA按鍵消抖大全

文章出處:【微信號:eet-china,微信公眾號:電子工程專輯】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    單片機按鍵與幾種按鍵電路

    按鍵電路 一、 硬件按鍵電路控制電路 所示利用RC 積分電路來達成雜波的濾除與波形修整的
    的頭像 發表于 12-17 07:45 ?10.6w次閱讀
    <b class='flag-5'>單片機</b>的<b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>與幾種<b class='flag-5'>按鍵</b>電路

    51單片機_獨立按鍵延時

    51單片機_獨立按鍵延時_獨立按鍵定時器_矩
    發表于 07-16 13:56

    按鍵及原理是什么

    淺談:在設計單片機按鍵輸入的時候,進行按鍵是防止按鍵輸入被CPU誤讀多次的必要手段。一、
    發表于 07-21 06:02

    STM32單片機定時器做按鍵原因

    STM32單片機定時器做按鍵原因:直接用軟件延時做會暫用整個資源,導致
    發表于 11-26 07:13

    STM32單片機按鍵和FPGA按鍵的相關資料分享

    寫在前面:STM32單片機按鍵和FPGA按鍵
    發表于 01-18 06:39

    51單片機按鍵有沒有什么簡潔又完美的方法?

    51單片機按鍵有沒有什么簡潔又完美的方法
    發表于 11-01 07:21

    利用狀態按鍵程序

    利用狀態按鍵程序講解,很好的資料下載吧。
    發表于 01-11 09:32 ?30次下載

    51單片機的獨立按鍵按鍵及矩陣按鍵的電路與程序免費下載

    本文檔的主要內容詳細介紹的是51單片機的獨立按鍵按鍵及矩陣按鍵的電路與
    發表于 07-26 17:36 ?28次下載
    51<b class='flag-5'>單片機</b>的獨立<b class='flag-5'>按鍵</b>和<b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>及矩陣<b class='flag-5'>按鍵</b>的電路與<b class='flag-5'>程序</b>免費下載

    使用51單片機實現按鍵的資料和程序免費下載

    不是測試過程。一般不會選擇通過狀態延時來,而是通過定時循環測試按鍵的狀態來。下面是針對51單片機
    發表于 07-05 17:41 ?5次下載
    使用51<b class='flag-5'>單片機</b>實現<b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>的資料和<b class='flag-5'>程序</b>免費下載

    使用51單片機實現矩陣按鍵的掃描和動作分離的程序免費下載

    本文檔的主要內容詳細介紹的是使用51單片機實現矩陣按鍵的掃描和動作分離的程序免費下載。
    發表于 07-04 17:41 ?5次下載
    使用51<b class='flag-5'>單片機</b>實現矩陣<b class='flag-5'>按鍵</b>的掃描<b class='flag-5'>消</b><b class='flag-5'>抖</b>和動作分離的<b class='flag-5'>程序</b>免費下載

    單片機按鍵電路圖免費下載

    本文檔的主要內容詳細介紹的是單片機按鍵電路圖免費下載。
    發表于 07-01 08:00 ?10次下載
    <b class='flag-5'>單片機</b><b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>電路圖免費下載

    STM單片機按鍵和FPGA

    閉合的時間超過了 20ms。因此單片機在檢測鍵盤是否按下時都要加上去抖動操作,有專用的去抖動電路,也有專門的去抖動芯片,但通常我們采用軟件延時的方法就可以解決抖動問題。 1、單片機按鍵
    的頭像 發表于 11-30 17:39 ?2695次閱讀

    單片機按鍵及原理(硬件和軟件方法詳解)

    淺談:在設計單片機按鍵輸入的時候,進行按鍵是防止按鍵輸入被CPU誤讀多次的必要手段。一、
    發表于 11-11 12:06 ?15次下載
    【<b class='flag-5'>單片機</b>】<b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>及原理(硬件和軟件方法詳解)

    STM32單片機定時器做按鍵

    STM32單片機定時器做按鍵原因:直接用軟件延時做會暫用整個資源,導致
    發表于 11-19 11:21 ?32次下載
    STM32<b class='flag-5'>單片機</b>定時器做<b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>

    單片機按鍵檢測程序(定時器法

    單片機按鍵檢測程序(定時器法)相信大家在初學51單片機的時候
    發表于 11-23 17:51 ?5次下載
    <b class='flag-5'>單片機</b><b class='flag-5'>按鍵</b>檢測<b class='flag-5'>程序</b>(定時器法<b class='flag-5'>消</b><b class='flag-5'>抖</b>)
    主站蜘蛛池模板: 午夜福利免费0948视频| 久久精品国产亚洲精品2020| 宝贝你骚死哥了好爽| 2020亚洲国产在线播放在线| 亚洲久久少妇中文字幕| 香蕉尹人综合精品| 四虎影视永久无码精品| 少妇高潮久久久久7777| 色婷婷国产麻豆AV| 涩涩视频在线看| 双腿被绑成M型调教PLAY照片| 日本激情网址| 三级黃60分钟| 我和黑帮老大第365天第2季在线| 爽死你个放荡粗暴小淫货漫画| 十分钟免费视频大全在线| 上原结衣快播| 亚洲 欧美无码原创区| 小莹的性荡生活| 亚洲免费成人| 在线日本v二区不卡| 99精品欧美一区二区三区美图| 99精彩免费观看| 成人国产精品免费网站| 囯产精品久久久久免费蜜桃 | 欧美高清另类video| 欧美丰满熟妇无码XOXOXO| 欧美黄色xxx| 色欲久久精品AV无码| 午夜在线观看免费完整直播网| 亚洲精品久久一区二区三区四区| 亚洲欧洲日产国产 最新| 在线观看国产精选免费| 99久久久久国产精品免费| 成人在线免费观看| 国产露脸无码A区久久| 狠狠国产欧美在线视频| 乱子伦在线观看中文字幕| 欧美最猛黑人XXXXWWW| 偷偷鲁青春草原视频分类| 夜蒲团之5阳性之教|