6.3 项目三编程实现通过按键控制两灯的亮灭
1.项目需求
通过程序设计实现通过按键控制开发板上两个灯D3、D4的亮灭。
2.项目分析
本项目使用的是新大陆公司的Zigbee开发板,四个灯和按键SW在开发板中的位置如图6-19所示。此开发板上有四个灯,依次为D4、D3、D6、D5,有一个按键SW,四个灯和按键在开发板中与CC2530单片机之间的连接引脚如图6-20所示。

图6-19 四个灯和按键SW在开发板中的位置

图6-20 四个灯和按键的对应引脚关系
要想通过按键SW控制开发板上的两个灯D3和D4的亮灭,需要找到灯对应的引脚,然后通过引脚发送指令去控制灯的状态。
要使按键能够输入指令去控制两个引脚P1.0和P1.1输出指令,进而控制两个灯D3和D4的亮灭,首先要设置引脚与灯的对应关系。可以通过宏定义#define D3 P1_0定义灯D3为P1.0口控制,通过宏定义#define D4 P1_1定义灯D4为P1.1口控制,这样就建立好了两个引脚和两个灯之间的对应关系。可以通过宏定义#define SW P1_2定义按键与引脚P1.2的对应关系。然后通过P1口的功能选择寄存器表查看到引脚值为1表示外设功能,为0表示普通输入输出口。要从引脚输出指令控制灯,必须将引脚设为普通输入输出功能,因此引脚值应置为0。P1口的功能寄存器与16进制的03取反后进行逻辑与运算:
P1SEL&=~0x07
等价于:
P1SEL&=~00000111
等价于:
P1SEL&=11111000
因此,无论P1口的功能寄存器原来的值为多少,与11111000做逻辑与运算后,引脚P1.0、P1.1、P1.2的值一定是0,这就保证了这三个引脚为普通输入输出功能。
要通过按键向引脚输入指令,必须将按键引脚P1.2的方向设置为输入,并将P1.0和P1.1两引脚设置为输出,从P1口的方向寄存器表中查看到引脚值0为输入,1为输出。P1口的方向寄存器与16进制的03取反后进行逻辑或运算:
P1DIR|=0x03
等价于:
P1DIR|=00000011
将P1.0和P1.1的值置为1,即设置P1.0和P1.1为输出口。因此,无论P1口对应的方向寄存器原来的值为多少,与00000011做逻辑或运算后,引脚P1.0和P1.1的值一定是1,这就保证了这两个引脚方向为输出。P1口的方向寄存器与16进制的04取反后进行逻辑与运算:
P1DIR&=~0x04
等价于:
P1DIR&=~00000100
等价于:
P1DIR&=111111011
将P1.2的值置为0,即设置P1.2为输入口。因此,无论P1口的方向寄存器原来的值为多少,与111111011做逻辑与运算后,倒数第三位的结果一定是0。
在主程序中,两灯初始状态为灭。通过while循环检测到按键被按下时,对电脉冲信号为低电平时有效。在延时一定时间后,如果仍然是按下键的状态,则触发两灯同时亮,并延时一定的时间。当再次按下按键,并在延时一定时间后仍然是按下键的状态时,则触发两灯同时灭,再重复此过程。“D3=!D3;”和“D4=!D4;”是将两灯的状态分别取反后再赋值给两灯。
3.程序设计
程序设计如下:
(https://www.daowen.com)
通过仿真器将程序烧写到开发板中,并运行程序,可以看到,当按下按键时两灯亮,再按下键时,两灯同时熄灭,依次类推此过程。
4.举一反三
如果更改项目需求,编程实现按键控制D5和D6两灯,该怎样编写程序?
要想通过按键SW控制开发板上的两个灯D5和D6的亮灭,需要找到对应的引脚,通过引脚发送指令来控制灯的状态。
要使按键能够输入指令去控制两个引脚P1.3和P1.4输出指令,进而控制两个灯D5和D6的亮灭,首先要设置引脚与灯的对应关系。可以通过宏定义#define D5 P1_3定义灯D5为P1.3口控制,通过宏定义#define D6 P1_4定义灯D6为P1.4口控制,这样就建立好了两个引脚和两个灯之间的对应关系。通过宏定义#define SW P1_2定义按键与引脚P1.2的对应关系。然后通过P1口的功能选择寄存器表查看到引脚值为1表示外设功能,为0表示普通输入输出口。要从引脚输出指令控制灯,必须将引脚设为普通输入输出功能,因此引脚值应置为0。P1口的功能寄存器与16进制的03取反后进行逻辑与运算:
P1SEL&=~0x18
等价于:
P1SEL&=~00011000
等价于:
P1SEL&=11100111
因此,无论P1口的功能寄存器原来的值为多少,与11100111做逻辑与运算后,引脚P1.2、P1.3、P1.4的值一定是0,这就保证了这三个引脚为普通输入输出功能。
要通过按键向引脚输入指令,必须将引脚的方向设置为输入,从P1口的方向寄存器表中查看到引脚值0为输入,1为输出。因此要设置方向寄存器对应引脚值为0,P1口的方向寄存器与16进制的03取反后进行逻辑或运算:
P1DIR|=0x18
等价于:
P1DIR|=00011000
将P1.3和P1.4的值置为1,即设置P1.3和P1.4为输出口。因此,无论P1口的方向寄存器原来的值为多少,与00011000做逻辑或运算后,引脚位P1.3和P1.4的结果一定是1,这就保证了这两个引脚方向为输出。
P1口的方向寄存器与16进制的04取反后进行逻辑与运算:
P1DIR&=~0x04
等价于:
P1DIR&=~00000100
等价于:
P1DIR&=111111011
将P1.2的值置为0,即设置P1.2为输入口,因此,无论P1口的方向寄存器原来的值为多少,与111111011做逻辑与运算后,倒数第三位的结果一定是0。
在主程序中,两灯初始状态为灭。通过while循环检测到按键被按下时,对电脉冲信号为低电平时有效。在延时一定时间后,如果仍是按下键的状态,则触发两灯同时亮,并延时一定的时间。当再次按下按键,并在延时一定时间后仍然是按下键的状态时,则触发两灯同时灭,再重复此过程。“D5=!D5;”和“D6=!D6;”是将两灯的状态分别取反后再赋值给两灯。
思考:如果需求改为按键控制D3和D5两灯,程序该怎样编写?
要考虑D3和D5两灯的引脚P1.0和P1.3。在开始的宏定义中要定义灯D3和P1.0的对应关系,灯D4和P1.3的对应关系。功能寄存器设置为:
P1SEL&=~0x09
方向寄存器设置为:
P1DIR|=0x19
P1DIR&=~0x04
主程序的编写请读者自己完成。