循环结构程序是重复执行同一个程序段的一种基本程序结构。实际应用中,经常会遇到需要多次执行某段特定代码的情况,这时可以采用循环程序,缩短程序的长度,节省程序的存储空间。从本质上说,循环结构程序是分支结构程序的一种特殊形式。由于它在程序设计中的重要性,因此,一般单独作为一种程序结构的形式来介绍。
一个典型的循环程序由4部分组成,即循环初始化部分、循环处理部分、循环控制部分和循环结束部分。下面分别进行介绍。
●循环初始化部分:程序在进入循环处理程序段之前,需要设置循环初始参数,如循环的次数、有关的工作单元清零、变量设置和地址指针设置等。
●循环处理部分:循环处理部分通常称为循环体,是循环执行的主要代码段,它是整个循环结构的核心。
●循环控制部分:循环控制部分一般由两个单元组成,修改控制变量和判断循环结束。循环控制变量可以采用循环递减计数法,即每循环一次,控制变量减1,并判断是否为0,若不为0,则继续执行循环体程序,否则结束循环体的执行;也可以采用条件控制,即判断结束条件是否成立,如果不成立,则继续执行循环体,否则,结束循环。
●循环结束部分:当循环体执行完毕后,需要在这里对结果进行处理和存储。
循环结构大致可以分为两种,分别如图5-5和图5-6所示。第一种是先执行后判断的循环结构,适用于循环次数已知的情况。其特点是一进入循环,先执行循环处理部分,然后根据循环次数或循环条件来判断是否继续循环。第二种是先判断后执行的循环结构,适用于循环次数未知的情况。其特点是将循环的控制部分放在循环的入口处,这样,进入循环体时,需要先根据循环控制条件来判断是否结束循环,如果不结束循环,则执行循环体,否则,则退出循环。
图5-5 先执行后判断的循环结构
图5-6 先判断后执行的循环结构
51系列单片机提供了两条循环转移指令,示例如下:
这两条指令采用不同的控制寄存器来实现循环结构,关于它们的详细介绍可以参阅本书第16章中的指令系统部分。这里,控制寄存器的计数方式一般都是减1计数,即每循环一次,计数器自动减1计数,同时判断控制寄存器是否为0,若不为0,继续执行循环;若为0,则结束循环程序的执行。循环次数需要在初始化的时候预置,循环次数的范围为1~255。如果实际问题中需要超过255次循环的时候,则可以采用多重循环来实现。
下面给出一个采用循环结构来查找最大值的程序。假定从20H单元开始连续存放了20个无符号整数,用汇编程序找出其中的最大值,并存入R2中。
寻找最大值的方法比较多,一个最基本的方法是采用比较和交换来依次进行。即先读取第一个数据与第二个数据,把第一个数据作为基准,进行比较。如果基准数大,则不做交换,再取下一个数进行比较;如果基准数小,则将大数取代原来的基准数,即相当于做一次数据交换,然后再以新的基准数与下一个数进行比较,直至全部比较完毕。这里的基准数始终保持为最大的数值,因此,全部比较完毕后,基准数即是数据块中的最大值。整个程序的流程图如图5-7所示。采用循环结构的程序示例如下:
另外,延时在程序中经常用到,延时可以用中断、计数和循环等多种方法来实现。采用循环程序来实现延时,一般可以达到任意延时的要求。采用循环延时的程序代码示例如下:
在该段程序中,主循环中采用空指令NOP来实现延时,延时的大小根据其中NOP指令的多少和每个指令的执行周期及单片机系统的主频决定。程序的流程图如图5-8所示。
图5-7 最大值查找流程图
图5-8 循环延时流程图
采用循环延时的方法虽然可以达到任意延时的要求,但其也有缺点。比如,需要牺牲CPU的工作,延时期间,CPU不能做任何事情,同时循环延时的方法一般不允许程序中有中断,否则会严重影响延时的准确性。
多重循环程序结构是循环体多于一个的程序结构。实际的程序设计中,经常遇到循环次数多于256的情况,这时必须采用多重循环来实现,既一个循环中又包含了一个或多个循环,因此也称为循环嵌套。多重循环的嵌套次数没有限制,这类循环主要应注意循环的层次要清晰,不要产生交叉,否则会造成系统紊乱。
以双重循环为例,前面的循环延时如果采用双重循环,则可以实现大的软件延时。示例如下: