咱们已经学习了如何使用按键和拨动开关,不知你有没有好奇 button_down 和 switch_status 等函数是如何实现的。本篇教程带你一探究竟,让咱们从按键的原理开始。安全
在原理图中,按键的符号以下图所示:函数
符号很简单,就是两个触点上方有一个动片,当按下时与两个触点接触。实际上按键内部的机械结构大致上就是这样,实现的功能是,没有按下时两端断路,按下时两端短路。学习
还有一种画法是这样的,即电键:测试
就按键内部的机械结构来讲,第一种更加真实,但从电路角度来看,二者没什么区别。spa
可是咱们的开发板上的按键有4个引脚,这是怎么回事呢?其实上面两个和下面两个分别是连通的,至关于只有两个:3d
拨动开关,至关于单刀双掷开关:code
从开发板反面能够看到拨动开关有3个引脚。拨到上方时,上面两个导通;拨到下方时,下面两个导通。blog
然而,光知道这些原理还不够。任何IC,包括单片机,与外界打交道的惟一途径是引脚。单片机要知道按键状态,必须由咱们搭建合适的电路,把按键和开关的信息转换为电平,链接到单片机上。教程
先说按键吧。按键按下时,两引脚之间导通,若是一端接在某一极(电源或地)上,另外一端的电平就是肯定的。然而,若是不链接其余器件,当没有按下时,这一端是浮空的,电压可能高也可能低,是无效的。而咱们但愿不按下时检测到的是另外一种电平,所以咱们能够在按键一端和另外一极之间接一个电路:开发
按键接到地,电阻接到电源,这是一种很常见的接法,其中的电阻称为上拉电阻,取值几千欧到几十千欧都没啥问题。这个电阻能够在单片机内部,也能够是一个独立的元件。在咱们的开发板上,4个按键(以及4个开关,后面会提到)是经过排阻上拉的。
为何把按键接在地上用上拉,而不是接在正电源上用下拉?这是个很复杂的问题。尽管在布尔代数中0和1是彻底对称的,但电子毕竟是电子而空穴是电子的缺失,因为某些很复杂的缘由,致使上拉比下拉更加常见(得多)。事实上,AVR单片机的引脚能够配置独立的上拉电阻,可是没有下拉电阻可选(部分新型号中有)。
若是你没有受过上拉电阻思想的熏陶,对于拨动开关,你可能会想到这种接法:
这种接法不须要额外的元器件,听起来很妙。然而,虽然可行,这是一种很差的方法。万一两个触点之间短路了怎么办?整块开发板都短路保护了。尽管短路保护听起来安全,但即便保护起来,在解决短路问题以前,开发板仍是不能用的。还有一种状况,我真的碰到过,就是单片机上两个相邻的读取开关的引脚由于焊接时的疏忽短路了,致使一旦这两个开关状态不同就会触发短路保护。总之,这种接法不提倡。
与按键相似,在开关这边咱们也能够用上拉电阻的接法:
利用这两种电路,咱们成功地将按键不按下与按下分别转换成高电平和低电平,把开关位于下方和上方分别转换成低电平和高电平。那么,单片机怎么读取电平呢?库提供了 pin_read 函数,定义在 <ee1/pin.h> 中。咱们仍是经过一个例子来学习其使用方法:保持黄灯和蓝灯的状态分别与按键2和开关2的电平相同。
1 #include <ee1/pin.h> 2 #include <ee1/led.h> 3 4 #define BUTTON2 PIN_0 5 #define SWITCH2 PIN_1 6 7 int main() 8 { 9 led_init(); 10 pin_mode(BUTTON2, INPUT); 11 pin_mode(SWITCH2, INPUT); 12 while (1) 13 { 14 led_set(LED_YELLOW, pin_read(BUTTON2)); 15 led_set(LED_BLUE , pin_read(SWITCH2)); 16 } 17 }
异常简单的例子,不是吗?用 pin_read 读取引脚电平,再把LED设置为相应值。
当程序涉及端口操做时,为了能在硬件链接改变时方便地修改程序,建议用宏或常量创建设备与引脚之间的映射关系。这样在修改时就只有这个映射关系须要改动了,总比程序每一处调用都修改要方便得多。
值得一提的是,尽管今天的教程介绍了更底层的知识,但这仍不是咱们能达到的最底层的地方。在几篇教程以后,你就能够抛弃库函数了。
做业:利用 pin_read 函数,结合以前教程中的知识,实现按键动做的检测并测试之。