前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >原创|怎么用一个按键控制LED实现闪烁和亮灭

原创|怎么用一个按键控制LED实现闪烁和亮灭

作者头像
单片机技术宅
发布2020-03-17 10:10:50
13.3K0
发布2020-03-17 10:10:50
举报
文章被收录于专栏:初学单片机
今天说一个很简单的问题,但是对于初学单片机的朋友来说也许还是不会,今天我们就来说说这简单的问题。

具体问下如下:怎么用一个按键控制小灯,按一次小灯不停闪烁,再按一次灭掉。问题很简单(其实问题是在一个论坛上看到的),但是我看了好几楼的回复,都没有看到完整的答案。

下面我们来分析下这个问题:1个小灯,其实就是LED灯;需要按键控制它的闪烁和灭,这样还需要一个按键;控制LED闪烁需要单片机开实现(问题提问者主要是要单片机程序)。按照上面的分析,我们画出图1的电路图(单片机部分省略)。

图1

如图1所示,LED和R1组成了LED驱动电路,这里我们采用单片机拉电流的驱动方式,当单片机IO口(P1.0)输出高电平时,电流从单片机IO口输出,流过LED和电阻R1,最终流到电源地,从而LED发光。当单片机IO口(P1.0)输出低电平时,P1.0电平和电源地电平一样,没有电压差,就不会有电流流过LED,所以LED不会发光。也就是说只要我们通过程序控制单片机IO口P1.0口的电平就可以实现控制LED的亮灭,那我们控制IO的电平重复出现“高---低---高---低……”就可以实现LED闪烁了。今天的问题是用按键控制实现闪烁和灭。下面我就来说按键的事。

图1中R2和S1组成按键电路,R2为上拉电阻,S1为我们真正的控制按键。R2的作用是给单片机IO口(P1.1)提供一个确定的状态,假如没有R2这个电阻,那在上电的瞬间或者是外接电磁干扰过大的时候,P1.1的状态可以会出现在高低电平上的跳变,这是我们不希望出现的。还有一点,假如没有R2这个电阻,在按键没有按下的情况下,IO(P1.1)是悬空的,这样P1.1的电平是不确定的。所以这个上拉电阻还是很有必要的。接下来说按键S1,如图1所示,当按键按下后,IO(P1.1)电平会被拉低为低电平,因为当按键按下后,P1.1直接通过按键接到电源地。当按键没有没按下时,IO(P1.1)电平被电阻R2上拉到高电平。这样一来,按键S1按下时,IO(P1.1)为低电平,按键S1没被按下时,IO(P1.1)为高电平,我们就可以读取IO(P1.1)的电平状态来识别按键是否被按下,从而控制LED的亮灭或者是闪烁。

以上是电路原理,现在我们说说程序的原理。程序部分主要的难点在如何实现按键第一次按下去控制LED闪烁,第二次按下后LED熄灭。这里我们说到了按键第一次按下,第二次按下,这是我们人可以这样说,那我们程序怎么办呢,同样是要编程去记录按键按下的次数,当程序判断当前为为第一次按下按键,就去控制LED闪烁,程序判断当前为第二次按下按键后,就去执行LED灭的程序。这样就实现了题目里要实现的要求了。具体的程序怎么写,下面说。

现在我们开始写程序部分。首先说明两点。1、我们本文所写的程序是基于STC15W系列的51单片机的;2、我们所用的程序开发环境是keil 。以下为完整的程序,可以直接复制来用。

// 按键控制LED闪烁和灭

//单片机:STC15W408AS

//调试时间: 2017.2.22

//作者:单片机技术宅

代码语言:javascript
复制
 #include<reg52.h>
 #define uint unsigned int 
 #define uchar unsigned char
 unsigned char i=0;
void delay_ms(unsigned int x);           //ms延时函数
 sbitLED=P1^0;        //小灯
 sbitkey1=P1^1;       //按键
//************************
//主函数
//**************************
 main()
 {   
         while(1){                                                 //大循环
                    if(key1==0){
                     delay_ms(10);      //消除抖动
                     if(key1==0){
                                     while(!key1);       //等待按键释放
                          i++;                            //记录按键次数
                          if(i>1){i=0;}     
                     }
               }
                     if(i==1){                                              //识别按键次数
                          LED=1;
                            delay_ms(100);
                            LED=0;
                            delay_ms(100);                          
                     }
                     else {LED=0;}
    }
}       
 //************************
 //ms延时函数,报时用
 //参数:x,x为ms
 //?***********************
void delay_ms(unsigned int x){
         unsignedint a,b;
  for(a=0;a<x;a++){
     for(b=0;b<110;b++);
   }
}

在以上程序中,变量i就是我们之前分析里提到的记录按键次数的变量。这里只记录按键按下2次。默认i=0,程序执行while(1)中的第二个if语句后的else语句LED=0,小灯不亮;当按键按下1次后,i=1,在程序中while(1)中的第二个if语句执行LED亮灭亮灭,达到闪烁的效果;当按键第二次按下后,i=2,紧跟着后面有个if(i>1){i=0;} ,这样一来,i=2肯定是大于1,所以i被清零返回默认值0,程序又会执行while(1)中的第二个if语句后的else语句LED=0,小灯不亮;这样一来就题目要求的按键按一下,LED闪烁,按第二次熄灭,这样这样重复操作下去。

在以上的程序中还有一句:while(!key1); 本句是检测按键释放没有的,我们在做按键的自加,或记录一个按键多功能的时候,必须加上按键释放的检测,不然你按一次按键,程序可能识别出好多次。因为我们认为按下一次按键的时间差不多在20ms左右,而程序在这个时间段里执行了好多此了。所以按键次数记录时必须要等按键释放后才加1,识别为一次有效按下。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 单片机技术宅 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档