本文隶属于AVR单片机教程系列。

我们已经学习了如何使用按键和拨动开关,不知你有没有好奇 button_down 和 switch_status 等函数是如何实现的。本篇教程带你一探究竟,让我们从按键的原理开始。

在原理图中,按键的符号如下图所示:

符号很简单,就是两个触点上方有一个动片,当按下时与两个触点接触。实际上按键内部的机械结构大体上就是这样,实现的功能是,没有按下时两端断路,按下时两端短路。

还有一种画法是这样的,即电键:

就按键内部的机械结构来说,第一种更加真实,但从电路角度来看,两者没什么区别。

但是我们的开发板上的按键有4个引脚,这是怎么回事呢?其实上面两个和下面两个分别是连通的,相当于只有两个:

拨动开关,相当于单刀双掷开关:

从开发板反面可以看到拨动开关有3个引脚。拨到上方时,上面两个导通;拨到下方时,下面两个导通。

然而,光知道这些原理还不够。任何IC,包括单片机,与外界打交道的唯一途径是引脚。单片机要知道按键状态,必须由我们搭建合适的电路,把按键和开关的信息转换为电平,连接到单片机上。

先说按键吧。按键按下时,两引脚之间导通,如果一端接在某一极(电源或地)上,另一端的电平就是确定的。然而,如果不连接其他器件,当没有按下时,这一端是浮空的,电压可能高也可能低,是无效的。而我们希望不按下时检测到的是另一种电平,因此我们可以在按键一端和另一极之间接一个电路:

按键接到地,电阻接到电源,这是一种很常见的接法,其中的电阻称为上拉电阻,取值几千欧到几十千欧都没啥问题。这个电阻可以在单片机内部,也可以是一个独立的元件。在我们的开发板上,4个按键(以及4个开关,后面会提到)是通过排阻上拉的。

为什么把按键接在地上用上拉,而不是接在正电源上用下拉?这是个很复杂的问题。尽管在布尔代数中0和1是完全对称的,但电子毕竟是电子而空穴是电子的缺失,由于某些很复杂的原因,导致上拉比下拉更加常见(得多)。事实上,AVR单片机的引脚可以配置独立的上拉电阻,但是没有下拉电阻可选(部分新型号中有)。

如果你没有受过上拉电阻思想的熏陶,对于拨动开关,你可能会想到这种接法:

这种接法不需要额外的元器件,听起来很妙。然而,虽然可行,这是一种不好的方法。万一两个触点之间短路了怎么办?整块开发板都短路保护了。尽管短路保护听起来安全,但即使保护起来,在解决短路问题之前,开发板还是不能用的。还有一种情况,我真的碰到过,就是单片机上两个相邻的读取开关的引脚因为焊接时的疏忽短路了,导致一旦这两个开关状态不一样就会触发短路保护。总之,这种接法不提倡。

与按键类似,在开关这边我们也可以用上拉电阻的接法:

利用这两种电路,我们成功地将按键不按下与按下分别转换成高电平和低电平,把开关位于下方和上方分别转换成低电平和高电平。那么,单片机怎么读取电平呢?库提供了 pin_read 函数,定义在 <ee1/pin.h> 中。我们还是通过一个例子来学习其使用方法:保持黄灯和蓝灯的状态分别与按键2和开关2的电平相同。

 #include <ee1/pin.h>
#include <ee1/led.h> #define BUTTON2 PIN_0
#define SWITCH2 PIN_1 int main()
{
led_init();
pin_mode(BUTTON2, INPUT);
pin_mode(SWITCH2, INPUT);
while ()
{
led_set(LED_YELLOW, pin_read(BUTTON2));
led_set(LED_BLUE , pin_read(SWITCH2));
}
}

异常简单的例子,不是吗?用 pin_read 读取引脚电平,再把LED设置为相应值。

当程序涉及端口操作时,为了能在硬件连接改变时方便地修改程序,建议用宏或常量建立设备与引脚之间的映射关系。这样在修改时就只有这个映射关系需要改动了,总比程序每一处调用都修改要方便得多。

值得一提的是,尽管今天的教程介绍了更底层的知识,但这仍不是我们能达到的最底层的地方。在几篇教程之后,你就可以抛弃库函数了。

作业:利用 pin_read 函数,结合之前教程中的知识,实现按键动作的检测并测试之。

