精华内容
下载资源
问答
  • 大多数单片机程序里,都是使用软件消抖,也就是先触发一次,然后延时5ms再检验一次。软件消抖的好处是使硬件变得简单化,当然也有坏处,就是使检验组合按键变得复杂,程序延时也积累的更多。 搜罗了网上的资料,并且...

    大多数单片机程序里,都是使用软件消抖,也就是先触发一次,然后延时5ms再检验一次。软件消抖的好处是使硬件变得简单化,当然也有坏处,就是使检验组合按键变得复杂,程序延时也积累的更多。
    搜罗了网上的资料,并且经过实际电路验证,有以下两种方法实现硬件消抖。
    1、使用电容。电路图如下:
    在这里插入图片描述
    共使用两个电阻和一个电容,相当于用电容实现硬件的延时,使得检验更准确。
    2、rs触发器
    我使用74ls279n做试验,电路图如下:
    在这里插入图片描述rs触发器是使用逻辑电路,不怕任何的按键抖动,而且没有使用电容,所以可以看做没有延迟。
    但是相对于电容消抖rs触发器有两个端点,r与s两个端点要互反点位的关系,所以不能使用普通的两脚微动开关,要使用三脚微动开关。
    一个rs触发器芯片有四个rs触发器,所以可以接四路开关,我自己是比较倾向使用这个方案的。

    展开全文
  • 按键的使用在大多数硬件设计里相当频繁,而按键的干扰处理可以使用硬件消抖,也可使用软件消抖。这两种方法可根据总体设计需求而选择,以高效的方式处理所有任务。本文采用51单片机的其中一个定时器作为全局时钟来...

    向兵 杨述凯

    摘 要:随着电子技术的发展,单片机的应用在教学及科技开发中越来越普遍,而针对单片机的开发环境而言,大多采用C51语法进行设计。按键的使用在大多数硬件设计里相当频繁,而按键的干扰处理可以使用硬件消抖,也可使用软件消抖。这两种方法可根据总体设计需求而选择,以高效的方式处理所有任务。本文采用51单片机的其中一个定时器作为全局时钟来定位处理任务,以不影响、不打断其他正常工作的前提为标准,可大大提高处理器工作效率。

    关键词:单片机;按键;消抖;定时器

    一、软件消抖现状

    通常,我们会在程序中自定义一段延时程序命名为类似于delayms(unsigned int i)格式,然后在程序处理过程中判断按键状态达到要求后调用此函数来进行消抖。此方法在程序运行时,一旦按键状态符合,需要进行延时等待二次判断,任务较小的情况下能够达到预期要求,若处理器任務较多,使用delayms函数进行延时会极大降低程序处理效率,且总体效果不佳。本文介绍的消抖方式是利用单片机定时器记录全局时间,在每一次进入中断后时钟变量加1,在主要任务处理时循环判断按键状态变化时间,来达到类似于分时操作的效果。

    二、程序初始化步骤

    首先认为系统上电后按键状态为高电平1,定义一个位变量:bit key_last_state=1,用来存储程序运行过程中按键最后保持的状态。我们将按键接在单片机P2.0引脚上,用变量key_current_state来表示P2.0引脚的电平,故定义:sbit key_current_state,此变量是由按键按下或松开之后的真实状态变化。其次定义全局时钟变量,将每一次进入中断后总体时间变化量保存在其中,故有:unsigned int globle_time=0。本文中采用51单片机定时器0工作方式1产生1ms的时间间隔,即每1ms进入一次中断服务程序。最后,定义按键变化时保存的临时时间变量,故有:unsigned int key_last_time = 0。

    至此,程序进入主函数后,首先应设置好定时器的工作模式及其方式,并赋予初始值。随后配置好定时器0中断,启动定时器计时。

    三、按键状态识别及消抖

    六、小结

    本文采用单片机定时器作为时间基准,将全局时间保存在变量globle_time中,作为时间记录值,消抖过程中可分时进行其他任务的操作,这样,无需消耗多余的等待时间而降低程序效率。在消抖后进行当前按键状态判断时,可辨别出按键正常按下及松开两种情况,分别做相应的程序处理及外围控制。

    参考文献:

    [1] 乔之勇等.单片机应用系统设计项目化教程[M].北京:电子工业出版社.2014.9

    [2] 王静霞.单片机基础与应用[M].高等教育出版社.2016.3

    [3]赵勇等.单片机原理与接口技术[M].电子科技大学出版社.2016.12

    [4] 陈希球等.单片机应用.高等教育出版社[M].2017.4

    作者简介:

    向兵(1990.10~),男,汉,四川南充人,助教,硕士研究生,从事单片机原理与应用、电子产品分析与制作等课程研究及项目开发。

    杨述凯(1998.10~),男,汉,四川巴中人,绵阳职业技术学院信息工程系2017级,电子信息工程技术专业专科在读,擅长单片机开发、程序设计。

    课题项目:绵阳职业技术学院,校级精品在线开放课程-《电子产品分析与 制作》

    展开全文
  • STM32单片机按键消抖和FPGA按键消抖大全 按键去抖:由上图可以看出理想波形与实际波形之间是有区别的,实际波形在按下和释放的瞬间都有抖动的现象,抖动时间的长短和按键的机械特性有关,一般为5~10ms。通常我们手动...

    写在前面:在这里插入图片描述

    STM32单片机按键消抖和FPGA按键消抖大全

    按键去抖:由上图可以看出理想波形与实际波形之间是有区别的,实际波形在按下和释放的瞬间都有抖动的现象,抖动时间的长短和按键的机械特性有关,一般为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仿真,但还没有在实际的项目中验证。在整理准备这个博客的时候,我又想到了一个感觉是更巧妙的方案,具体是这样的:在第三个方案的基础上,因为按键输入有变化的第一时刻,输出就已经改变了,在这种情况下,我可以把计时的时长改为一个很小的值,该值只要比抖动中的最长高低电平变化时间长即可。但想想也没这个必要,且这个抖动的高低电平变化时长我也很难去给它界定一个值。
    在这里插入图片描述

    展开全文
  • 一、按键电路,二、按键消抖,三、硬件消抖,四、软件延时消抖
  • 51单片机按键消抖

    千次阅读 2014-12-16 14:44:23
    一般处理有两种方式:一种是硬件消抖,另一种是软件消抖。硬件消抖不仅会增加开发成本,而且有时不稳定。一般都会选择软件消抖。 因为单片机最重要的是测试状态,而不是测试过程。一般不会选择通过状态延时来消抖,...

    抖动是机械按键存在的现象,是必须要进行处理的。一般处理有两种方式:一种是硬件消抖,另一种是软件消抖。硬件消抖不仅会增加开发成本,而且有时不稳定。一般都会选择软件消抖。

      因为单片机最重要的是测试状态,而不是测试过程。一般不会选择通过状态延时来消抖,而是通过定时循环测试按键的状态来消抖.下面是针对51单片机的独立按键写的一个通过定时器来消抖的程序:

    #include<reg52.h>

    sbit  ADDR0 = P1^0;
    sbit  ADDR1 = P1^1;
    sbit  ADDR2 = P1^2;
    sbit  ADDR3 = P1^3;
    sbit  ENLED = P1^4;
    sbit  KEY4 = P2^7;
    //数码管的数字十六进制表示
    unsigned char code LedChar[]=
    {
     0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
     0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
    };


    bit KeySta = 1;


    void main()
    {
     bit backup = 1;
     unsigned char cnt = 0;

    //打开总中断
     EA = 1;
     ENLED = 0;
     ADDR3 = 1;
     ADDR2 = 0;
     ADDR1 = 0;

     ADDR0 = 0;

    //设置TMOD的状态

     TMOD = 0x01;

    //定时为2ms

     TH0 = 0xF8;
     TL0 = 0xCD;
     ET0 = 1;
     TR0 = 1;
     P2  = 0xF7;
     P0 = LedChar[cnt];


     while(1)
     {
      if(KeySta !=backup)
       {
        if(backup==0)
    {
    cnt++;
    if(cnt>=10)
    {
     cnt=0;
    }
    P0 = LedChar[cnt];
    }
    backup=KeySta;
        
       }
     }


    }


    void InterruptTimer0() interrupt 1
    {
      static unsigned char keybuf = 0xFF;
      TH0 = 0xF8;
      TL0 = 0xCD;
      keybuf = (keybuf<<1) |KEY4;
      if(keybuf == 0x00)
      {
       KeySta = 0;
      }
      else if(keybuf == 0xff)
      {
       KeySta = 1;
      }
      
    }
    展开全文
  • 单片机消抖程序

    2011-12-15 12:35:51
    单片机消抖程序,不是采用延时消抖,很好的利用了cpu的资源
  • 浅谈:在设计单片机按键输入的时候,进行按键消抖是防止按键输入被CPU误读多次的必要手段。 一、按键抖动 通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合...
  • 8.6 单片机按键消抖

    2019-02-18 17:29:06
    按键消抖可分为硬件消抖和软件消抖。 硬件消抖就是在按键上并联一个电容,如图 8-11 所示,利用电容的充放电特性来对抖动过程中产生的电压毛刺进行平滑处理,从而实现消抖。但实际应用中,这种方式的效果往往不是...
  • 按键的延时消抖是初学...软件消抖就相对较好些,新手即可操作,延时消抖,并非消抖的最终最优方法,但好在简单易懂,我们先认识消抖的方法和目的。 按键在按下和抬起时,都会出现短暂的抖动,称之为前沿抖动和后沿...
  • AVR单片机软件按钮消抖与确认

    千次阅读 2017-03-14 11:10:07
    第一次写博客,有不对或不好的地方欢迎指正。        按钮在按下与弹起的过程中会出现一定的抖动,这有时会对应用过程产生影响,所以我想了一个办法,用switch来 判断按钮的状态。 #include ...
  • } } } } } 3、使用定时器消抖 原理说明:1次按下+1次抬起构成一个按键动作,当同时检测到这两个动作时,才完成一次按键操作。按下时,将按键值存储为0;抬起时,将按键值存储为1。在前一次的按键值为0的...
  • 单片机按键扫描程序,不使用软件延时和定时器,方便移植,便于理解。
  • 单片机通过软件实现按键消抖

    千次阅读 2017-07-19 17:05:10
    通过上图可以看出理想波形...因此单片机在检测键盘是否按下时都要加上去抖动操作,有专用的去抖动电路,也有专门的去抖动芯片,但通常我们采用软件延时的方法就可以解决抖动问题。软件实现如下://软件 if (0 == K
  • 单片机按键消抖程序

    万次阅读 2014-09-15 12:27:33
    按键消抖可分为硬件消抖和软件消抖。 硬件消抖就是在按键上并联一个电容,如图 8-11 所示,利用电容的充放电特性来对抖动过程中产生的电压毛刺进行平滑处理,从而实现消抖。但实际应用中,这种方式的效果往往...
  • 单片机消抖方式

    千次阅读 2018-04-11 10:03:40
    单片机按键消抖方式详解通常按键所用的开关都是机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上就稳定的接通,在断开时也不会一下子彻底断开,而是在闭合和断开的瞬间...
  • 单片机之按键消抖

    千次阅读 2019-08-20 17:23:29
    却不明白真正操作起来会遇到的一系列问题,由于机械触点的弹性,一个按键开关在闭合后不会马上稳定接通,断开时也不会马上断开,如果不处理的话,会导致按键识别为多下,故我们就来研究一下按键消抖(针对的是K1 K2 ...
  • 开发板:普中A7开发板 核心板:51和STM32F103C8T6 ...因为其中一种按键消抖方法就是学自宋老师课程,需要详细查看的话可以看《手把手教你51单片机.pdf》文档。 我知道的软件消抖(轮询方式)有两种方式: 1、在...
  • 关于按键的硬件和软件消抖方法,很给力啊,按键消抖按键消抖按键消抖
  • 基本思想就是监测,延时,监测。。。,放进循环中可进行扫描式操作 /** * 函数功能: 读取按键KEY1的状态 * 输入参数:无 * 返 回 值: KEY_DOWN:按键被按下; * KEY_UP :按键没被按下 ... ...
  • #51单片机#按键消抖

    千次阅读 2020-02-18 21:16:32
    为什么要按键消抖? 为了保证操作效果 先看一段代码: #include <reg52.h> unsigned char code LedChar[10]={//数码管显示的数字0~9 0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90}; sbit KEY1 = P3^3...
  • 程序参考郭天祥老师的视频开发板普中科技 HC6800 V2.8 连接方式如图所示,按下按键K1,LED D1点亮,数码管DS1显示计数,说明抖动现象。/*************************.../* 连接方法:连接JP10(P0)与JP5(按钮接口) *
  • STM32单片机定时器做按键消抖

    千次阅读 2019-09-07 14:03:40
    STM32单片机定时器做按键消抖 原因:直接用软件延时做消抖会暂用整个资源,导致程序全部卡死等待延时,如下面程序: if(key_up&&(KEY0==0||KEY1==0||WK_UP==1)) { delay_ms(10);//去抖动 key_up=0; ...
  • 一种相对高效的按键消抖方法

    千次阅读 2017-09-29 20:43:20
    按键软件消抖自我接触单片机开始就已经存在这个问题了,网上的办法无非是延时消抖和定时轮询。对于写裸机的我来说这两种方法都不可避免的会有资源浪费掉,今天突然有了灵感,想到了一种相对高效的办法来解决消抖问题...
  • 此程序是用C语言编写的键盘接口消抖程序,用于单片机开发中的应用
  • 独立按键消抖单片机和FPGA中都是个不可避免的问题,首先,解释一下什么叫做按键抖动,如图,按键在按下和松开的那个瞬间存在大概20ms的机械抖动:    下面就是本篇的第一个重点 —— 什么时候需要按键消抖设计...
  • 按键软件消抖的原理

    千次阅读 2017-03-15 09:13:38
    在数字系统中,如果按键较多,常用软件方法消抖,即检测到按键闭合后执行一个5-10ms的延时程序,让闭合抖动消失后再一次检测按键的状态,如果仍保持闭合状态,则确认真正有按键按下。当检测到按键释放后,也要给5-...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,185
精华内容 474
关键字:

单片机软件消抖方法