查看: 13552|回复: 40

按键控制LED实验

[复制链接]
  • TA的每日心情
    奋斗
    2018-8-17 09:12
  • 签到天数: 47 天

    [LV.5]常住居民I

    发表于 2017-12-18 00:25 | 显示全部楼层 |阅读模式
    本文节选自《Arduino程序设计基础》


    我们要结合数字输入输出功能,制作一个可控制的LED。实现按住按键时,点亮LED,放开按键后,熄灭LED的效果。
    实验中我们将用到按键或者按键模块,常见的有2脚按键和4脚按键,其内部如图2-25所示。当按下按键时,就会接通按键两端,放开时,两端会再次断开。
    aa.jpg

    所需材料
    Arduino、面包板、LED一个、按键一个、220Ω电阻一个、10KΩ电阻一个

    连接示意图
    aaaaa.png

    原理图
    aaaaaa.png

    如上图所示,我们使用了两个电阻。LED的一端,我们使用了220Ω的电阻,按键一端,我们使用了10K的电阻,两个电阻的作用分别如下:

    ------------------------------------------------------------
    限流电阻
    一般LED的最大能承受的电流为25mA,如若直接将LED连接到电路中,当其点亮时,如果电流过大,很容易烧毁。如图2-24所示,我们在LED一端串联了一个电阻R2,这样做可以控制流过LED的电流,防止损坏LED。这个电阻我们称之为限流电阻。

    下拉电阻
    在Genuino101的2号引脚到GND之前,连接了一个阻值10K的电阻。如果没有该电阻,当未按下按键时,2号引脚会一直处于悬空 状态,此时使用digitalRead() 读取2号引脚状态,会得到一个不稳定的值(可能是高,也可能是低)。添加这个R1电阻到地就是为了稳定引脚的电平,当引脚悬空时,就会识别为低电平。而这种将某节点通过电阻接地的做法,叫做下拉,这个电阻叫做下拉电阻。
    ------------------------------------------------------------

    实现方法分析
    当未按下按键时,2号引脚检测到的输入电压为低电平;当按下按键时,会导通2号引脚和VCC,此时2号引脚检测到的输入电压为高电平。通过判断按键是否被按下,来控制LED的亮灭。

    示例程序
    你可以在 Arduino IDE菜单>文件>示例>02.Digital>Button 中找到以下程序:

    [C++] 纯文本查看 复制代码
    /*
      Button
    
    通过2号引脚连接的按键,控制13号引脚连接的LED
    
    备注:大多数Arduino的13号引脚上都连接了名为L的LED. 
    created 2005
    by DojoDave <[url=http://www.0j0.org]http://www.0j0.org[/url]>
    modified 30 Aug 2011
    by Tom Igoe
    
    This example code is in the public domain.
    
    [url=http://www.arduino.cc/en/Tutorial/Button]http://www.arduino.cc/en/Tutorial/Button[/url]
    */
    
    // 设置各引脚别名
    const int buttonPin = 2;     // 连接按键的引脚
    const int ledPin =  13;      // 连接LED的引脚
    
    // 变量定义
    int buttonState = 0;         // 存储按键状态的变量
    
    void setup() {
      // 初始化LED引脚为输出状态
      pinMode(ledPin, OUTPUT);      
      // 初始化按键引脚为输入状态
      pinMode(buttonPin, INPUT);     
    }
    
    void loop(){
      // 读取按键状态并存储在变量中
      buttonState = digitalRead(buttonPin);
    
      // 检查按键是否被按下
      // 如果按键按下,那buttonState应该为高电平
      if (buttonState == HIGH) {     
        // 点亮LED
        digitalWrite(ledPin, HIGH);  
      } 
      else {
        // 熄灭LED
        digitalWrite(ledPin, LOW); 
      }
    }


    编译并上传该程序后,按下按键,你会观察到LED会被点亮,松开按键,LED又会熄灭。


    项目进阶
    对于在以上项目,我们还可以做如下修改。

    连接示意图
    bb.png

    如上,我们去掉了原来电路中2号引脚连接的下拉电阻,并将按键的一端连接到GND;

    原理图
    bbb.png

    同时,我们需要将原程序setup() 部分中的
    [C++] 纯文本查看 复制代码
    pinMode(buttonPin,INPUT);

    修改为
    [C++] 纯文本查看 复制代码
    pinMode(buttonPin,INPUT_PULLUP);


    这样能使能该引脚上的内部上拉电阻,等效于在该引脚到VCC之间连接一个外部上拉电阻。

    -----------------------------------------------------
    上拉电阻
    同下拉电阻一样,可以稳定I/O口电平,不同的是电阻连接到VCC,将引脚稳定在高电位。这种电阻叫做上拉电阻。
    -----------------------------------------------------

    这里使用的是内部上拉电阻,也可以使用外部上拉电阻替代。稳定悬空引脚的电平所用电阻应该选择合适的阻值,例如10K。

    示例程序
    修改后的程序代码如下:

    [C++] 纯文本查看 复制代码
    /*
    按键控制LED - 1
    [url=http://www.arduino.cn/]http://www.arduino.cn/[/url]
    */
    
    int buttonPin = 2;
    int ledPin = 13;
    int buttonState = 0; 
    
    void setup() 
    {
      // 初始化I/O口
      pinMode(buttonPin,INPUT_PULLUP);
      pinMode(ledPin,OUTPUT);
    }
    
    void loop() 
    {
      buttonState = digitalRead(buttonPin);
      // 按住按键时,点亮LED;放开按键后,熄灭LED。
      if(buttonState==HIGH)
      {
        digitalWrite(ledPin,LOW);
      }
      else
      {
        digitalWrite(ledPin,HIGH);
      }
    }



    接下来我们要对控制程序做一个升级,完成一个新的控制效果。按一下按键,点亮LED;再按一下按键,熄灭LED。

    程序代码如下:

    [C++] 纯文本查看 复制代码
    /*
    按键控制LED - 2
    [url=http://www.arduino.cn/]http://www.arduino.cn/[/url]
    */
    
    int buttonPin = 2;
    int ledPin = 13;
    boolean ledState=false;  // 记录LED状态
    boolean buttonState=true;  // 记录按键状态
    
    void setup() 
    {
    // 初始化I/O口
      pinMode(buttonPin, INPUT_PULLUP);
      pinMode(ledPin,OUTPUT);
    }
    
    void loop() 
    {
    // 等待按键按下
    while(digitalRead(buttonPin)==HIGH){}
    
      // 当按键按下时,点亮或熄灭LED
      if(ledState==true)
      {
        digitalWrite(ledPin,LOW);
        ledState=!ledState;
      }
      else
      {
        digitalWrite(ledPin,HIGH);
        ledState=!ledState;
      }
      delay(500);
    }



    编译并上传该程序后,每按一下按键,LED状态都会改变。以上程序中,使用了
    [C++] 纯文本查看 复制代码
    while(digitalRead(buttonPin)==HIGH){}


    因为在初始化时,我们已经将buttonPin引脚设为了输入上拉状态。如果没有按下按键,使用digitalRead(buttonPin) 读出的值始终为高电平,这个循环也将一直运行;当你按下按键后,digitalRead(buttonPin) 读出了低电平,while循环的判断条件为假,程序会退出这个循环,并开始运行此后的语句。这样我们就实现了一个等待用户按下按键的效果。

    程序末尾有一个delay(500) 的延时,它在这里是极其重要的。可以尝试删去这个延时操作,再上传程序到Arduino。你会发现按键经常出现控制失灵的情况。这是因为程序运行的非常快,没有了延时操作,你按下按键到放开按键的间隔时间虽然极短,但loop中的语句可能已经运行了很多次,很难确定你放开按键时正在运行的loop() 循环是点亮还是熄灭LED。正是这样的原因,程序变得不那么好用了。
    上面程序中,我们使用延时操作来使两次按键间产生一定的间隔时间,在间隔时间内Arduino会忽略按键按下情况,从而达到区分两次按键的目的。



    如果以上内容对你有帮助,你可以通过打赏支持作者

    1人打赏

  • TA的每日心情
    开心
    2018-9-4 15:16
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2018-9-4 11:23 | 显示全部楼层
    刚开始不明白 上拉电阻 下拉电阻,细细咀嚼一下,懂了,为了稳定引脚电平状态,不能让引脚处在悬空状态,所以需要接地或者接入高电平,但是又不能直接连,因为这样电路就短接了,所以接入一个大电阻
  • TA的每日心情
    开心
    2018-4-3 11:56
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    发表于 2018-3-15 13:35 | 显示全部楼层
    我试验成功了,虽然里面的原理我还是不太懂
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2018-4-16 18:24
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2018-4-16 22:17 | 显示全部楼层
    很齐全的算法

    该用户从未签到

    发表于 2018-4-20 14:38 | 显示全部楼层
    代码中的
    ledState=!ledState
    起什么作用?
    如果不用这个有什么影响吗?
    纯小白!

    点评

    取反,如果不懂,请看C语言逻辑运算  详情 回复 发表于 2018-4-20 19:58
  • TA的每日心情
    奋斗
    2018-8-17 09:12
  • 签到天数: 47 天

    [LV.5]常住居民I

     楼主| 发表于 2018-4-20 19:58 | 显示全部楼层
    love294710 发表于 2018-4-20 14:38
    代码中的
    ledState=!ledState
    起什么作用?

    取反,如果不懂,请看C语言逻辑运算
    如果以上内容对你有帮助,你可以通过打赏支持作者

    该用户从未签到

    发表于 2018-4-20 20:55 | 显示全部楼层
    love294710 发表于 2018-4-20 14:38
    代码中的
    ledState=!ledState
    起什么作用?

    谢谢解答
    您说这个我知道是取反
    只是不太明白这个ledstate=!ledstate取反在这里有什么意义呢  
    如果这样写有什么弊病吗?
    if(ledState==true)
      {
        digitalWrite(ledPin,LOW);
      }
      else
      {
        digitalWrite(ledPin,HIGH);
      }
      delay(500);
    }
  • TA的每日心情

    2018-5-5 01:52
  • 签到天数: 6 天

    [LV.2]偶尔看看I

    发表于 2018-4-20 23:09 | 显示全部楼层
    love294710 发表于 2018-4-20 20:55
    谢谢解答
    您说这个我知道是取反
    只是不太明白这个ledstate=!ledstate取反在这里有什么意义呢  

    第一次按下按键的时候,LED亮,以后不管你再怎么按按键,LED都亮,永久亮因为ledstate状态恒为false
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    Arduino IDE安装esp8266 SDK
    Arduino IDE安装esp8266 S
    使用Arduino IDE开发esp8266开发板 1.下载Arduino IDE 下载地址 2.打开Arduino IDE
    arduino SD卡识别不了
    arduino SD卡识别不了
    arduino版本为1.8.7 单片机是arduino uno 使用的程序为自带程序cardinf 连线开始弄错
    arduino sd卡读取后 后期数据处理的问题
    arduino sd卡读取后 后期
    测试内容:UNO板子+SD卡+时钟1302模块+自制传感器模块。实现采集到的数据储存到SD卡中
    求助!在使用Digispack Kickstarter做BadUSB时报错
    求助!在使用Digispack Ki
    如图 在编译时出现错误 [mw_shl_code=c,true]void setup() { Digispark.Keyboard vo
    arduino智能小车蓝牙控制系统
    arduino智能小车蓝牙控制
    蓝牙智能小车简介 智能小车主要可以分为 3 部分, 传感器部分、控制部分、执行部分。
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表