AVR单片机教程——数字输入的更多相关文章

  1. AVR单片机教程——数字输出

    从上一篇教程中我们了解到,按键与开关的输入本质上就是数字信号的读取.这一篇教程要讲的是,控制LED的原理是数字信号的输出.数字IO是单片机编程之有别于桌面编程的各项内容中最简单.最基础的. 在讲数字信 ...

  2. AVR单片机教程——旋转编码器

    好久没写这个系列了.今天讲讲旋转编码器. 旋转编码器好像不是单片机玩家很常用的器件,但是我们的开发板上有,原因如下: 旋转编码器挺好用的.电位器能旋转的角度有限,旋转编码器可以无限圈旋转:旋转时不连续 ...

  3. AVR单片机教程——数码管

    先解答之前一个思考题:如果不把引脚配置为输出而写高电平,连接LED会怎样? 实验结果是,LED会亮,但相比于输出高电平的情况,亮度很低.这是为什么呢? 通过上一篇教程我们知道,引脚输入输出模式是由寄存 ...

  4. AVR单片机教程——拨动开关

    在按键的上方有4个拨动开关.开关与按键,在原理和使用方法上都是很类似的,但有不同的用途——按键按下后松开就会弹起,而开关可以保存其状态. <switch.h> 定义了与开关相关的函数.sw ...

  5. AVR单片机教程——按键动作

    上一篇教程中我们学习了如何读取按键状态.而按键的动作,比如单击,至少需要两个状态才能判定,长按.双击的判定更加复杂.今天我们来学习如何使用库函数判断按键单击,以及其实现原理. 我们要实现的是:当一个按 ...

  6. AVR单片机教程——按键状态

    好久没更新了,今天开始继续,争取日更. 今天我们来讲按键.开发板的右下角有4个按键,按下会有明显的“咔嗒”声.如何检测按键是否被按下呢?首先要把按键或直接或间接地连接到单片机上.与之前使用的4个LED ...

  7. AVR单片机教程——随机点亮LED

    之前我们做的闪烁LED和流水灯,灯效都是循环的.这次我们来尝试一些不一样的——每一次随机选择一个LED并点亮. 要实现随机的效果,我们要用C语言标准库中的相关设施: #define RAND_MAX ...

  8. AVR单片机教程——流水灯

    上次我们用 delay 函数与 while 循环实现了一个LED的闪烁.这一次我们把所有LED加入进来,让它们依次闪烁,形成流水灯的效果. 开发板上有4个LED,我们可以用不多的语句把循环体直接描述出 ...

  9. AVR单片机教程——闪烁LED

    上次我们把LED点亮了.你可能已经试过把 LED_RED 换成其他灯,也可能已经用 led_on() 把所有LED一起点亮了.但是LED点亮以后,程序就退出了,之后LED一直没有暗,直到没有供电.这一 ...

随机推荐

  1. 洛谷 P2512 [HAOI2008]糖果传递 题解

    每日一题 day47 打卡 Analysis 首先,最终每个小朋友的糖果数量可以计算出来,等于糖果总数除以n,用ave表示. 假设标号为i的小朋友开始有Ai颗糖果,Xi表示第i个小朋友给了第i-1个小 ...

  2. ssh2

    UserBiz public interface UserBiz { public List<User> list(User user); public int add(User user ...

  3. javascript根据两点和底角,计算等腰三角形的顶点坐标

    参考图: 代码如下: var x1 = 0; var y1 = 100; var x2 = -100; var y2 = 0; var angle = 30; var PI = Math.PI; // ...

  4. Sybase数据库连接配置

    简介 1984年,Mark B. Hiffman和Robert Epstern创建了Sybase公司,并在1987年推出了Sybase数据库产品.SYBASE主要有三种版本,一是UNIX操作系统下运行 ...

  5. Luogu3379 【模板】最近公共祖先(LCA)

    题面 题解 这里讲一种硬核做法. 首先\(\mathrm{dfs}\)整棵树,求出这棵树的欧拉序,然后\(\mathrm{LCA}\)问题就变成了\(\pm 1\mathrm{RMQ}\)问题. 考虑 ...

  6. office2010安装不了提示已经安装32位的了怎么办

    1.打开控制面板,查看是否有安装的程序没有拆卸,如果没有继续往下看,如果有直接拆卸掉,再进行下面的步骤. 2.首先打开注册列表.按下win+R键即可打开,输入regedit,也可以在开始菜单中搜索re ...

  7. java生成HMACSHA256的方法

    data要加密的数据,key密钥 public static String HMACSHA256(String data, String key) throws Exception { Mac sha ...

  8. [RoarCTF]Easy Calc

    目录 [RoarCTF]Easy Calc 知识点 1.http走私绕过WAF 2.php字符串解析特性绕过WAF 3.绕过过滤写shell [RoarCTF]Easy Calc 题目复现链接:htt ...

  9. [Beta]第一次 Scrum Meeting

    [Beta]第一次 Scrum Meeting 写在前面 会议时间 会议时长 会议地点 2019/5/5 22:00 30min 大运村公寓6F寝室 附Github仓库:WEDO 例会照片 工作情况总 ...

  10. 第06组 Beta冲刺(4/4)

    队名:福大帮 组长博客链接:https://www.cnblogs.com/mhq-mhq/p/11990575.html 作业博客 : https://edu.cnblogs.com/campus/ ...