《Arduino实战》——2.2 获得控制权

本节书摘来异步社区《Arduino实战》一书中的第2章,第2.2节,作者:【美】Martin Evans ,Joshua Noble ,Jordan Hochenbaum,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.2 获得控制权

Arduino实战
现在你的程序已经开始工作了,伴随着LED一个接一个地点亮和熄灭,下面我们要添加一个按钮,来控制这电路了。这个按钮用来启动和停止LED序列的闪烁。

2.2.1 电路图

电路图如图2-7所示。你需要保留最初版本的电路,并再添加一个按钮(S1)和一个阻值为10 kΩ的电阻(R6)就可以了。

在你看懂了修改过的电路图之后,就可以把新的元件添加到面包板上了。

《Arduino实战》——2.2 获得控制权

2.2.2 连接

首先,将Arduino从USB电缆上断开,然后将按钮安装到面包板上,如图2-8所示。请注意如何将其跨接在面包板中间。电阻R6是一个下拉电阻,在按钮未被按下的时候,它能防止D2的输入浮空,而将D2的输入下拉到地(GND),也就是低电平。当按钮按下的时候,D2的输入会接到5 V,也就是高电平。

图2-9展示了在面包板上组装完成后的电路。Arduino的供电由连接在计算机上的USB电缆提供。

上拉电阻和下拉电阻

在包含按钮的电路中,上拉电阻和下拉电阻的使用是十分普遍的,它可以防止由电气噪声或干扰带来的错误信号。这个电阻将输入口的电平保持在与程序检测电位相反的电平上。一个上拉电阻将电平上拉到5 V,一个下拉电阻将电平下拉到地。
当你连接好按钮和增加的电阻后,就可以来处理一下代码这边的工作了。在这个程序里,我们要使用Arduino中一个专门的特性,称为中断。

《Arduino实战》——2.2 获得控制权

2.2.3 认识中断

Arduino的中断非常强大,它可以在任何时候打断程序流程的执行。中断就像你就要走进浴室时突然有人按门铃一样——你必须马上处理它。Arduino也是一样的,一旦中断信号发出,你的程序就要马上去处理它。

标准的Arduino可以使用最多两个中断,但在这个项目中,你只会用到一个。当按钮被按下时就会发生一个中断,第一次按下按钮会时LED序列停止闪烁,再按一次则会使其重新开始闪烁,以此类推。

2.2.4 通过按钮控制LED的程序

下列代码清单就是新版的程序。你可以在现有程序的基础上修改,也可以再新建一个程序。

代码清单2-2 开始-停止显示

《Arduino实战》——2.2 获得控制权

在代码的开头,你将变量state声明为volatileC:UsersAdministratorAppDataRoamingTencentUsers330842669QQWinTempRichOle2$@2VSST70VFGY$8EWIA0{7.png。用volatile关键字修饰一个变量,表示该变量可能在其出现的代码段以外被修改,volatile的主要用途之一就是用于中断处理,我们在这里遇到的就是这种情况。

标准的Arduino有两个中断:中断0绑定在2号数字引脚,中断1绑定在3号数字引脚。Arduino Mega还有4个额外的中断:中断2绑定在21号数字引脚,中断3绑定在20号数字引脚,中断4绑定在19号数字引脚,中断5绑定在18号数字引脚。

注意 函数attachInterrupt(interrupt, function, mode)有3个参数。第一个参数是中断号,可以设置为0或者1;第二个参数是中断调用的函数,必须是一个无参数无返回值的函数;第三个参数是产生中断的模式。中断模式可赋下列4种值:设置LOW时,中断在引脚电平为低时触发;设置为CHANGE时,中断在引脚电平改变时触发;设置为RISING时,中断在引脚电平从低电平变为高电平时触发;设置为FALLING时,中断在引脚电平从高电平变为低电平时触发。
在这个程序中,将中断的触发方式设为RISINGC:UsersAdministratorAppDataRoamingTencentUsers330842669QQWinTempRichOle[G)49Q0ZES093B)](8Y}TKV.png。在按下按钮时,会将相应引脚的电平从低电平切换到高电平,中断就会在这个时候被触发。这个程序的另外一个改变是,现在所有的LED会以一个很小的间隔一个接一个地点亮,当所有的LED都被点亮后,会有一个很小的停顿图像说明文字,之后再以一个很小的间隔一个接一个地熄灭。这个过程会不断重复。按下按钮会使这个过程停止,再按一次按钮会让它重新开始。

