您好,欢迎访问三七文档
当前位置:首页 > 机械/制造/汽车 > 机械/模具设计 > 第6章MCS-51单片机应用教程
第6章程序设计集锦6.1循环程序6.2查表程序6.3分支程序6.4常用子程序集6.5小结习题本章从程序结构及应用出发,通过介绍汇编语言典型程序设计的实例,使读者进一步理解和掌握MCS-51单片机的指令系统,并熟练掌握程序设计的方法和技巧。通过对本章的学习,读者应具备以下能力:熟练掌握循环程序、分支程序和查表程序的设计方法掌握定点数、浮点数数据格式及其运算程序的设计方法掌握数制和码制转换程序的设计方法本章学习目标循环程序是一段可以反复执行的程序。在程序设计时,如果遇到需要反复执行的某种操作,可以使用循环程序结构。6.1循环程序循环程序一般包括以下4部分:(1)循环初始化把初值参数赋给控制变量。例如,给循环体中的计数器和各工作寄存器设置初值,其中循环计数器用于控制循环次数。(2)循环处理是循环程序重复执行的部分。(3)循环修改一般由控制变量增1(或减1)计数实现。(4)循环控制根据循环结束条件,判断循环是否结束。延时程序在单片机控制中用途很广,实践中常常先编写出典型延时子程序以供随时调用。典型延时子程序可取100μs、1ms、100ms、1s等。6.1.1延时程序例6-1延时1ms子程序。当使用6MHz晶振时,一个机器周期为Tm=2μs。方法1:指令DJNZ的指令周期为2个Tm,即4μs,当循环执行250次时,4μs×250=1000μs=1ms。参考程序如下:YS10:MOVR7,#250;循环计数器赋初值L1:DJNZR7,L1;循环处理及循环控制RET;子程序返回方法2:乘法指令MUL指令周期为4个Tm,即8μs,执行2次MUL需16μs,执行1次DINZ需4μs,共循环50次。(16μs+4μs)×50=1000μs=1ms。参考程序如下:YS11:MOVR7,#50;1TmL1:MULABMULABDJNZR7,L1;循环体10TmRET;2Tm以上延时时间没有考虑循环体外指令的执行时间。实际延时时间为1000μs+6μs=1006μs,要实现精确延时时间1ms,程序需要进行如下修改(方法1):YS10:MOVR7,#124;循环计数器赋初值L1:NOPNOP;空操作1TmDJNZR7,L1;循环体内4TmNOPRET实际延时时间为8μs×124+8μs=1000μs=1ms例6-2延时100ms子程序。调99次延时1ms子程序YS10。参考程序如下:YS100:MOVR6,#99;1TmL100:LCALLYS10;2TmNOP;1TmDJNZR6,L100;2TmNOP;1TmNOP;1TmRET;2Tm实际延时时间为1000μs×99+10μs×99+10μs=100ms如果一个循环程序中包含了其他循环程序,则称该程序为多重循环程序。例6-3延时1s子程序。使用12MHz时,一个机器周期为Tm=1μs。采用三重循环程序结构。执行内循环需10μs,三重循环延时10μs×250×200μs×2=106μs=1s参考程序如下:YS1:MOVR4,#2;外层循环计数器L0:MOVR3,#200;中层循环计数器L1:MOVR2,#250;内层循环计数器L2:MULAB;4TmMULAB;内循环体DJNZR2,L2;2TmDJNZR3,L1DJNZR4,L0RET考虑到内循环体外指令的执行时间,实际延时时间为(从第一条指令到最后一条指令)(1+1×2+1×200+10×250×200×2+2×200+2×2+2)μs=1000609μs≈1s数据排序就是对给定对象中的各数据元素按指定的顺序进行排列的过程。在日常生活中经常遇到排序问题,本节介绍比较常用的排序方法。6.1.2数据排序程序1.插入排序法人们在玩扑克牌时,每抓一张牌,就会按花色和大小把它插到手中已有牌中的某个适当位置,使手中的牌始终保持有序状态,这种排序方法就是插入排序。例6-4将10个单字节无符号数升序排序,排序前后的数据均置于内部RAM的50H~59H单元内。(1)题目分析采用插入排序法。待排序数据N=10,需要排序处理N-1=9次。外循环9次。第一个数据不用排序,从第二个数据开始,每取一个数据都要和已经排序的数据进行比较,然后确定位置插入。已经排序的数据个数为X,所以内循环比较次数为X。(2)硬件资源分配:内部RAM的50H~59H:排序前后数据存放区B:保存待排序元素的数值R0:待排序数据的地址R1:已经排序区域的最后一个元素的地址R2:需要继续排序处理次数R3:已排序数据个数R4:本次比较次数上限(3)程序流程图如图6-1所示。图6-1插入排序法流程图(4)参考程序DATEQU50H;待排序数据区首址NEQU10;待排序数据元素个数CRPX:MOVR3,#1;默认第一个元素已经排序MOVR2,#N-1;需要继续排序处理的元素为N-1个LOOP:MOVA,R3;取当前已经排序的元素个数MOVR4,A;作为本次比较次数的上限ADDA,#DAT;加上数据区首址MOVR0,A;得到待排序元素的地址DECA;前面一个地址MOVR1,A;是已经排序区域的最后一个元素的地址MOVB,@R0;保存待排序元素的数值LOOP1:MOVA,@R1;取一个已经排序的数据元素SETBCSUBBA,B;与待插入的排序元素比较JCLOOP2;不大于待插入的排序元素,不必交换MOVA,@R1;大于待插入的排序元素,读取其数值MOV@R0,A;数据交换DECR0;调整指针,准备继续比较DECR1DJNZR4,LOOP1;处理完全部已经排序的元素LOOP2:MOV@R0,B;将待排序的元素插到空出的位置INCR3;已经排序的元素个数增加一个DJNZR2,LOOP;处理完N-1个数据元素RET;全部排序完毕2.选择排序法先确定位置,然后再寻找应该占有这个位置的对象,这就是选择排序算法。假设要将N个无序数据按增序进行排序,首先确定第一个位置(地址),然后寻找数据对象,在N个无序数据中找到最小数据,放在第一个位置。假设最小值占有第k个位置,则将它搬到第一个位置上,然后将原来占有第一个位置的数据元素存放到空出来的第k个位置上,即和应该占有这个位置的元素交换位置。最后一个数据是经过N-1次选择后剩下的数据,肯定是全部数据中的最大值,理所当然占有最后一个位置。选择和交换的过程见表6-1。(见书84页)选择排序算法主要是进行最小值的选择,这是通过一系列的比较实现的,不需要进行位置移动,故在数据元素的结构比较大(多字节)的情况下具有较高的效率。例6-5上题采用选择排序法。(1)题目分析从50H单元开始进行比较,第一个循环比较9次,选择出最小值,存入50H;第二个循环比较8次,选择出次最小值,存入51H;依此类推,共需要进行9个循环。(2)硬件资源分配:内部RAM的50H~59H:排序前后数据存放区B:保存本轮比较最小值R0:本次最小值存放地址R1:与本次最小值存放地址相邻的地址R2:排序处理的次数,即外循环次数R3:一个内循环中最小值所在地址R4:本次比较次数,即内循环次数(3)程序流程图如图6-2所示。图6-2选择排序法流程图(4)参考程序DATEQU50H;待排序数据区首址NEQU10;待排序数据元素个数XZPX:MOVR0,#DAT;从第一个位置开始MOVR2,#N-l;需要处理的元素为N-1LOOP:MOVB,@R0;取当前位置元素作为最小值的初始值MOVA,R0MOVR3,A;取当前位置作为最小值的位置INCAMOVR1,A;取下一个位置作为比较的开始MOVA,R2MOVR4,A;控制比较次数LOOP1:MOVA,@R1;取一个数据元素CLRCSUBBA,B;与当前最小值比较JNCLOOP2;不小于当前最小值MOVB,@Rl;保存新的最小值MOVA,R1MOVR3,A;保存新的最小值的地址LOOP2:INCR1;调整指针DJNZR4,LOOPl;比较完全部未排序元素MOVA,R3MOVR1,A;取当前最小值的地址MOVA,@R1;将当前最小值和指定位置的数据元素进行交换XCHA,@R0XCHA,@R1INCR0;处理下一个位置DJNZR2,LOOP;处理完前N-1个位置RET3.冒泡排序法在选择排序中利用了交换操作来达到排序目的,N个数据最多进行N-1次交换,但每次交换前要进行大量的比较操作来确定交换对象,比较的次数远大于交换的次数,工作量较大。当数据规模较小时,采用冒泡排序法将具有较高的效率。冒泡排序法把一批数据想像成纵向排列,自下而上比较相邻的两个数据元素,如果这两个数据元素的大小顺序符合要求,则保持原样,否则交换它们的位置。这样比较一轮后,最小的数据元素就像气泡一样浮到最顶上,故称冒泡算法。实际编程设计时,每一轮操作都从数据区的首地址开始,向末端推进。N个数据元素一般要进行N-1轮次比较、交换排序。表6-2表示冒泡排序法的执行过程。(见书86页)假定原始数据为具有6个数据元素的无序数列,从最上面开始进行相邻数据元素的比较,大的数据放上面,小的数据放下面。第一轮操作,6个数据进行6-1=5次比较,最大数据69“沉淀”到最下面(55H单元)。第二轮操作69不参加,5个数据需比较6-2=4次,5个数据中的最大值24“沉淀”到54H单元。本例中,经过三轮操作就已完成排序,无需进行第四轮和第五轮排序操作。为此应设立一个标志位,每轮开始时标志位清0,在操作过程中出现位置交换,标志位置1,每轮结束时若标志位为0,则说明数据已经有序,可以提前结束排序,从而提高了效率。例6-6将例6-4中的数据采用冒泡排序法排序。(1)硬件资源分配:内部RAM的50H~59H:排序前后数据存放区R0:数据区地址指针R2:本轮比较次数,即内循环次数R3:暂存待比较数据R4:比较轮次数,即外循环次数F0:数据交换标志(2)程序流程图如图6-3所示。图6-3冒泡排序法流程图(3)参考程序DATEQU50H;排序数据首址NDATA10;数据个数MPPX:MOVR4,#N;第一轮冒泡操作中的比较次数SRT1:CLRF0;在第一轮冒泡操作前,初始化交换标志DECR4MOVA,R4;取上一轮冒泡操作中比较次数MOVR2,A;控制本轮比较次数JZSRT4;比较次数为零,排序结束MOVR0,#DAT;取数据区首址SRT2:MOVA,@R0;读取一个数据MOVR3,A;暂存INCR0;指向后一个数据MOVA,@R0;读取CLRCSUBBA,R3;和前一个数据比较JNCSRT3;不小于前一个数据,符合增序要求SETBF0;小于前一个数据,设置交换标志MOVA,R3;交换两个数据(冒泡)XCHA,@R0DECR0;指向前一个数据XCHA,@R0INCR0;恢复指针,指向后一个数据SRT3:DJNZR2,SRT2;处理完这一轮JBF0,SRTl;本轮若有交换操作,则需进行下一轮操作SRT4:RET4.几种排序方法比较在插入排序、选择排序和冒泡排序3种算法中,如果数据元素规模较大(多字节)时,应采用选择排序算法;如果数据元素为单字节时,可采用插入排序或冒泡排序算法;如果数据元素初始状态基本有序,采用冒泡算法较为有效。单片机应用系统中,查表程序是一种常见的程序。查表程序实现查表算法,该方法把事先计算或实验数据按一定顺序编成表格,存于程序存储器内,然后根据输入参数值,从表中取得结果。查表程序可完成数据补偿、计算和转换等功能。用于查表的专用指令有两条:MOVCA,@A+DPTRMOVCA,@A+PC6.2查表程序1.用DPTR作为基址的查表操作的3个步骤(1)先把数据表格表头地址存入DPTR。(2)然后把要查得的数在表中相对于表头地址的偏移量送入累加器A。(3)最后执行MOVCA,@A+DPTR,把查表结果送累加器A。2.用PC作为基址的查表操作的3个步骤(1)用传送指令把所查数据的项数送入累加器A。(2)使用ADDA,#data指令对累加器A进行修正,data值由下式确定:PC当前值+data=数据表头地址其中data值等于查表指令和数据表格之间的字节数。(3)用指令MOVCA,@A+PC完成查表。例6-7设有一个循回检测报警装置,需要对1
本文标题:第6章MCS-51单片机应用教程
链接地址:https://www.777doc.com/doc-3306131 .html