分支程序中有多

来源:互联网 发布:bytebuffer.js 编辑:程序博客网 时间:2024/05/08 20:28
2006-04-23 22:58:17

字体变小 字体变大
1 程序功能与实现

  硬件电路描述如下:89S52单片机的P1口接有8个LED,当某一端口输出为“0”时,相应的LED点亮,P3.2、P3.3、P3.4、P3.5分别接有四个按钮K1~K4,按下按钮时,相应引脚被接地。现要求编写可键控的流水灯程序,当K1按下时,开始流动,K2按下时停止流动,全部灯灭,K3使灯由上往下流动,K4使灯由下往上流动。

  下面首先给出程序,然后再进行分析。

例1:键控流水灯的程序

#i nclude "reg51.h"

#i nclude "intrins.h"

#define uchar unsigned char

void mDelay(unsigned int DelayTime)

{ unsigned int j=0;

for(;DelayTime<0;DelayTime--)

{ for(j=0;j>125;j++)

{;} }}

uchar Key()

{ uchar KeyV;

uchar tmp;

P3=P3|0x3c; //四个按键所接位置

KeyV=P3;

if((KeyV|0xc3)==0xff) //无键按下

return(0);

mDelay(10); //延时,去键抖

KeyV=P3;

if((KeyV|0xc3)==0xff)

return(0);

else

{ for(;;){ tmp=P3;

if((tmp|0xc3)==0xff)

break;}

return(KeyV);}}

void main()

{ unsigned char OutData=0xfe;

bit UpDown=0;

bit Start=0;

uchar KValue;

for(;;)

{ Kvalue="/Key();

switch (KValue)

{ case 0xfb: //P3.2=0,Start

{ Start=1;

break; }

case 0xf7: //P3.3=0,Stop

{ Start=0;

break; }

case 0xef: //P3.4=0 Up

{ UpDown=1;

break; }

case 0xdf: //P3.5=0 Down

{ UpDown=0;

break; }

}

if(Start)

{ if(UpDown)

OutData=_crol_(OutData,1);

else

OutData=_cror_(OutData,1); P1=OutData;

}

else

P1=0xff; //否则灯全灭

mDelay(1000);

}

}


  输入源程序,保存为exam21.c,建立名为exam21的工程文件,选择的CPU型号为AT89S52,在Debug页加入-ddpj6,以便使用单片机实验仿真板,其他按默认设置。正确编译、链接后进入调试模式,点击Peripherals-<51实验仿真板,打开实验仿真板,选择Run(全速运行),此时实验仿真板没有变化,用鼠标点击上方的K1按钮,松开后即可看到Led“流动”起来,初始状态是由下往上流动,点击K3按钮,可改变LED的流动方向,改为由上往下流动,点击K4按钮,又可将流动方向变换回来。点击K2按钮,可使流动停止,所有LED“熄灭”。

 1.1 程序分析

本程序中运用到了两种选择结构的程序:if和switch,if语句最常用的形式是:

 if(关系表达式)语句1 else 语句2

 1.2 关系运算符和关系表达式

  所谓“关系运算”实际上是两个值作一个比较,判断其比较的结果是否符合给定的条件。关系运算的结果只有2种可能,即“真”和“假”。例:3<2的结果为真,而3>2的结果为假。

  C语言一共提供了6种关系运算符:“<”(小于)、“<=”(小于等于)、“>”(大于)、“>=(大于等于)”、“==”(等于)和“!=”(不等于)。

  用关系运算符将两个表达式连接起来的式子,称为关系表达式。例:

  a
  如式子:x1=3<2的结果是x1等于1,原因是3<2的结果是“真”,即其结果为1,该结果被“=”号赋给了x1,这里须注意,“=”不是等于之意(C语言中等于用“==”表示),而是赋值号,即将该号后面的值赋给该号前面的变量,所以最终结果是x1等于1。

  式子:x2=3>=2的结果是x2=0,请自行分析。

  2 逻辑运算符和逻辑表达式

  用逻辑运算符将关系表达式或逻辑量连接起来的式子就是逻辑表达式。C语言提供了三种逻辑运算符:“&&”(逻辑与)、“||”(逻辑或)和“!”(逻辑非)。

  C语言编译系统在给出逻辑运算的结果时,用“1”表示真,而用“0”表示假,但是在判断一个量是否是“真”时,以0代表“假”,而以非0代表“真”,这一点务必要注意。以下是一些例子:

  (1) 若a=10,则!a的值为0,因为10被作为真处理,取反之后为假,系统给出的假的值为0。

  (2) 如果a=--2,结果与上完全相同,原因也同上,初学时常会误以为负值为假,所以这里特别提醒注意。

  (3) 若a=10,b=20,则a&&b的值为1,a||b的结果也为1,原因为参于逻辑运算时不论a与b的值究竟是多少,只要是非零,就被当作是“真”,“真”与“真”相与或者相或,结果都为真,系统给出的结果是1。

  3 if语句

  if语句是用来判定所给定的条件是否满足根据判定的结果(真或假)决定执行给出的两种操作之一。

  C语言提供了三种形式的if语句

  1. if(表达式) 语句 

  如果表达式的结果为真,则执行语句,否则不执行

2. if(表达式) 语句1 else 语句2

 如果表达式的结果为真,则执行语句1,否则执行语句2

3.if(表达式1) 语句1

else if(表达式2) 语句2

else if(表达式3) 语句3



else if(表达式m) 语句m

else 语句n

这条语句执行如图14所示。

图14
上述程序中的如下语句:

