![基于Proteus和Keil的C51程序设计项目教程(第2版):理论、仿真、实践相融合](https://wfqqreader-1252317822.image.myqcloud.com/cover/785/36511785/b_36511785.jpg)
2.3 任务3:有规律变化的花样灯——一一亮灯
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_67_1.jpg?sign=1739039230-me1O6y46kSKki8lOhSxwWdq9ovkyuKcA-0-265f63af73bb5a222dd4f82652d11a14)
2.3.1 任务要求与分析
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_67_2.jpg?sign=1739039230-5zxkSHEjh1KrCzTvPLd3aaijvUH8eFKI-0-23aa233cd4c3c7095f4c5b48e4b6ae75)
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一一亮的状态分析表
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_67_3.jpg?sign=1739039230-ywd10KR6TrsSlKPKLD97mDDMztBTEHNt-0-a02187e13b932eba17c56e9ecf579d6f)
续表
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_68_1.jpg?sign=1739039230-gdh6nb9w2jbtENWXLn235OzqBskkZKuz-0-47be5bdd2857591acbab920881afa39c)
2.3.2 用“位”运算符实现一一亮灯
1.认识C51的位运算符
C51支持的位操作运算符有按位进行与(&)、或(|)、异或(^)、非(~)以及开放的左移(<<)、右移(>>)。
位的逻辑运算规则见表2-7。
表2-7 位的逻辑运算规则
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_68_2.jpg?sign=1739039230-OkEVJdGvTMZhx4IBIhjgwtuYNp1suEaD-0-64439db08674cbdab83727c8994c90a1)
~:将一个数的各二进制位取反,即将0变为1,1变为0。
<<:将一个数的各二进制位全部左移若干位,右面补0,高位左移后溢出舍弃。
>>:将一个数的各二进制位全部右移若干位,无符号数高位补0,低位右移后溢出舍弃。
例如:
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_68_3.jpg?sign=1739039230-09yEkbiG41NaEWZG7JPfzzaFTcM3IDq5-0-a04aadfaff2ee6eef284a72de9bd67b9)
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_68_4.jpg?sign=1739039230-0llS6G6GjWkbi9l1G1XHtdVeU6MhH8JB-0-0e97e55efac763b4451db9386ee26ea9)
左移1位相当于该数乘以2(条件:积<255),右移n位相当于该数除以2n的商。
注意:不能对浮点型数据进行位运算。
位运算的优先级见表2-8。
表2-8 位运算的优先级
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_68_5.jpg?sign=1739039230-SCczwL4dngoP2MlnGuk99v0biVa7a9vA-0-5a65a91ccd4dc34be4552d13d3f32460)
2.用左移运算符“<<”实现一一亮灯的分析
用左移运算符“<<”实现一一亮灯的分析见表2-9。
表2-9 用左移运算符“<<”实现一一亮灯的分析
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_69_1.jpg?sign=1739039230-16HbCsOQS68A27sg9uEqSCSpRDlaQYc1-0-1c6924f0ab73188ff16e7df4b6a1845b)
2.3.3 预处理:条件编译#if、#else、#endif等
预处理:在源程序编译之前做一些处理,生成扩展C源程序。
一般情况下,在对C语言程序进行编译时,所有的程序行都参加编译,但如果要对其中的一部分内容进行编译,则可以使用条件编译。选择不同的编译条件,产生不同的代码,可为一个程序提供多个版本,实现不同的版本功能,广泛应用于商业软件。条件编译的几种格式如下。
格式一
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_69_2.jpg?sign=1739039230-6JO8848RbXB8DsZGcig5rAhL5qL9cjMo-0-9399e7dd83bf49c4cbee056b0e63cbe3)
格式二
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_69_3.jpg?sign=1739039230-0dw7Ct9wksl7M1VMcKfUjQXelEVd3Oji-0-0f399a3ed50225ca5589d7c9aa92cf2d)
格式三
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_69_4.jpg?sign=1739039230-ZLssa2DB816LNyBMCOob7LnN0cAwRo8a-0-0eccbe4c0e43bbb2986b9700b7216f24)
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_70_1.jpg?sign=1739039230-r6lG6OTj0rEo3shfWX16lo77WNeawDhE-0-d0cf92149942eff55fd30d542b58527d)
2.3.4 设计延时函数头文件“dly05s.h”
延时函数用途很多,在本项目中,多个任务的延时时间一样,用同样的程序语句,故在每个任务中都写一遍,既占空间又费时间又麻烦,故可将其设为一个头文件。
注意:保存在本任务工程中的头文件,只能供本工程用。要在不同的源程序中都可应用某头文件,就要把它保存在Keil的安装路径“驱动器\Keil\C51\INC”下。需要时通过#include<*.h>命令调用即可。
掌握预处理命令的用法,体会预处理命令的便利。
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_70_2.jpg?sign=1739039230-vhB640Lg6vAMLD8yOBtMMdFwPLonxIaS-0-99040fb04e4d872e7c02719bb3fd1ed9)
2.3.5 流程与程序设计
使用左移运算符实现一一亮灯的程序流程图如图2-23所示。程序实现如下:
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_70_3.jpg?sign=1739039230-X944Sa7TB9QLwAaZgHvCPmBOIeKuOPxx-0-c2b18265d60155cc360c769be0363589)
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_71_1.jpg?sign=1739039230-DL3z4hQkP54QEAsXkw7lzRfRNkVJW9mq-0-9dee79d06f329a72876e2ac5709ab70f)
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_71_2.jpg?sign=1739039230-xit44v8HLsRqtfq4pY5cyPlgj4VWiJZr-0-721200603a2bde5e1d712544bfdaefff)
图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一一熄灭的控制逻辑推演
![](https://epubservercos.yuewen.com/964F67/19391577901347306/epubprivate/OEBPS/Images/40331_72_1.jpg?sign=1739039230-LcdDCiIKZbkfRjXSGnPOnr9qd70mcfYS-0-5ca2967b1146d03854c98c9c46411d90)