首页 理论教育 单片机应用技术:基本程序结构

单片机应用技术:基本程序结构

时间:2023-10-17 理论教育 版权反馈
【摘要】:即根据条件对程序的执行情况进行判断,满足条件则转移,否则顺序执行。执行JNC指令后,形成了程序分支。采用循环程序可使程序结构紧凑、节省存储单元。图3.5循环程序结构类型a)设置计数器实现已知循环次数的循环程序。这种独立的有一定功能的程序称为子程序。调用子程序的源程序称为主程序。

单片机应用技术:基本程序结构

1.顺序程序设计

顺序程序又称简单程序,是指顺序执行的程序。在这种程序中,没有分支、循环或子程序。顺序结构程序虽然比较简单,但也能完成一定的功能,是构成复杂程序的基础。

【例3.25】两个8位无符号数相加,和仍为8位。

假设两个无符号数X1、X2分别存放于内部RAM的60H、61H单元中,求和送入62H单元。程序如下:

MOV R0,#60H ;设R0为数据指针

MOV A,@R0 ;取X1

INC R0

ADD A,@R0 ;X1+X2

INC R0

MOV @R0,A ;保存结果

2.分支程序设计

分支结构程序通常是利用条件转移指令来实现的。即根据条件对程序的执行情况进行判断,满足条件则转移,否则顺序执行。用于判断分支转移的指令有:JZ、JNZ、JC、JNC、JB、JNB、JBC、CJNE和DJNZ。另外,在该类分支程序的设计中,要设置好判断测试对象、程序转移方向及转移的标志地址。在MCS-51指令系统中,把这些指令结合在一起使用,就可以完成多种条件判断,如正负判断、溢出判断、大小判断等。

(1)利用条件转移指令实现程序分支。

【例3.26】比较内部RAM的40H和50H单元中两个无符号数的大小,使得40H存放大数,50H单元存放小数

程序流程图如图3.4所示。

图3.4 比较两个无符号数的大小

程序如下:

ORG 2000H

START:CLR C

MOV A,40H

SUBB A,50H

JNC DONE ;若无借位,即(40H)≥(50H)时转移

MOV A,40H

XCH A,50H ;有借位,即(40H)<(50H)时交换

MOV 40H,A

DONE:SJMP 

上面的程序中,用减法指令SUBB来比较两数的大小。由于这是一条带借位的减法指令,所以在执行该指令前,先要把进位位清零。用减法指令通过借位(CY)的值来判断两数的大小,是比较两个无符号数大小的常用方法。执行JNC指令后,形成了程序分支。

(2)利用比较转移指令实现程序分支。

【例3.27】用CJNE指令实现车速自动控制。检测车速V存放到R7中,与标准车速相比较,标准车速在V1~V2之间(V1<V2),分别存放在BUF1、BUF2单元内。若V介于V1、V2之间,汽车正常行驶;若V>V2,汽车减速;若V<V1,汽车加速。该程序段编写如下:

MOV A,R7

CJNE A,BUF1,CON1

AJMP KEEP ;KEEP为保持车速程序段

CON1:JC UP ;UP为加速程序段

CJNE A,BUF2,CON2

AJMP KEEP

CON2:JNC DOWN ;DOWN为减速程序段

AJMP KEEP

KEEP:…

UP:…

DOWN:…

3.循环程序设计

在应用程序中,有时需要重复执行某一段程序,这时可采用循环程序。循环程序是指当某种条件满足时,能够重复执行某一段程序的程序结构。采用循环程序可使程序结构紧凑、节省存储单元

循环程序一般由以下5部分组成:

初始化部分:这是循环程序的准备部分,如给循环次数计数器、地址指针和某些地址变量赋初值。

②处理部分:为反复执行的程序段,这是循环程序的实体。

③修改部分:每执行一次处理部分后,对地址指针作一次修改,使指针指向下一数据所在位置,为进入下一轮处理作准备。

④控制部分:根据循环次数计数器的值(即循环变量值)或其它循环条件,确定循环是否继续进行。若循环次数未达规定值或循环条件满足,继续循环;否则退出循环。

⑤结束部分:分析、处理及存放程序执行结果。

循环程序的结构一般有两种形式:

①先进入处理部分,再控制循环,如图3.5a所示。这种结构至少执行一次循环体。

②先控制循环,后进入处理部分,如图3.5b所示。这种结构根据判断结果,控制循环的执行与否,有时可能不进入循环体就退出了循环。