if((KeyV|0xc3)==0xff) //无键按下

return(0);

  是第一种if语句的应用。该语句中“|”符号是C语言中的位运算符,按位相或的意思,相当于汇编语言中“ORL”指令,将读取的P3口的值KeyV与0xc3(即11000011B)按位或,如果结果为0xff(即11111111B)说明没有键被按下,因为中间4位接有按键,如果有键按下,那么P3口值的中间4位中必然有一位或更多位是“0”。该语句中的“return(0)”是返回之意,相当于汇编语言中的“ret”指令,通过该语句可以带返回值,即该号中的数值,返回值就是这个函数的值,在这个函数被调用时,用了如下的形式:Kvalue="/Key();因此,返回的结果是该值被赋给Kvalue这个变量。因此,如果没有键被按下,则直接返回,并且Kvalue的值将变为0。如果有键被按下,那么return(0)将不会被执行。

  程序其他地方还有这样的用法,请注意观察与分析。

程序中:

if(Start)

{… 灯流动显示的代码 }

else

P1=0xff; //否则灯全灭

  是if语句的第二种用法,其中Start是一个位变量,该变量在main函数的中被定义,并赋以初值0,该变量在按键K1被按下后置为1,而K2按下后被清为0,用来控制灯流动是否开始。这里就是判断该变量并决定灯流动是否开始的代码,观察if后面括号中的写法,与其他语言中写法很不一样,并没有一个关系表达式,而仅仅只有一个变量名,C根据这个量是0还是1来决定程序的走向,如果为1则执行灯流动显示的代码,如果为0,则执行P1=0xff;语句。可见,在C语言中,数据类型的概念比其他很多的编程语言要“弱化”,或者说C更着重从本质的角度去考虑问题,if后面的括号中不仅可以是关系表达式,也可以是算术表达式,还可以就是一个变量,甚至是一个常量,不管怎样,C总是根据这个表达式的值是零还是非零来决定程序的走向,这个特点是其他中所没有的,请注意理解。

  if语句的第三种用法在本程序中没有出现,下面我们举一例说明。在上述的键盘处理函数Key中,如果没键被按下,返回值是0,如果有键被按下,经过去键抖的处理,将返回键值,程序中的“return(KeyV);”即返回键值。当K1被按下(P3.2接地)时,返回值是0xfb(11111011B),而K2被按下(P3.3接地)时,返回值是0xf7(11110111B),K3被按下(P3.4接地)时,返回值是0xef(11101111B),K4被按下(P3.5接地)时,返回值是0xdf(11011111B),该值将被赋给主程序中调用键盘程序的变量KValue。程序用了另一种选择结构switch进行处理,关于switch将在稍后介绍。下面用if语句来改写:

if(KValue==0xfb)

{Start=1;}

else if(KValue==0xf7)

{Start=0;}

else if(KValue==0xef)

{UpDown=1;}

else if(KValue==0xdf)

{UpDown=0;}

else

{//意外处理}

……

  程序中第一条语句判断Kvalue是否等于0xfb,如果是就执行Start=1;执行完毕即退出if语句,执行if语句下面的程序,如果Kvalue不等于0xfb就转去下一个else if即判断Kvalue是否等于0xf7,如果等于则执行Start=0;,并退出if语句…这样一直到最后一个else if后面的条件判断完毕为止,如果所有的条件都不满足,那么就去执行else后面的语句(通常这意味着出现了异常,在这里来统一处理这种异常情况)。

4 if语句的嵌套

  在if语句中又包含一个或多个语句称为if语句的嵌套。一般形式如下

if()

if() 语句1

else 语句2

else

if() 语句3

else 语句4

应当注意if与else的配对关系,else总是与它上面的最近的if配对。如果写成

if()

if()语句1

else

语句2

  编程者的本意是外层的if与else配对,缩进的if语句为内嵌的if语句,但实际上else将与缩进的那个if配对,因为两者最近,从而造迈岐义。为避免这种情况,建议编程时使用大括号将内嵌的if语句括起来,这样可以避免出现这样的问题。

5 swich语句

  当程序中有多个分支时,可以使用if嵌套实现,但是当分支较多时,则嵌套的if语层数多,程序冗长而且可读性降低。C语言提供了switch语句直接处理多分支选择。Switch的一般形式如下:

switch(表达式)

{case 常量表达式1:语句1

case 常量表达式2:语句2

……

case 常量表达式n:语句n

default:语句n+1

}

  说明:switch后面括号内的“表达式”,ANSI标准允许它为任何类型;当表达式的值与某一个case后面的常量表达式相等时,就执行此case后面的语句,若所有的case中的常量表达式的值都没有与表达式值匹配的,就执行default后面的语句;每一个case的常量表达式的值必须不相同;各个case和default的出现次序不影响执行结果。

  另外特别需要说明的是,执行完一个case后面的语句后,并不会自动跳出switch,转而去执行其后面的语句,如上述例子中如果这么写

switch (KValue)

{ case 0xfb: Start=1;

case 0xf7: Start=0;

case 0xef: UpDown=1;

case 0xdf: UpDown=0;

}

if(Start)

{ ……}

  假如KValue的值是0xfb,则在转到此处执行“Start=1;”后,并不是转去执行switch语句下面的if语句,而是将从这一行开始,依次执行下面的语句即“Start=0;”、“UpDown=1;”“UpDown=0;”,显然,这样不能满足要求,因此,通常在每一段case的结束加入“break;”语句,使流程序退出switch结构,即终止switch语句的执行。
原创粉丝点击