2.3 任务3:有规律变化的花样灯——一一亮灯

2.3.1 任务要求与分析

1.任务要求

8个LED依次亮起来,即亮1个,亮2个,……,8个全亮,循环。假设从最低位亮起。

2.任务目标

(1)掌握先分解后主线串联的问题分析方法。

(2)学习现象分析并用表达式表示。

(3)掌握goto语句应用。

(4)掌握位运算符与(&)、或(|)、异或(^)、非(~),以及开放的左移(<<)、右移(>>)的应用。

3.任务分析

硬件电路如图2-9所示。P1口控制8个LED。根据亮灯逻辑,引脚电平为高,LED灭;引脚电平为低,LED亮。所以第1个显示状态为只有P1.0脚的LED亮,……,第8个显示状态为只有P1.7脚的LED亮。8个LED一一亮的状态分析见表2-6。

表2-6 8个LED一一亮的状态分析表

续表

2.3.2 用“位”运算符实现一一亮灯

1.认识C51的位运算符

C51支持的位操作运算符有按位进行与(&)、或(|)、异或(^)、非(~)以及开放的左移(<<)、右移(>>)。

位的逻辑运算规则见表2-7。

表2-7 位的逻辑运算规则

~:将一个数的各二进制位取反,即将0变为1,1变为0。

<<:将一个数的各二进制位全部左移若干位,右面补0,高位左移后溢出舍弃。

>>:将一个数的各二进制位全部右移若干位,无符号数高位补0,低位右移后溢出舍弃。

例如:

左移1位相当于该数乘以2(条件:积<255),右移n位相当于该数除以2n的商。

注意:不能对浮点型数据进行位运算。

位运算的优先级见表2-8。

表2-8 位运算的优先级

2.用左移运算符“<<”实现一一亮灯的分析

用左移运算符“<<”实现一一亮灯的分析见表2-9。

表2-9 用左移运算符“<<”实现一一亮灯的分析

2.3.3 预处理:条件编译#if、#else、#endif等

预处理:在源程序编译之前做一些处理,生成扩展C源程序。

一般情况下,在对C语言程序进行编译时,所有的程序行都参加编译,但如果要对其中的一部分内容进行编译,则可以使用条件编译。选择不同的编译条件,产生不同的代码,可为一个程序提供多个版本,实现不同的版本功能,广泛应用于商业软件。条件编译的几种格式如下。

格式一

格式二

格式三

2.3.4 设计延时函数头文件“dly05s.h”

延时函数用途很多,在本项目中,多个任务的延时时间一样,用同样的程序语句,故在每个任务中都写一遍,既占空间又费时间又麻烦,故可将其设为一个头文件。

注意:保存在本任务工程中的头文件,只能供本工程用。要在不同的源程序中都可应用某头文件,就要把它保存在Keil的安装路径“驱动器\Keil\C51\INC”下。需要时通过#include<*.h>命令调用即可。

掌握预处理命令的用法,体会预处理命令的便利。

2.3.5 流程与程序设计

使用左移运算符实现一一亮灯的程序流程图如图2-23所示。程序实现如下:

图2-23 使用左移运算符实现一一亮灯的程序流程图

2.3.6 编译、代码下载、仿真、测判

按项目1所述方法,先在Keil中新建工程LED23,然后添加源程序、设置工程选项并编译,生成代码文件LED23.HEX。参考2.1.7节下载代码,设置振荡频率为12MHz,进行仿真调试。

将代码下载到实物板进行测试。实践记录:是否成功?__________。自评分:__________。

2.3.7 进阶设计与思路点拨3:1~8个灯逐一熄灭

LED全亮后,先熄灭1个LED,即P1.0口的LED1;再熄灭两个LED,即P1.0口的LED1和P1.1口的LED2;……;最后8个LED全熄灭,再从头循环。LED一一熄灭的控制逻辑推演见表2-10。数据间的关系为

下一状态数据=(上一状态数据<<1)|0x01

从状态1→状态2,状态2→状态3,……,状态8→状态9,共移位8次。根据运行状态自行绘制流程图,设计程序,并仿真调试。

表2-10 LED一一熄灭的控制逻辑推演