极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 20230|回复: 11

《博哥Arduino学习笔记系列》- 第四课 经典按键实验

[复制链接]
发表于 2016-12-3 23:51:45 | 显示全部楼层 |阅读模式
本帖最后由 单片机菜鸟 于 2016-12-3 23:55 编辑

一、前言

     回顾一下第三课

     《博哥Arduino学习笔记系列》- 第三课 经典LED
          http://www.geek-workshop.com/thread-27948-1-1.html  (出处: 极客工坊)

      我们讲了数字IO口介绍以及做了流水灯演示(主要用到IO口的输出功能),这节课我们讲解一下IO口的输入功能,说到输入功能,最经典的例子莫过于按键实验。废话少说,赶紧上车。

二、实验介绍

       注意:这课实验是基于第三课实验材料进行的。

       使用了大按键模块:
      

       这个模块,低电平有效。

      

       1)实验1  当按住按键时点亮LED,当放开按键后熄灭LED
       2)实验2  当点击一次按键时点亮LED,当再次点击一次按键时熄灭LED(就跟家里灯一样)


三、实验过程

        我的实验尽量都在代码中解释,毕竟代码才是最直观的展示

        1)实验1 当按住按键时点亮LED,当放开按键后熄灭LED
            代码如下:
  1. /**
  2. * @Desc 按键灯(当按住按键时点亮LED,当放开按键后熄灭LED)
  3. * @author 单片机菜鸟
  4. * @Date  2016/12/3
  5. * 注意:LED的一端接到5V,另外一端接到输出引脚,低电平亮
  6. *       按键是高电平有效
  7. */

  8. #define LED  2
  9. #define KEY  10

  10. int buttonState = HIGH;//记录当前按键状态

  11. void setup() {
  12.   //配置2号引脚作为输出引脚
  13.    pinMode(LED,OUTPUT);
  14.    digitalWrite(LED,HIGH);//灭掉LED
  15.    //配置10号引脚为输入引脚 如果是自己连接普通按键 pinMode(KEY,INPUT_PULLUP),弱上拉
  16.    pinMode(KEY,INPUT);
  17. }

  18. void loop() {

  19.   buttonState = digitalRead(KEY);//读取当前按键状态
  20.   if(buttonState == HIGH){
  21.     //按键按下
  22.     digitalWrite(LED,LOW);//点亮LED
  23.   }else{
  24.     //按键放开
  25.     digitalWrite(LED,HIGH);//熄灭LED
  26.   }
  27.   
  28. }
复制代码


          2)实验2  当点击一次按键时点亮LED,当再次点击一次按键时熄灭LED(就跟家里灯一样)
           代码如下:
  1. /**
  2. * @Desc 按键灯(当点击一次按键时点亮LED,当再次点击一次按键时熄灭LED)
  3. * @author 单片机菜鸟
  4. * @Date  2016/12/3
  5. * 注意:LED的一端接到5V,另外一端接到输出引脚,低电平亮
  6. *       按键是高电平有效
  7. */

  8. #define LED  2
  9. #define KEY  10

  10. int buttonState = HIGH;//记录当前按键状态
  11. int flag = HIGH;//默认当前灭灯

  12. void setup() {
  13.   //配置2号引脚作为输出引脚
  14.    pinMode(LED,OUTPUT);
  15.    digitalWrite(LED,flag);//灭掉LED
  16.    //配置10号引脚为输入引脚 如果是自己连接普通按键 pinMode(KEY,INPUT_PULLUP),弱上拉
  17.    pinMode(KEY,INPUT);
  18. }

  19. void loop() {
  20.   buttonState = digitalRead(KEY);//读取当前按键状态
  21.   if(buttonState == HIGH){
  22.     //按键按下
  23.     delay(40);//做一个防抖动延时(确保真是按下了按键而不是错误)
  24.     buttonState = digitalRead(KEY);//再一次读取按键状态
  25.     if(buttonState==HIGH){
  26.       //再次确认是否真的按下了按键,是的话就置反当前灯的状态
  27.       flag = !flag;
  28.       digitalWrite(LED,flag);
  29.     }
  30.   }
  31. }
