在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

STM單片機(jī)中的按鍵消抖和FPGA消抖

454398 ? 來源:alpha007 ? 作者:alpha007 ? 2022-11-30 17:39 ? 次閱讀

寫在前面:

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

1、單片機(jī)中按鍵消抖程序

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

軟件消抖程序:

if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14)==1)
{
delay_ms(20);// 延時 20ms 再去檢測按鍵值
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14)==0) // 相當(dāng)于下降沿
{
KEY1 = 1; // 表示 KEY1 被按下
}
}

1.2 比較全面的按鍵消抖程序及按鍵狀態(tài)檢測程序

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

第二步:初始化按鍵對應(yīng)的 IO,復(fù)用為邊沿觸發(fā)的外部中斷。

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

代碼部分:
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

簡單定義一個按鍵狀態(tài)的結(jié)構(gòu)體,用于管理每個按鍵的狀態(tài)。順便再定義一個長短按的識別閾值,用于區(qū)分按鍵的長短按。

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;
}
}


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

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

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

2、FPGA 按鍵消抖程序

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

假定按鍵的默認(rèn)狀態(tài)為 0,被按下后為 1
假定按鍵抖動時長小于 20ms,也即使用 20ms 的消抖時間

核心:方案

最容易想到的方案

在按鍵電平穩(wěn)定的情況下,當(dāng)?shù)谝淮螜z測到鍵位電平變化,開始 20ms 計時,計時時間到后將按鍵電平更新為當(dāng)前電平。

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

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

消除按鍵反應(yīng)延時抖方案

在有電平變化時立即改變按鍵輸出電平,并開始 20ms 計時,忽略這其中抖動
測試平臺設(shè)計(修改代碼以仿真的 1us 代替實(shí)際 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

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

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

審核編輯黃昊宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1630

    文章

    21802

    瀏覽量

    606368
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6044

    文章

    44627

    瀏覽量

    638972
  • STM
    STM
    +關(guān)注

    關(guān)注

    1

    文章

    557

    瀏覽量

    42599
  • 按鍵消抖
    +關(guān)注

    關(guān)注

    2

    文章

    27

    瀏覽量

    10497
收藏 人收藏

    評論

    相關(guān)推薦

    單片機(jī)按鍵與幾種按鍵電路

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

    fpga教程之——按鍵

    電平,這次對按鍵進(jìn)行操作則是對FPGA進(jìn)行輸入了。  2. 按鍵  2.1 按鍵輸入原理  
    發(fā)表于 02-27 11:49

    按鍵

    請問大家的按鍵是用什么方法解決的,如普通的按鍵如何。
    發(fā)表于 09-26 22:17

    FPGA按鍵的方法

    FPGA按鍵的方法
    發(fā)表于 05-01 16:12

    技術(shù)分享:明德?lián)P按鍵的原理和基于fpga設(shè)計

    本帖最后由 明德?lián)P吳老師 于 2017-8-2 11:45 編輯 按鍵1功能概述按鍵開關(guān)是各種電子設(shè)備不可或缺的人機(jī)接口,如電腦的鍵盤等。實(shí)際應(yīng)用
    發(fā)表于 08-02 10:38

    51單片機(jī)_獨(dú)立按鍵延時

    51單片機(jī)_獨(dú)立按鍵延時_獨(dú)立按鍵定時器_矩
    發(fā)表于 07-16 13:56

    按鍵及原理是什么

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

    MCU按鍵問題

    按鍵問題機(jī)械按鍵是必須的,1、延時
    發(fā)表于 11-04 06:37

    STM32單片機(jī)按鍵FPGA按鍵的相關(guān)資料分享

    寫在前面:STM32單片機(jī)按鍵FPGA按鍵
    發(fā)表于 01-18 06:39

    基于FPGA按鍵電路設(shè)計

    采用了VHDL語言編程的設(shè)計方法,通過FPGA來實(shí)現(xiàn)按鍵的硬件電路。論述了基于計數(shù)器、RS觸發(fā)器和狀態(tài)機(jī)3種方法來實(shí)現(xiàn)
    發(fā)表于 12-05 14:13 ?224次下載

    單片機(jī)按鍵程序

    效率上來說,延時花費(fèi)時間在無意義延時上,而相對較好的定時輪詢還是不可避免的在輪詢,而現(xiàn)在這種方式完全是中斷性質(zhì)的。唯一多出的開銷(全局時間戳)并不是只可以用于按鍵
    的頭像 發(fā)表于 06-19 08:55 ?3.2w次閱讀
    <b class='flag-5'>單片機(jī)</b><b class='flag-5'>中</b><b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>程序

    51單片機(jī)的獨(dú)立按鍵按鍵及矩陣按鍵的電路與程序免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是51單片機(jī)的獨(dú)立按鍵按鍵及矩陣按鍵的電路與程序免費(fèi)下載。
    發(fā)表于 07-26 17:36 ?28次下載
    51<b class='flag-5'>單片機(jī)</b>的獨(dú)立<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>的電路與程序免費(fèi)下載

    使用51單片機(jī)實(shí)現(xiàn)按鍵的資料和程序免費(fèi)下載

    抖動是機(jī)械按鍵存在的現(xiàn)象,是必須要進(jìn)行處理的。一般處理有兩種方式:一種是硬件,另一種是軟件。硬件
    發(fā)表于 07-05 17:41 ?5次下載
    使用51<b class='flag-5'>單片機(jī)</b>實(shí)現(xiàn)<b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>的資料和程序免費(fèi)下載

    單片機(jī)按鍵電路圖免費(fèi)下載

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

    如何在FPGA實(shí)現(xiàn)按鍵

    FPGA(現(xiàn)場可編程門陣列)實(shí)現(xiàn)按鍵是一個重要的設(shè)計環(huán)節(jié),特別是在處理用戶輸入時,由于物理按鍵
    的頭像 發(fā)表于 08-19 18:15 ?2249次閱讀
    主站蜘蛛池模板: 亚洲高清一区二区三区 | 亚洲精品美女视频 | 2021天天操 | 欧美1314www伊人久久香网 | 日本免费视频 | 日本免费黄色 | 天堂影 | 糖心vlog麻豆精东影业传媒 | 国产手机在线看片 | 韩国理论三级在线观看视频 | 国产日日夜夜 | 国产农村一级特黄α真人毛片 | 日本在线不卡一区 | 两性色午夜视频免费网 | 色老头视频在线观看 | 天堂网2021天堂手机版 | 亚洲成年人影院 | 影音先锋五月天 | 五月激情六月婷婷 | 色www国产阿娇 | 天天爽天天狼久久久综合 | 加勒比日本道 | 亚洲成片在线观看12345ba | 久久久久99精品成人片三人毛片 | www.欧美色图 | 欧美成人精品一区二三区在线观看 | аⅴ天堂中文在线网 | 久久精品第一页 | 黄色在线网 | 清冷双性被cao的合不拢腿 | 成年网站在线在免费播放 | 亚洲美女视频一区 | 手机看片1024精品日韩 | 日本三级网站在线线观看 | 80s国产成年女人毛片 | 欧美一级特黄乱妇高清视频 | 黄网观看 | 免费高清在线观看a网站 | 国产精品一区二区三区四区 | 天天舔| 伊人久久香 |