产品
有人云 — 物联网云平台 零编程,组态拖拽即可实现远程监控。同时支持私有部署,拥有属于自己的软硬件一体化方案
200
+
私有云项目
数据本地化
业务个性化
10
+
万 公有云注册用户
80%公有云功能免费
付费VIP享自定义品牌服务
有人云官网
有人智造 — ODM/EMS 依托自动化、智能化、柔性化、透明化的智能工厂,
提供代研、代料、代工一站式OEM/ODM服务
有人智造官网
有人智能 — 解决方案 打包提供云、管、边、端整体解决方案
从问题诊断、方案设计,到实施落地、系统运维
有人智能官网
新闻资讯
AVR单片机利用按键控制发光二极管的亮灭 IO实验
2010-11-28


2.1 利用按键控制发光二极管的亮灭
2.1.1 实例功能
在“点亮发光二极管”和“让发光二极管动起来”这两个例子中,都是通过单片机程序来控制发光二极管的亮灭。如果想要控制发光二极管的亮灭,只有通过打开或者关闭电源来实现控制。那么怎样实现人工参与控制呢?
在有些应用场合,需要单片机对人工的开关信号作出相应的响应和处理,通过控制电源的通断会影响到单片机系统中的其他功能,所以通过控制电源的方法并不明智。能不能通过按动一个按键来实现发光二极管的亮灭呢?
当然可以,前面已经讲过,AVR单片机的I/O口都是双向的,也就是既能当作输出控制端口,也能当作输入检测端口。既然我们可以通过控制端口输出不同的高低电平使发光二极管实现点亮和熄灭;那么为什么不能通过监测端口输入电平的状态来进行相应的处理呢。
在本例中,通过介绍利用按键开关控制发光二极管的亮灭来了解AVR单片机的端口检测外部信号的功能和方法。
本例中有3个功能模块,描述如下:
● 单片机系统:检测外界的按键开关信号,根据按键的开关状态控制发光二极管的亮灭状态。
● 外围电路:首先是产生信号的按键电路,包括对按键去抖动电路的介绍;然后是发光二极管的控制电路。
● 软件程序:通过读取AVR单片机相应端口的状态,编写相应的程序控制发光二极管的亮灭。
本例的目的在于希望读者完成本例后,能完成相关电路的设计和相应程序的编写,从而掌握以下知识点:
◆ 了解AVR单片机端口输入功能,掌握使用AVR单片机端口输入功能检测外部信号的原理。
◆ 熟悉单片机端口输入输出功能的综合使用。
◆ 掌握AVR单片机按键的硬件去抖动的电路设计和原理。
◆ 掌握AVR单片机端口输入输出程序的编写。
◆ 掌握AVR单片机按键软件去抖动功能的实现。

2.1.2  器件和原理
本例主要介绍AVR单片机外围电路中按键去抖电路的设计,分别介绍相应的软件和硬件解决方案。然后利用C语言编写通过按键控制发光二极管亮灭状态的程序。
1、按键的去抖动电路
(1)按键的响应过程
我们日常所说的按键,实际上是一个机械开关,本实例所用的按键外观如图2.1.1所示。理想的按键的闭合和断开时,接触点的电压应该立即变高或者变低,但 是由于机械触点的弹性以及按键按动时电压突变等原因,在触点闭合或断开的瞬间会出现电压抖动现象,如图2.1.2所示。在发生抖动的时间一般在 5-10ms。
一次按键处理过程如下:当按键按下之后,相应的按键接触点的电压以高低电平的方式输入到单片机的I/O口。按键的闭合与断开是有一定时间的,一般为 0.1-1S。而AVR单片机的机器周期一般为1us甚至更短,在0.1-1S的时间段内,程序会检测很多次按键的输入电平,这样单片机可能会认为按键被 按下了多次,从而出现误判。

图2.1.1 按键开关             图2.1.2  按键闭合断开时的电压波动示意图
(2)按键去抖动的方法和原理
为了去除按键的抖动,保证单片机对按键的一次输入只响应一次,可以采用硬件和软件两种方法:硬件电路去抖动是在外围电路中加入去抖动电路(如R-S触发 器);软件去抖动是在程序中加入延时程序以跳过抖动时间,等待信号稳定后再次判断按键的输入电平,如果信号电平保持不变,则可以确认一次按键按下。
●硬件去抖动电路的原理
用R-S触发器形成去抖电路是单片机外围电路设计中常用的方法,这种方法可以减少单片机软件对按键动作的延时和计算。
先来了解一下R-S触发器的基本工作原理和工作特点。R-S触发器的基本构成如图2.1.3所示,这个电路有两个与非门交叉耦合而成,/S、/R是信号输入端,低电平有效。Q和/Q既表示触发器状态,又是触发器的输出端。