循环程序不论是先处理后判断,还是先判断后处理,其关键是控制循环的次数。循环次数的控制方法根据实际情况而定:循环次数已知的,可以用计数器来控制;循环次数未知的,可以用某种条件控制。

图3.5 循环程序结构类型(www.xing528.com)

a)设置计数器实现已知循环次数的循环程序。

【例3.28】将首地址为STA的100个外部RAM单元清零。

该例题为循环次数已知(循环100次)的循环程序,设置R0为控制循环的计数器。

程序如下:

START:MOV R0,#64H ;设置计数器初值

MOV DPTR,#STA ;设置地址指针初值

CLR A ;累加器A清零

LOOP:MOVX @DPTR,A ;清外部RAM单元

INC DPTR ;修改地址指针

DJNZ R0,LOOP ;循环控制

SJMP 

b)利用条件转移指令控制循环次数未知的循环程序。

【例3.29】设某以“$”为结束标志的字符串存放在内部RAM以STA为首地址的连续单元中(字符总数不超过256个)。统计该字符串的长度,并存放到内部RAM的LEN单元。

程序如下:

ORG 1000H

MOV R2,#STA ;设置地址指针

MOV B,#00H ;设置计数器

LOOP:MOV A,@R2

CJNE A,“$”,NEXT ;判断是否结束

MOV LEN,B ;存数据结果

SJMP DONE

NEXT:INC B ;修改计数器

INC R2 ;修改地址指针,准备下一次循环

SJMP LOOP

DONE:END

4.子程序调用设计

在实际程序编制中,往往会多次进行一些相同的计算或操作,如乘除运算、数码转换、延时等等。如果每次都重新编制一段程序,不仅麻烦,而且浪费存储空间。因此,对于一些常用的程序段,可将它们从程序中独立出来,以便由其它程序随时调用。这种独立的有一定功能的程序称为子程序。调用子程序的源程序称为主程序。

当主程序在运行中需要用子程序时,只要执行调用子程序的指令,使程序转到子程序。子程序执行完毕,依靠最后一条指令——返回指令自动返回主程序,继续其后的操作。在MCS-51指令系统中,提供了两条调用子程序指令ACALL、LCALL以及一条返回主程序的指令RET。

一个子程序在其运行过程中,还可以调用其它的子程序,这称为子程序嵌套。MCS-51对子程序嵌套的层数没有限制,但要为堆栈容量所允许。在编制子程序时,要注意以下几点:

(1)子程序的首地址必须要用标号,此标号也就是该子程序的名称。子程序的最后一定要设置一条返回指令。

(2)尽可能编成浮动地址程序,使用相对转移而不用绝对转移指令,以便于存放在存储区的任意位置。

(3)为了便于使用,每个子程序要有使用说明。其内容包括:

①子程序功能的简要说明。

②入口条件。就是指运行该子程序所需要的一些参数及其存放处。

③出口条件。这是指该子程序运行完毕后给出的结果及其存放处。

④所占用的寄存器和存储单元。

用户在调用子程序时,要注意以下两个问题:

(1)子程序的入口条件和出口条件。主程序要根据子程序的入口条件提供所需的数据,放到指定的寄存器或存储单元;根据出口条件取得该子程序的运行结果。

(2)现场保护。主程序在调用子程序时,虽已对断点作了保护,但对子程序中所用到的寄存器的内容未作保护。因此,对于在主程序和子程序中都要用到的那些寄存器,在转向子程序之前的主程序中或在子程序的起始部分,应将其内容压入堆栈,在子程序返回时再恢复。

【例3.30】单字节二进制数转换为BCD码子程序SBTOD。

功能:将单字节二进制数转换为三位BCD码。

入口:R2中存放要转换的二进制数。

出口:(R0)给出百位BCD码的存放地址。(R0)+1给出十位和个位BCD码的存放地址,高半字节放十位,低半字节放个位。

占用寄存器:A,B,R0,R2。

程序如下:

SBTOD:MOV A,R2 ;取数

MOV B,#64H

DIV AB ;除以100后,A中为百位数

MOV @R0,A ;存入(R0)单元

MOV A,#0AH

XCH A,B ;余数B送A

DIV A,B ;除以10,得十位和个位

SWAP A ;十位数放于高半字节

ADD A,B ;个位数放于低半字节

INC R0

MOV @R0,A ;十位、个位存入(R0)+1单元

RET

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