抖动消除

在中断服务程序,也就是ledOnOff()函数中,我们还添加了一些代码,用于处理机械按钮中存在的抖动(bounce)问题。当按钮被按下时,在它从断开状态转换到闭合状态的瞬间,其中机械部件的接触并不完美,而是会产生一系列被称为抖动的干扰信号,导致与之相连的引脚电位高低变化数次后才最终稳定。按钮通常需要10 ms~50 ms才能最终稳定,但当你观察到一些奇怪的结果并怀疑其是由于抖动造成的时,你也可以尝试将这个时间改得更长一些。
在这个程序中,对抗按钮抖动现象的方法是使用了一个叫做lastMillisC:UsersAdministratorAppDataRoamingTencentUsers330842669QQWinTempRichOlePVKKH{6R(0E%2_G%KQ]UCV7.png的静态变量。静态变量在多次调用函数之间会保留其数值。millis()函数会返回程序开始运行以来经过的毫秒数,每次调用中断服务程序时,都将millis()的返回值赋值给变量newMillis。将newMillis与lastMillis的数值进行比较C:UsersAdministratorAppDataRoamingTencentUsers330842669QQWinTempRichOleX`DSQSS(WC84LOP)THHG226.png,如果结果小于50 ms(处于抖动期),就什么也不做,然后回到主程序中继续循环。如果结果大于等于50 ms,说明已经在抖动期之外,意味着按钮真的被再次按下了。在这种情况下,在返回到主循环之前需要更新变量state并将newMillis的值赋给lastMillis。

警告 很多人认为中断是一个高级技巧,但只要你够仔细,应该可以毫无障碍地使用它。在中断服务程序中,让你的程序代码尽可能小巧,这将会避免你在程序的其他部分遇到预料之外的事情。另外一个警告就是,你不能在中断服务程序中使用delay函数。
接下来让我们一起来测试我们最新的程序吧。

2.2.5 烧写和测试

将Arduino通过USB电缆连接到你的计算机。确保你的程序已经被正确编译,然后将其写入到Arduino中。当程序烧写完成后,所有LED都处于熄灭状态,直到你按下按钮。尝试着多按几次按钮,观察LED序列如何开始和停止。

2.2.6 使用break语句

保留原来的电路不动,现在把一个break语句添加到你的程序中。break``指令用于跳出一个循环或者switch语句。你利用它停止LED序列并保持LED的点亮状态,直到再次按下按钮,所以如果你在已经点亮3个LED的时候按下按钮,这3个LED就会一直处于点亮状态,直到再次按下按钮,序列才会继续循环点亮。

下列代码清单给出了使用break语句的新版程序。

代码清单2-3 添加break语句

《Arduino实战》——2.2 获得控制权

当所有的LED都点亮后,你检查状态变量state,看按钮是否已经被按下C:UsersAdministratorAppDataRoamingTencentUsers330842669QQWinTempRichOle2$@2VSST70VFGY$8EWIA0{7.png。如果按钮已经被按下,就会执行break语句C:UsersAdministratorAppDataRoamingTencentUsers330842669QQWinTempRichOle[G)49Q0ZES093B)](8Y}TKV.png,使程序从循环中跳出。当按钮被再次按下的时候,序列重新开始循环。

下面要检查一下你的程序能否正常工作。

2.2.7 烧写和测试

确保你的程序已经正确地编译,然后烧写并测试它。当按下按钮时,闪烁的LED序列应该会暂停,再次按下按钮,序列应该重新开始循环。

是时候让你的项目进入到下一个阶段了。你要来制作一个反应测试仪。

上一篇:《Microduino实战》——2.2 兼容Arduino系列产品


下一篇:NR 标准体系架构介绍 |带你读《5G 无线系统设计与国际标准》之七