资源描述
学习情境3 变化点亮LED彩灯
知识点:
1.C51程序的if语句形式及选择结构程序设计方法;
2. C51程序中的关系运算符及表达式;
3. C51程序中的逻辑运算符及表达式;
4. C51程序中的switch语句;
5. C51程序中的位逻辑运算符及表达式;
6. C51程序中的数字表示形式。
技能点:
1.能熟练运用Keil51软件调试源程序;
2.能熟练运用proteus仿真软件;
3.能应用if语句的嵌套形式设计多分支程序;
4.能应用switch设计多分支程序;
5.能熟练应用C51中的关系运算符、逻辑运算符、位逻辑运算符及表达式完成控制程序的编写;
6.能设计开关量的输入电路。
学习情境目标
本学习情境是以8只发光二极管显示为例,用单片机控制发光二极管,实现8只发光二极管有规律的变化点亮。从而学习C51的分支结构程序设计、关系运算符和逻辑运算符及表达式。
学习情境分析
为了让单片机控制发光二极管,将8只发光二极管接在单片机P1口上,根据P2口外接的组合开的状态有规律的控制P1口的任意管脚上为低电平,则接在它上面的发光二极管就被点亮;反之,如果P1口的任意管脚上为高电平,则接在它上面的发光二极管就不会被点亮。连接电路图如图3-1所示。
图3-1 连接电路图
任务一 简单变化点亮8路彩灯
任务目标
本任务是用P2口外接8位组合开关,根据P2口的开关组合状态,单片机的P1口控制外接的8个发光二极管固定显示。掌握利用if~else语句实现分支结构程序设计的方法。
任务程序分析
在这里,要编写C51程序,首先读取P2口的开关组合状态,利用if~else控制语句实现将一个不同的8位无符号数通过P1口输出并能通过8个发光二极管观察结果。从输出的具体数据来看,D1灯亮需要的数据是P1.0的位为0,D2灯亮需要的数据是P1.1的位为0,依此类推。
源程序
#include "reg51.h" //包含头文件
#define uint unsigned int //宏定义
#define uchar unsigned char //宏定义
void main(void)
{
uchar i;// 定义i为无符号字符型变量
while(1)//无限循环
{
i=P2;//将P2口外接开关状态读进来送给i变量
if(i==0xff) P1=~i;//判i变量的值如果为0xff,则P1输出00,二极管全亮
else if(i==0xfe) P1=0xfe;// 判i变量的值如果为0xfe,则P1输出0xfe,只有D1二极管亮
else if(i==0xf0) P1=0xf0; //判i变量的值如果为0xf0,则P1输出0xf0,D1、D2、D3、D4二极管亮
else if(i==0x0f) P1=0x0f;// 判i变量的值如果为0x0f,则P1输出0x0f,D5、D6、D7、D8二极管亮
else if(i==0x55) P1=0x55;// 判i变量的值如果为0x55,则P1输出0x55,D2、D4、D6、D8二极管亮
else if(i==0xaa) P1=0xaa;// 判i变量的值如果为0xaa,则P1输出0xaa,D1、D3、D5、D5二极管亮
else P1=0xff;//否则,全不亮
}
}
任务实施
1.利用proteus仿真软件绘制电路原理图
按照情景一proteus仿真软件绘制电路过程绘制原理图3.1,绘制原理图时的添加器件有:AT89S51,LED-BLUE,RESPARK-8,DIPSW_8等,注意电源器件的放置于连线。
2. C51程序的编译
按照情景一Keil C51编译软件的操作步骤对源程序进行编译和调试。
3.执行程序观察效果
将编译成功后的.HEX文件加载到CPU,根据程序设置DIPSW_8组合开关的状态,执行程序观察效果。
相关知识
1. C51程序的选择结构程序设计
在结构化的程序设计中,程序由三种基本结构组成。它们分别是顺序结构,选择结构和循环结构。已经证明,由三种基本结构组成的算法结构可以解决任何复杂的问题。由三种基本结构组成的程序可以称为结构化程序。其中:
顺序结构流程图如图3.2所示。由图我们不难看出,程序执行时先执行语句1再执行语句2,两者是顺序执行的关系,我们前面介绍的源程序中,赋值语句都可以实现该结构。
选择结构流程图如图3.3所示。当判断表达式P为真时,执行语句1部分,否则执行语句2部分。尤其要注意的是语句1和语句2在程序的执行中只有一个被执行。
循环结构将在情景4中介绍。
语句2
语句1
真
假
语句2
语句1
P表达式
图3.2 顺序结构流程图 图3.3 选择结构流程图
2. C51程序中的if语句的三种形式
C语言提供了三种形式的if语句。
(1)if(表达式) 语句
例如:if(a>b) { t=a; a=b; b=t; }
(2)if (表达式) 语句1 ;
else 语句2;
例如:if(i==0xaa) P1=0xaa;
else P1=0xff;
(3)if(表达式1) 语句1;
else if(表达式2) 语句2;
else if(表达式3) 语句3;
···
else if(表达式m) 语句m;
else 语句n;
源程序中采用了这种形式。这种形式实际上是一种嵌套的if形式,用于多分支结构程序设计。
3.关系运算符和关系表达式
关系运算是一种简单的逻辑运算,关系运算符中的“关系”二字指的是一个值与另一个值之间的关系。
(1)关系运算符及优先级
关系运算符就是关系比较符,C语言共有6种关系运算符,见表3-1。
表3-1 关系运算符
关系运算符
作 用
结 合 性
<
小于
左结合性
<=
小于等于
>
大于
>=
大于等于
==
等于
左结合性
!=
不等于
注意:
1)关系运算符共分两级,其中<,<=,>,>=的优先级相同,且高于==和!=(二者优先级相同)。
2)关系运算符的优先级低于算术运算符,高于赋值运算符。
例:
a+b>c 等价于 (a+b)>c
a<b==c 等价于 (a < b)==c
a>b!=c 等价于 (a>b)!=c
a=b>=c 等价于 a=(b>=c)
a-8<=b==c 等价于 ((a-8)<=b)==c
(2)关系表达式
关系表达式是由关系运算符和括号将两个表达式连结起来的一个有值的式子,其中关系运算符两边的表达式可以是算术表达式、变量、常数、数组元素、函数,表达式的值只能同时是算术量或同时是字符,关系表达式的值是一个逻辑量,只能是“.TRUE.”和“.FALSE.”二者之一,习惯用“1”和“0”来表示。例如,程序中“i==0xff”就是一个关系表达式,看i的值是否是0xff,i的值如果是0xff,则关系表达式的值为1,反之为0。
4.逻辑运算符和逻辑表达式
逻辑运算就是将关系表达式用逻辑运算符连接起来,并对其求值的一个运算过程。
(1)逻辑运算符及优先级
C51语言提供三种逻辑运算符,分别是: &&(逻辑与),||(逻辑或)和!(逻辑非)。“逻辑与”和“逻辑或”是双目运算符,要求有两个运算量,如 (A>B) && (X>Y)。“逻辑非”是单目运算符,只要求有一个运算量。如 !(A>B)。
逻辑运算符及其他运算符之间的优先级关系见表3-2所示。
表3-2 逻辑运算符优先级
运算符
优先级
!(逻辑非)
(高)
算术运算符
关系运算符
&& 和 ||
赋值运算符
(低)
“逻辑与”相当于生活中说的“并且”,就是两个条件都成立的情况下“逻辑与”的运算结果才为 “真”。例如:“明天又下雨并且又刮风”这是一个预言,到底预言的对不对呢?如果明天只下了雨或者只刮了风或者干脆就是大晴天,那么这个预言就错,或者说是假的。只有明天确实是又下雨并且又刮风,这个预言才是对的,或者是真的。
“逻辑或”相当于生活中的“或者”,当两个条件中有任一个条件满足,“逻辑或”的运算结果就为“真”。例如:“明天不是刮风就是下雨”,这也是一个预言了。如果明天下了雨或者明天刮了风或者明天又下雨又刮风,那么这个预言是对的。只有明天又不刮风又不下雨,这个预言才是错的。
“逻辑非”相当于生活中的“不”,当一个条件为真时,“逻辑非”的运算结果为“假”。
表3-3为逻辑运算真值表:它表示当条件A是否成立与条件B是否成立形成不同的组合时,各种逻辑运算所得到的值。A、B的值为0表示条件不成立,为1表示条件成立。
表3-3 逻辑运算真值表
A
B
!A
!B
A&&B
A||B
0
0
1
1
0
0
0
1
1
0
0
1
1
0
0
1
0
1
(2)逻辑表达式
用逻辑运算符连接若干个表达式组成的式子叫逻辑表达式。逻辑表达式的值为一个逻辑值1或0。逻辑运算符不仅可以连接关系表达式,还可以连接常量、变量、算术表达式、赋值表达式甚至逻辑表达式本身。如果一个表达式太复杂,可以通过括号来保证运算次序。
例如: a<b || c= =d 等价于: (a<b) || (c= =d)
又如: x<10&&x+y!=20 等价于: (x<10)&&((x+y)!=20)
注意:C51程序中规定任意一个非零整数的逻辑值为1,而常数0的逻辑值为0。例如:
5&&0的逻辑值为0
5||0的逻辑值为1
!20的逻辑值为0
想一想为什么?
5.AT89S51的P2口外接组合开关电路介绍
电路图中DIPSW-8为一个组合开关,里面包含8路独立单个开关,单个开关电路工作原理图如图3.4所示。
单片机
图3.4 单个开关电路工作原理图
由图可知,在开关断开时由于端口引脚上拉电阻的存在,使得引脚电平为高电平;在开关合上时,由于开关的另一端接地使得引脚电平为低电平。
任务二 复杂变化点亮8路彩灯
任务目标
本任务是用P2口外接8位组合开关,根据P2口的开关组合状态,单片机的P1口控制外接的8个发光二极管固定显示。掌握利用switch语句实现多分支结构程序设计的方法。
任务程序分析
在这里,要编写C51程序,首先读取P2口的开关组合状态,利用switch控制语句实现将一个不同的8位无符号数通过P1口输出并能通过8个发光二极管观察结果。
源程序
#include "reg51.h" //包含头文件
#define uint unsigned int //宏定义
#define uchar unsigned char //宏定义
void main(void)
{
uchar i;// 定义i为无符号字符型变量
while(1)//无限循环
{
i=P2;//将P2口外接开关状态读进来送给i变量
switch(i)
{case 0xff: P1=~i;//判i变量的值如果为0xff,则P1输出00,二极管全亮
break;
case 0xfe: P1=0xfe;// 判i变量的值如果为0xfe,则P1输出0xfe,只有D1二极管亮
break;
case 0xf0: P1=0xf0; //判i变量的值如果为0xf0,则P1输出0xf0,D1、D2、D3、D4二极管亮
break;
case 0x0f: P1=0x0f;// 判i变量的值如果为0x0f,则P1输出0x0f,D5、D6、D7、D8二极管亮
break;
case 0x55: P1=0x55;// 判i变量的值如果为0x55,则P1输出0x55,D2、D4、D6、D8二极管亮
break;
case 0xaa: P1=0xaa;// 判i变量的值如果为0xaa,则P1输出0xaa,D1、D3、D5、D5二极管亮
break;
default: P1=0xff;//否则,全不亮
}
}
}
任务实施
1.利用proteus仿真软件绘制电路原理图
按照情景一proteus仿真软件绘制电路过程绘制原理图3.1,绘制原理图时的添加器件有:AT89S51,LED-BLUE,RESPARK-8,DIPSW_8等,注意电源器件的放置于连线。
2. C51程序的编译
按照情景一Keil C51编译软件的操作步骤对源程序进行编译和调试。
3.执行程序观察效果
将编译成功后的.HEX文件加载到CPU,根据程序设置DIPSW_8组合开关的状态,执行程序观察效果。
相关知识
1. C51程序中的switch控制语句
switch语句是多分支选择语句。用来实现多分支选择结构。if语句只有两个分支可供选择,而实际问题中常常需要多分支的选择。
(1)switch语句的形式如下:
switch(表达式)
{ case 常量表达式1:语句1;
case 常量表达式2:语句2;
·
·
·
case 常量表达式n:语句n;
default : 语句n+1;
}
说明:
① switch是关键字,switch语句后面用括号括起来的部分是语句体。
② 紧跟在switch后一对括号内的表达式可以是整型表达式,也可以是字符型和枚举类型的表达式等。表达式两侧的括号不可以省略。
③ case也是关键字,与其后面的常量表达式和称case语句标号。常量表达式的类型必须与switch语句后的表达式一致。各case语句后的常量应互不相同。
④ default也是关键字,起标号的作用。代表所有case标号以外的标号。default标号可以出现在语句体的任何位置,在switch语句中也可以没有default标号。
⑤ case语句标号后的语句1,语句2,可以是一条语句也可以是若干语句,也可以省略不写。
⑥ 在关键字case和常量表达式间一定要有空格。
⑦ switch语句的执行如下:首先计算紧跟在其后括号内的表达式的值,然后在switch语句体中找与该值吻合的case的标号,如果有,则执行该标号后开始的各语句,包括在其后的所有case和default中的语句,直到switch语句的结束。如果没有与该值相吻合的标号,并且存在default语句,则从default标号后的语句开始执行,直到switch语句结束。如果没有与该值吻合的标号,并且没有default标号,则跳过该switch语句体,什么也不做。
(2)switch语句中break语句的使用。
break语句又称间断语句,可使程序跳出switch语句而执行switch以后的语句。根据上面关于switch语句执行过程的说明,我们知道switch语句并没有真正实现多分支选择的流程,这就需要在switch语句中使用break语句。可以在case标号之后的语句最后加上break语句,每当执行到break语句,立即跳出switch语句体,从而使switch语句真正起到多分支的作用。
程序中实际上利用变量i的值即P2口外接的组合开关的状态来控制单片机执行哪一条case语句后的语句,从而实现P1口输出不同数据,最后执行break语句跳出switch语句,实现了多分支结构程序设计。用switch语句实现多分支程序在逻辑上要比用嵌套的if语句实现更清晰一些。
2. C51程序中的位逻辑运算符
C51语言和其它高级语言不同的是它完全支持按位逻辑运算符。这与汇编语言的位操作有些相似。C51语言中按位逻辑运算符如表3-4:
表3-4 按位逻辑运算符
操作符
含 义
&
位逻辑与
|
位逻辑或
^
位逻辑异或
~
位逻辑反
>>
右移
<<
左移
按位运算是对字节或字中的实际位进行检测、设置或移位, 它只适用于字符型和整数型变量以及它们的变体, 对其它数据类型不适用。
关系运算和逻辑运算表达式的结果只能是1或0。 而按位运算的结果可以取0或1以外的值。要注意区别按位运算符和逻辑运算符的不同。
下面详细说明每个运算符的功能
(1)按位逻辑与(&)
按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1,否则为0。参与运算的数以补码方式出现。
例如:
9&5可写算式如下:
00001001 (9的二进制补码)
00000101 (5的二进制补码) (按位与 &)
00000001 (1的二进制补码)
可见9&5=1。
(2)按位逻辑或(|)
按位或运算符"|"是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。
例如:
9|5可写算式如下:
00001001
00000101 (按位或|)
00001101 (十进制为13)
可见9|5=13。
(3)按位逻辑异或(^)
按位异或运算符"^"是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。参与运算数仍以补码出现。
例如:
9^5可写成算式如下:
00001001
00000101 (按位异或 ^)
00001100 (十进制为12)
(4)求反运算符~
求反运算符“~”为单目运算符,具有右结合性。其功能是对参与运算的数的各二进位按位求反。
例如:
~9的运算为:
~(0000000000001001)
结果为:1111111111110110
程序中变量i 被定义为无符号字符型,在内存中占一个字节空间,如果i的值为0xff即8位二进制数为11111111,则按位取反后为00000000,然后通过P1口输出,所以外接的所有二极管都亮。
(5)移位运算符
移位运算符">>"和"<<"是指将变量中的每一位向右或向左移动, 其通常形式为:
右移: 变量名>>移位的位数
左移: 变量名<<移位的位数
经过移位后, 一端的位被"挤掉", 而另一端空出的位以0 填补, 所以, C51语言中的移位不是循环移动的。
例如:
设 a=15
a>>2
表示把000001111右移为00000011(十进制3)。
又如 a<<4
指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48)。
应该说明的是,对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0,而为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定。Turbo C和很多系统规定为补1。
3.计算机中带符号数的表示形式
计算机中的数都是以二进制数来表示和存储的,计算机中数的表示形式有3种,即所谓的原码、反码、补码。对带符号数而言,数的最高位为符号位,如果符号位为0表示该数为正数,如果符号位为1表示该数为负数,并且一般用补码来表示带符号数。下面以一个数的三种表示形式来阐述原码、反码、补码的概念。
(1)+30的原码、反码、补码
+30的原码就是将正数转化为8位二进制数,转换结果为00011110,画线部分为符号位,对于一个正数而言,它的原码、反码、补码是一样的。
(2)-30的原码、反码、补码
先求-30的绝对值数的原码:00011110
将符号位改为1变成: 10011110 即为-30的原码
符号位不变,其它位取反变成:11100001即为-30的反码
在最低位加1,符号位为1不变:11100010即为-30的补码
注意:-30在计算机存储器里就是以8位二进制数11100010存放的。
变一变
1.用if语句的第一种形式修改任务1的源程序完成相同功能。
2.修改任务1的源程序,当组合开关的状态为00110011、10011001、00001111、11110000、10001001、01110111时,P1口分别输出对应的组合开关的状态。
3.修改任务2的源程序完成上一题的功能。
10 / 10
展开阅读全文