前文说了输入的方法和如何检测,包括我们进行了自锁和非自锁的实验,两种按键都是可以完成信号输入的,区别就在于信号在程序中的处理方法不同,进而输出效果也不大一致。
今天就再说说,多点输入的操作,如果说单点输入是明白如何检测信号,那么多点输入就是对信号检测的熟练掌握。我们先说下练习的规则,本次采用P1和P2端口,P1采用总线方式,P2采用单点检测方式。对输入的数据我们均采用自锁方式处理。处理后用于P3端口的控制LED小灯点亮。
首先我们把代码先写好。
我选取了两个io作为单独的开关,用来测试单独的开关状态读取。分别是P20、P21,然后对P1的所有端口都进行了状态读取,类似于总线方式的读取,跟我们之前的总线方式的输出有相似之处,一个是把数据输出出去,一个是把数据读取进来,两个都是把8位的端口数据放在了一个字节中。
接着在主函数中,首先是对需要使用的端口进行置1,这个是常规操作,因为我们之前说过,如果不置1,就无法准确的读取外部输入的信号状态。所以要读取,就内部先置1.
接着是循环体,这个主要是为了让程序不停的循环,以保证成能正常运行,防止意外跑飞。
循环体中,显示对P1进行了读取判断,我给的是一个固定的值,0xf7,写成二进制就是11110111,可以看出当P1.3,也就是P1的第四个引脚处于低电位时,LED就会输出0x08,二进制就是00001000,相当于通过点亮LED来指示哪个按键按下。
然后是开关的判断,通过判断两个单独的开关状态,然后分别输出不同的动作。
由于都是对P3口进行的操作,所以最后一个按下的开关,决定了P3端口的最终状态。
根据程序,我来设计出仿真电路。
左侧是P1端口,接了8个按键开关,右侧上端是两个单独开关接在P2上,下方是八个小灯,接在了P3口上,仿真电路中没有绘制出最小系统所需要的晶振和复位电路,记得实际电路这些是不能省去的,不然无法运行,别说运行了,程序都下不进去的。
接下来简单测试下功能,首先依次按下P1.0到P1.7,我们会发现,只有在按下P1.3时P3才会出现动作,点亮一个小灯,其他熄灭,当松开按键,小灯状态不发生改变。
这主要是由于我们使用了判断语句,条件满足就会执行输出,条件不满足,就不进入判断,输出的状态保持上一个循环的状态。于是只要条件不符合,输出状态就不会改变,相当于自锁了。接下来再测试一下两个单独的按键,分别按下按键,查看状态。
可以看出,不同的按键按下,输出的LED状态随之改变,最终的输出状态,维持了最后的按键按下时的状态。有没有一种方法,我们可以让按键的按下,对其他按键产生的状态做出改变,却又不是简单的覆盖呢?我们尝试下,当我按下P13时,八个LED灯开始流水,当我按下P20,LED开始闪烁,当我按下P21时,状态清空,所有小灯熄灭。
我们尝试书写下程序。
为了有流水的效果,我使用了延时函数。本来想写闪烁的,但想到取反一样可以看出开关导致的状态变化,所以就使用了取反,这样每一次按下,都会有变化。程序很短,对于延时不会的,可以查看往期文章或者留言即可。来看下仿真,硬件没有改变。
初始状态下,所有的都是高电位,而且由于没有符合判断条件出现的情况,所以所有判断语句都没有执行。于是LED就是初始状态,全亮。此时按下P13,会看到,LED从高位逐渐向低位开始置零,直到全熄灭后,出现间隔点亮,然后静止不动。
出现该状态,说明运行正常,接着就再按下P20再试试。
通过不断的单击按键,会发现,LED的状态在不断的变化,按下一次就变化一次。
最后我们通过P21将所有状态都清空。
所有灯熄灭。在本次测试中,我们遇到几个问题,第一个:当P1进入第一判断语句时,流水灯开始,此时按键P20、P21就没有用了,点击没有反应。第二个,当点击P20时,会出现有时按一下按键,灯的状态改变两次的情况。第三个,32个端口,就只能控制32个开关?