图2.1.3  R-S触发器的基本原理
在启动过程中,/S端一旦下降到开门电平,Q端电平就会上升,反馈到门B的输入端,此时门B在/R的低电平作用下处于导通状态,/Q输出高电平反馈到A的 输入端,如果这时/S端电压有一个高的跳动,则A门截止,Q段输出低电平,这个低电平反馈到A的输入端,使A门导通,Q端电平为高,这样就保证了Q端电平 的稳定,从而消除按键的抖动。
典型的硬件去抖动电路如图2.1.4,74LS02按键输出端口通过/Q端接入单片机的I/O口,74LS02构成一个R-S触发器电路实现按键的消抖。
●软件消抖的原理和实现
软件消抖的基本原理是在软件中对按键进行两次检测确认,记载第一次检测到按键按下后,间隔10ms左右再次检测按键是否按下,只有在两次都检测到按键按下时才最终确认有键按下,这样就避开了按键的抖动时间,从而消除了抖动的影响。
图2.1.4 74LS02实现的硬件消抖电路
在按键接口软件的设计中,除了要考虑按键消抖外,一般还要判别按键的释放,只有检测到按键释放后,才能确定为一次完整的按键动作。
通用的案件检测程序如下:

[code="c"]
Keyscan()
{
if(!key)       //判断按键是否按下,key=0表示按键按下
{
delayms(20);  //延时20ms。避开按键抖动时间
if(!key)     //再次判断按键是否按下,
{
…     //按键按下的处理程序
}
}
While(!key);    //判断按键是否放开,key=1表示按键释放,退出按键处理函数
}
[/code]

2.1.3 电路
本例中的电路如图2.1.5和2.1.6所示。
1、电路原理
图2.1.5是按键检测电路,两个按键分别连接到单片机的PD6、PD7管脚,AVR单片机在程序里把PD6、PD7设置为带上拉的端口,这样按键没有按 下时,PD6、PD7处于高电平状态,当按键按下时PD6、PD7被连接到地,电平状态变为低电平,程序中检测到PD6、PD7的电平为低电平时,就可以 认为按键被按下了。
图2.1.6为LED显示电路,当按键K3被按下时,D1、D3、D5、D7点亮,D2、D4、D6、D8熄灭。当按键K4被按下时,D1、D3、D5、D7熄灭,D2、D4、D6、D8点亮。
2、元器件选择
在这里列出和本例相关的、关键部分的器件名称及其在电路中的作用。
● ATmega16:单片机,检测按键按下情况并控制发光二极管的亮灭。
● D1-D8:发光二极管,指示按键状态。
● RP1:阻值为330Ω的排阻,限流电阻。
● K3、K4:按键,当按键按下时,与按键连接的单片机端口的电平发生变化。

3、管脚连接
在这里列出和本例相关的、关键部分的单片机端口与外围电路的连接。
● PB0-PB7:连接8个发光二极管LED1-LED8,控制发光二极管的亮灭。
● PD6、PD7:连接按键K3、K4,检测两个按键的状态。
2.1.4 程序设计
1、程序功能
● 按键软件消抖
本例中采用软件消抖的方法,在程序中加入软件延时,去除按键的抖动。
● 按键检测
通过将单片机的PD6、PD7口设置为输入状态,同时使能这两个口的内部上拉电阻(因为这两个口在按键没有按下时处于悬空状态,易受外界干扰,所以必须将其内部上来电阻使能,使其平时处于高电平状态),检测按键是否按下。

  1. LED的亮灭控制

     通过将单片机的PB0-PB7口设置为输出状态,根据K3、K4两个按键的按下情况,控制不同的发光二极管点亮或熄灭。
● AVR单片机端口输入状态的读取
AVR单片机端口配备有3个寄存器,分别是方向控制寄存器DDRx,数据寄存器PORTx,和输入引脚寄存器PINx(x=A\B\C\D)。当I/O工作在输入方式,要读取外部引脚上的电平时,应读取PINxn的值,而不是PORTxn的值。
2、主要变量和函数说明

3、使用WINAVR开发环境,makefile文件同前面的例子,直接复制到本实例程序的文件夹中即可。
4、程序代码
[code="c"] #include <avr/io.h>    
#include <util/delay.h>

int main(void)         
{           
PORTB = 0X00;      //输出低,LED全部熄灭
DDRB = 0Xff;      //PB端口置为输出
PORTD = 0Xc0;     //一定要使能上拉电阻,否则会有干扰
DDRD = 0X3F;      //K3、K4按键(PD6、PD7)设置为输入端口

while(1)
{
if(!(PIND & (1 <<  PD6)))     //判断按键是否按下
{
_delay_ms(20);    //判断按键按下,延时一会再判断是否按下, 以消除干扰
if(!(PIND & (1 <<  PD6)))    // 按键真正按下后,进行相应处理
{
PORTB = 0X55;              //          按键按下,灯亮   
while(!(PIND & (1 <<  PD6)));//等待按键释放
//PORTB = 0X55;  //  把这句话从上面移到这里,按键释放后,灯才点亮
}
}

if(!(PIND & (1 <<  PD7)))     //判断按键是否按下
{
_delay_ms(20);     //判断按键按下,延时一会再判断是否按下, 以消除干扰
if(!(PIND & (1 <<  PD7)))    // 按键真正按下后,进行相应处理
{
PORTB = 0Xaa;                  //
while(!(PIND & (1 <<  PD7)));  //
//PORTB = 0Xaa;                        //
}
}
}
}

[/code]
工作日每天: 14:00~17:00
抖音、天猫 "有人旗舰店"

关注有人微信公众号
了解更多信息