复制代码


          我的按键模块的实验结果是:偶尔可以,偶尔又不可以,证明只是简单防抖动肯定是不行的。后面经过查资料用以下防抖动方法:
  1. /**
  2. * @Desc 按键灯(当点击一次按键时点亮LED,当再次点击一次按键时熄灭LED)
  3. * @author 单片机菜鸟
  4. * @Date  2016/12/3
  5. * 注意:LED的一端接到5V,另外一端接到输出引脚,低电平亮
  6. *       按键是高电平有效
  7. */

  8. #define LED  2
  9. #define KEY  10

  10. int flag = HIGH;//默认当前灭灯

  11. // 定义记录按键当前状态的变量
  12. int state_btn;
  13. // 定义记录按键最近一次状态变化的变量,并初始化状态为LOW。
  14. int lastButtonState = LOW;
  15. // 定义记录最近一次抖动的时间变量,并初始化时间为0毫秒。
  16. long lastDebounceTime = 0;
  17. // 定义延迟抖动的时间变量
  18. long debouncdDelay = 60;

  19. void setup() {
  20.   //配置2号引脚作为输出引脚
  21.    pinMode(LED,OUTPUT);
  22.    digitalWrite(LED,flag);//灭掉LED
  23.    //配置10号引脚为输入引脚 如果是自己连接普通按键 pinMode(KEY,INPUT_PULLUP),弱上拉
  24.    pinMode(KEY,INPUT);
  25. }

  26. void loop() {
  27.   int buttonState = digitalRead(KEY);//读取当前按键状态

  28.   if(buttonState != lastButtonState){
  29.      //如果按键发生了变化  则重新设置最近一次抖动的时间
  30.      //方法millis()可以获取当前时间,单位统一为毫秒。
  31.      lastDebounceTime = millis();  
  32.   }
  33.   
  34.   // 判断按键按下状态时间间隔是否大于延迟抖动的时间长度。
  35.   if(millis()-lastDebounceTime>debouncdDelay){
  36.     // 判断当前的按键状态是否和之前有所变化
  37.     if(buttonState != state_btn){
  38.        // 如果发生了变化,
  39.        // 则更新按键状态变量。
  40.        state_btn = buttonState;
  41.        if(state_btn == HIGH){
  42.         //再次确认是否真的按下了按键,是的话就置反当前灯的状态
  43.          flag = !flag;
  44.          digitalWrite(LED,flag);
  45.        }
  46.     }
  47.   }
  48.   // 更新按键最近一次状态变化的变量
  49.      lastButtonState = buttonState;
  50. }
复制代码


    这里的防抖算法的思路是:需要记录一个最近状态 lastButtonState (每读一次引脚状态就记录一次),然后在抖动间隔内(60ms)判断最新状态,只要间隔内状态改变,就不断更新抖动时间的起始点(也就是 lastDebounceTime = millis(); ),直到防抖动满足 millis()-lastDebounceTime>debouncdDelay。之后再判断一下当前状态和之前状态是否改变 buttonState != state_btn (以防用户按太久了)

四、总结
       这节课我们主要学习数字IO口的输入功能,整体上还算简单,主要是注意按键防抖动。下一节我们计划将模拟IO


博哥学习笔记系列:

《博哥Arduino学习笔记系列》- 第一课 初识Arduino
        http://www.geek-workshop.com/thread-27936-1-1.html

《博哥Arduino学习笔记系列》- 第二课 Arduino语言基础
        http://www.geek-workshop.com/thread-27938-1-1.html

《博哥Arduino学习笔记系列》- 第三课 经典LED
        http://www.geek-workshop.com/thread-27948-1-1.html

《博哥Arduino学习笔记系列》- 第四课 经典按键实验
        http://www.geek-workshop.com/thread-27958-1-1.html

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2016-12-4 07:52:34 | 显示全部楼层
写的很详细!顶一个!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-12-4 09:06:10 | 显示全部楼层
antbot 发表于 2016-12-4 07:52
写的很详细!顶一个!

互相学习   刚入门不久
回复 支持 反对

使用道具 举报

发表于 2016-12-5 10:16:02 | 显示全部楼层
顶,新手刚好需要            
回复 支持 反对

使用道具 举报

发表于 2016-12-6 22:24:30 | 显示全部楼层
挺好的,代码也很全
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-12-6 22:36:40 | 显示全部楼层
Herman 发表于 2016-12-5 10:16
顶,新手刚好需要

谢谢哈哈哈哈哈哈
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-12-6 22:36:53 | 显示全部楼层
coolcxm 发表于 2016-12-6 22:24
挺好的,代码也很全

谢谢哈哈哈哈哈哈
回复 支持 反对

使用道具 举报

发表于 2017-5-11 10:12:52 | 显示全部楼层
好巧妙的防抖方法,学习啦谢谢楼主分享
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-12 16:02:19 | 显示全部楼层
BisonRumble 发表于 2017-5-11 10:12
好巧妙的防抖方法,学习啦谢谢楼主分享

谢谢哈哈哈哈哈
回复 支持 反对

使用道具 举报

发表于 2017-7-17 18:24:50 | 显示全部楼层
if(digitalRead(s1)==1)
  {
     delay(60);//消去按下抖动
     if(digitalRead(s1)==1)
     {
        k++;
        while(digitalRead(s1));//消去松手抖动
       }
    }
/*************************这个按键消抖要好理解很多,而且程序简*****************************/
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-7-18 10:24:59 | 显示全部楼层
bgy 发表于 2017-7-17 18:24
if(digitalRead(s1)==1)
  {
     delay(60);//消去按下抖动

有用过 但是有时还是有问题
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-18 18:20 , Processed in 0.057453 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表