单片机基础(第3版)——第4章_第1页
单片机基础(第3版)——第4章_第2页
单片机基础(第3版)——第4章_第3页
单片机基础(第3版)——第4章_第4页
单片机基础(第3版)——第4章_第5页
已阅读5页,还剩77页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

MCS-51系列单片机的程序设计,第四章,交叉汇编语言MASM51,单片机汇编语言程序设计方法及技巧,了解交叉汇编语言MASM51的特点,掌握顺序程序、分支程序、循环程序、查表程序、子程序的基本设计方法和技巧,掌握汇编语言程序设计的一般步骤,4.1交叉汇编语言MASM51,汇编语言源程序是由汇编指令和伪指令组成的文件,其扩展名为“ASM”。,程序设计就是用计算机所能接受的语言把解决问题的步骤描述出来,也就是编制程序。常用的MCS-51程序设计语言有MCS-51汇编语言和MBASIC51、C51、PLM51等高级语言。,编程汇编语言编程时大多在PC中用文本编辑器(如EDIT)编写,目前几乎所有的单片机仿真器所配的软件均有文本编辑器。如南京伟福WAVE6000forWindows、KeilVision2等软件。只要运行软件后进入程序编辑状态即可编写程序。,汇编汇编语言必须经过机器汇编或人工汇编才能得到相应的机器程序,即目标程序,以供单片机识别和执行。由于人工汇编工作量大,容易出错,现已不用。机器汇编一般是在PC上利用一些汇编软件进行。目前几乎所有的单片机仿真器配的开发软件都有汇编程序,在源程序编写完成后使用汇编功能菜单即可进行对源程序汇编。,在汇编时若发现源程序有语法错误或跳转超出范围等情况,系统会将错误显示给用户。用户在改正错误后,需再对源程序进行汇编,直到源程序完全没有语法错误。此时汇编程序会生成与其对应的目标文件。一般情况下是生成HEX(十六进制)和BIN(二进制)文件。没有语法错误并不等于程序开发成功,一般来说还要对程序进一步调试、修改,运行无误后,程序才算最终完成。这时才可将目标文件写入到程序存储器中。,1)人工汇编人工汇编是通过人工查出源程序中所有汇编指令的机器码,并依次将机器码输入单片机中,使之成为单片机能直接执行的目标程序。,2)机器汇编机器汇编是指在计算机上通过汇编程序对源程序进行汇编,即从源程序到目标程序的转换过程是由计算机上的汇编程序自动完成的。,3)交叉汇编是指用一种计算机上的汇编程序去汇编另一种计算机的源程序,为另一种计算机产生目标程序。,单片机MCS-51汇编语言程序设计步骤:1分析问题2确定算法3设计程序流程图4分配内存单元5编写汇编语言源程序6调试程序,4.2程序设计方法及技巧,4.2.1顺序程序设计,顺序程序在单片机中是最简单的程序片段,在顺序程序中没有判断、没有分支。只是顺序向下执行。如单片机开始时对内部或外部资源初始化的程序就是一个典型的顺序程序。,分析:应注意片内和片外的寻址指令不同,ORG1000HMOVR0,#68HMOVA,R0;片内RAM104单元内容送累加器MOVDPTR,#0104HMOVXDPTR,A;完成片内RAM104单元内容送片;外104H单元中INCR0MOVA,R0;片内RAM105单元内容送累加器INCDPTRMOVXDPTR,A;完成片内RAM105单元内容送片;外105H单元中SJMP$;等待END;结束,4.2.2分支程序设计,分支程序就是在程序执行过程中要判断某些条件,当条件成立后程序转移到不同的功能处运行。在MCS-51单片机中条件转移指令都可以用在分支程序中。,测试条件符合转移,如:JNBTI,$;TI是串行控制寄存器;SCON的第一位CLRTI,比较不相等转移,如:CJNER0,#2FH,LOOPRET减1不为0转移,如:DJNZR7,LOOPRET根据某些单元或寄存器的内容转移,如:JMPA+DPTR,1.简单分支程序,图4.1简单分支程序转移,分析:只要将两数进行比较,用比较的结果作为分支转移的条件就很容易地找出其中的大数。,ORG1000HCLRCMOVR0,#FRIST;第一个数地址送R0中MOVA,R0;取第一个数INCR0;R0指向第二个数地址SUBBA,R0;两数比较JCBIG;第二个数大转BIGDECR0;R0指向第一个数地址BIG:MOVSECOND,R0;存大数SJMP$;等待END;结束,参考程序,2)多路分支程序(散转程序),图4.2多路分支程序转移,1)把AJMP或LJMP指令组成一个分支程序的转移表,表的首地址放入DPTR中;2)调整后的出口信息放入累加器A中;3)执行JMPA+DPTR转向对应的分支程序。,可通过间接转移指令JMPA+DPTR和无条件转移指令中的AJMP或LJMP指令来实现多路分支转移:,例4.3,已知R0中存放有一数字关键码,要求根据码值的不同,分别转向对应的码值程序段去执行。即当(R0)=K时,便执行CODEK程序。,ORG1000HMOVDPTR,#TAB;表首址送DPTRMOVA,R0;取数字关键码ADDA,R0;每条AJMP指令占用两个字;节,将出口信息乘2JNCLESS;关键码小于128转LESSINCDPHLESS:JMPA+DPTRTAB:AJMPCODE0;关键码为0,转CODE0执行AJMPCODE1;关键码为1,转CODE1执行AJMPCODE255;关键码为255,转CODE255;执行SJMP$;等待END;结束,参考程序,AJMP指令的转移范围不超出所在的2KB字节区间,如各小段程序较长,在2KB字节内无法全部容纳,上面的程序应该怎样修改?,思考,1)循环初始化设置循环的初始状态,位于循环程序的开头位置2)循环处理循环程序的主体部分,是通过反复执行来完成数据的具体处理,它位于循环体内。,4.2.3循环程序设计,循环程序由4部分组成:,3)循环控制也在循环体内,是用于控制循环的继续与否。4)循环结束通常位于循环体后,是用来存放循环处理的最终结果及恢复各寄存器与工作单元的原始值。,设MCS-51单片机内部RAM从40H开始的连续16个单元中,每个单元中分别存放有单字节的带符号数。要求将其中的正数存入50H开始的连续单元中,负数存入60H开始的连续单元中,并将正数、负数和零的个数分别存入70H、71H、72H单元中。,例4.4,1)带符号数的最高位为符号位,可通过最高位判断正负:“0”表示正数,“1”表示负数。2)程序中需要从40H单元开始取源数,存正数和负数,故需要三个地址指针来指向对应的内存单元;设对应的地址指针分别为R0、R1和R2,由于R2不能用间接寻址方式,故R2需要同R1或R0进行交换后,才能进行负数的存放。,分析,参考程序:ORG1000HCLRAMOV70H,A;存放正数的个数单元清0MOV71H,A;存放负数的个数单元清0MOV72H,A;存放零的个数单元清0MOVR3,#10H;设循环计数器初值MOVR0,#40H;设源数地址指针MOVR1,#50H;设正数地址指针MOVR2,#60H;设负数地址指针,LOOP:MOVA,R0;取源数JZZERO;源数为0,转ZER0JNBACC.7,POSI;源数为正,转POSIINC71H;负数个数加1MOVR4,A;暂存原数MOVA,R2XCHA,R1;R1与R2中的内容交换XCHA,R4MOVR1,A;存负数XCHA,R4XCHA,R1;R1与R2中的内容交换INCR2;调整负数地址指针SJMPLOOP1;转循坏控制,POSI:INC70H;正数个数加1MOVR1,A;存正数INCR1;调整正数地址指针SJMPLOOP1ZERO:INC72H;零的个数加1LOOP1:INCR0;调整源数地址指针DJNZR3,LOOP;未送完,则继续SJMP$;等待END;结束,查表就是把事先计算或测得的数据按照一定的顺序编制成表格存放在存储器中,然后根据输入的数据,从表格中查出所需的结果。,4.2.4查表程序设计,片内RAM的EGA单元中有一个大写的英文字母,要求将此字母在英文字母表中的位置送入片内的COUNT单元中,如EGA单元中字母为I时,则COUNT单元中需送入数字9。,例4.6,第一条查表指令采用DPTR存放数据表格的地址,查表过程简单。查表前先把数据表格起始地址存入DPTR,然后把所查表的索引值送入累加器A中,最后使用“MOVCA,A+DPTR”完成查表。第二条查表指令要复杂,其步骤分如下三步:1、使用传送指令把所查数据的索引值送入累加器A2、用“ADDA,#data”指令对累加器A进行修正。data值由PC+data=数据表首地址确定。PC是“MOVCA,A+PC”的下一条指令的地址。data值实际等于查表指令和数据表格之间的字节数3、采用查表指令“MOVCA,A+PC”完成查表。,如果将26个英文字母按照顺序编成一个表,通过查表法得到一个字母与EGA单元中的字母比较,若不相等再查,同时记录查表的次数。查完后,将记录次数送COUNT单元。,分析,参考程序ORG1000HEGAEQU50HCOUNTEQU60HMOVCOUNT,#00HMOVA,#16;调整地址LOOP:PUSHAMOVCA,A+PC;查表CJNEA,EGA,NF;所查字母与EGA中字母比较*3SJMPLAST;相等转LAST*2NF:POPA;*2INCA;调整地址*1INCCOUNT;记数值加1*2SJMPLOOP;继续查*2LAST:INCCOUNT;记数值加1*2SJMP$;等待*2ALPT:DBA,B,Y,ZEND;结束,求y=n!(n=0,1,9),已知n的值在片内NUM单元中,y值用BCD码表示且存放在片内GETY开始的单元中。,例4.6,分析:将函数值列成表,采用查表法求y=n!当n=9时,y=362880H,需要三个单元存放结果。设每个n对应的y值都用3个单元来存放,则y值在表格中的首地址的计算公式为:y地址=函数表首址+n*3,参考程序ORG1000HNUMEQU50HGETYEQU60HMOVR1,#03HMOVR0,#GETYMOVA,NUM;取n值MOVB,#03HMULAB;n*3MOVR2,A;暂存MOVDPTR,#TAB;表的首地址送DPTR中,LOOP:MOVCA,A+DPTR;查表MOVR0,A;存结果INCR0;调整存放结果地址指针INCDPTR;修正表地址指针MOVA,R2;恢复n*3DJNZR1,LOOP;未查完,继续SJMP$;等待END;结束TAB:DB01H,00H,00H,01H,00H,00HDB02H,00H,00H,06H,00H,00HDB24H,00H,00H,20H,01H,00HDB20H,07H,00H,40H,50H,00HDB20H,03H,04H,80H,28H,36H,4.2.5子程序设计,实际问题中,常遇见在一个程序中有许多相同的运算或操作,通常把这种多次使用的程序段按一定结构编好,存放在内存中,需要时,程序就去调用这些独立的程序段。这种可以被反复调用的程序段就是子程序;调用子程序的程序成为主程序。分为调用和返回两个过程。子程序在功能上应具有通用性,在结构上应具有独立性。它在结构上与一般程序的主要区别:子程序末尾有一条子程序返回指令RET,其功能是执行完子程序后通过堆栈内的断点地址弹出至PC返回到主程序中去。,编写子程序时应注意:a.子程序的第一条指令之前必须有标号;b.子程序中需要保护现场;c.主程序和子程序之间的参数传递。,1)数码转换子程序,例4.7二进制码转换为ASCII码,二进制数与ASCII码的对应关系:四位二进制ASCII0000(0)30H0001(1)31H1001(9)39H1010(A)41H1111(F)46H,ORG1000BTOASC:PUSHA;保护现场PUSHPSW;保护现场MOVA,R0ANLA,#0FH;取低四位二进制数MOVR0,A;暂存CLRCSUBBA,#0AH;与10比较MOVA,R0;恢复四位二进制数JCLOOP;小于10转LOOPADDA,#07H;大于10先加07HLOOP:ADDA,#30H;加30HMOVR0,A;存结果POPPSW;恢复现场POPA;恢复现场RET;返回,主程序调用子程序指令:LCALLadd16ACALLadd11子程序返回指令:RET,主程序在调用子程序时要注意:1.在主程序中要安排相应指令,满足子程序的入口条件,提供子程序的入口数据。2.在主程序中不希望被子程序更改内容的寄存器,也可在调用前在主程序中安排压栈指令保护现场,子程序返回后再安排弹出指令恢复现场。3.在主程序中安排相应指令,处理子程序提供的出口数据。4.在需要保护现场的诚信中,要正确地设置堆栈指针。,已知片内BLOCKB单元开始处有一数据块,块长在R2中,在此数据块的每个单元中存放有一个BCD码,要求将每个BCD码转换为ASCAII码,并存放在片内BLOCKA开始的连续单元中。,例4.8BCD码转换为ASCAII码,将一位BCD码转换为ASCAII码的子程序:TRANS:MOVA,R0;取BCD码ADDA,#30HMOVR1,A;送ASCAII码INCR0INCR1RET;返回,分析:将一位BCD码转换为相应的ASCAII码只需加上30H即可。,主程序:ORG1000HMOVR2,#LMOVR0,#BLOCKB;设BCD码的地址指针MOVR1,#BLOCKA;设ASCAII的地址指针LOOP:ACALLTRANS;调用TRANS子程序DJNZR2,LOOP;未转换完,继续SJMP$;等待END;结束,设片内40H单元中有一组合的BCD码,要求将其转换为二进制数存回原处。分析:1)组合的BCD码为两位十进制数,需将十位数和个位数分开处理。2)十位数转换时只要乘以10,取乘积低四位就能将其转换为相应的二进制数,然后再将个位数直接加到转换后的十位数上就可完成整个数的转换。,例4.9BCD码转换为二进制数,参考程序ORG1000BCDTOB:MOVA,40HANLA,#F0H;取十位数SWAPA;将十位数换到低4位JZDONE;十位数为0,返回MOVB,#0AH;取乘数MULAB;A中高半字节乘10MOVR3,A;取乘积的低四位MOVA,40HANLA,#0FH;取个位数ADDA,R3;与十位相加MOV40H,A;转换完,存结果DONE:RET,已知片内RAMADR1开始的单元依次从低位到高位存放有L个字节的无符号数,片外RAMADR2开始的单元也依次从低位到高位存放有L个字节的无符号数。请编一个加法程序,将他们的和存放在ADR1开始的连续单元中。,2)算术运算子程序,例4.11多字节无符号数相加,开始,#ADR1(R0)#ADR2(DPRTR)#L(R2)C清零,(R0)+(DPTR)(A),(A)(R0),(R0)+1(R0)(R1)+1(R1)(R2)-1(R2),(R2)=0?,Y,N,出口,初始化设初值,循环体,工作部分,修改循环体参数,判别,程序流程框图:,参考程序,ORG1000HNSADD:MOVR0,#ADDR1;设被加数的地址指针MOVDPTR,#ADDR2;设加数的地址指针MOVR2,#L;设循环计数器初值CLRCLOOP:MOVXA,DPTR;取加数ADDCA,R0;两数相加MOVR0,A;存和INCR0;调整被加数地址指针INCDPTR;调整加数地址指针DJNZR2,LOOP;未加完,继续RET;返回,已知被乘数和乘数分别为双字节的无符号数,被乘数的高字节和低字节分别存放在R7和R6中,乘数的高字节和低字节分别存放在R5和R4中。要求乘积存放在片内RAM以ADR开始的单元中。分析:由于只有单字节乘法指令,双字节的乘法需要分作4次乘法运算才能实现。,例4.15两双字节无符号数相乘,ORG1000HMUL1:MOV40H,#00H;统计bdH+adL+bcL;的进位单元清0MOV41H,#00H;统计adH+bcH+acL;的进位单元清0MOVR0,#50H;积的首地址送R0中MOVA,R6;b送AMOVB,R4;d送BMULAB;bdMOVR0,A;bdL送50H单元中MOVR1,B;bdH送R1中,参考程序,MOVA,R7;a送AMOVB,R4;d送BMULAB;adMOVR2,A;adL送R2中MOVR3,B;adH送R3中MOVA,R6;b送AMOVB,R5;c送BMULAB;bcADDA,R2;bcL+adLJNCNEXT1;无进位转NEXT1INC40H;统计进位NEXT1:ADDA,R1;bcL+adL+bdHJNCNEXT2;无进位转NEXT2INC40H;统计进位NEXT2:INCR0MOVR0,A;存bcL+adL+bdH结果于51H单元中,MOVR1,B;bcH存R1中MOVA,R7;a送AMOVB,R5;c送BMULAB;acADDA,40H;acL加低位进位JNCNEXT3;无进位转NEXT3INC41H;统计进位NEXT3:ADDA,R1;acL+bcHJNCNEXT4;无进位转NEXT4INC41H;统计acL+bcH进位NEXT4:ADDA,R3;acL+bcH+adHINCR0MOVR0,A;存acL+bcH+adH的结果于52H单元中MOVA,BADDCA,41H;acH加低位进位INCR0MOVR0,A;积最高位存53H单元中RET;返回,R1,R3,例16:按下面公式编写程序,x为无符号数,存在20h单元y存放在21h单元。,ORG0030HMOVA,20HCJNEA,#21H,LOOP1LOOP1:JCNEXT1CJNEA,#40H,LOOP2LOOP2:JNCNEXT2MOVB,#2MULABAJMPNEXT2NEXT1:CPLANEXT2:MOV21H,AEND最终结果存在21h中,1.用硬件电路实现2.定时器实现3.软件延时,定时(或延时)方法:,3)延时程序,软件延时:利用计算机执行程序耗用的时间来实现延时,又称“延时程序”。,例:设计一延时程序,延时时间为1ms。若MCS51单片机系统采用12M晶振,则Tcy1us,内循环一次需要4个机器周期,共循环18H24次延时时间:1(14242)102Tcy993us1ms延时程序常设计为子程序,以便频繁调用。,4.3单片机汇编程序结构一个完整单片机的程序由多个功能模块组成,其中主程序是必须的,其他功能子程序则根据实际的系统情况可有可无,而子程序由主程序调用,中断服务程序则根据中断条件决定是否执行。,4.3.1程序总体结构MCS-51单片机的汇编程序由主程序、若干个子程序、中断服务程序等组成。由于MCS-51单片机复位后PC=0000H,也就是程序从程序存储器的0000H开始执行,由于MCS-51单片机程序存储器的0003H、000BH、0013H、001BH、0023H分别是外部中断0、定时器0、外部中断1、定时器1、串行口的中断入口地址,所以主程序开始的地址一般安排在0030H之后的程序存储器中。一般在程序存储器的0000H开始放一条无条件转移指令(AJMP、LJMP、SJMP)转到主程序的开始处。如果要使用某些中断,则在相应的中断入口地址也放一条无条件转移指令,多数情况下用LJMP指令,这是因为使用LJMP指令可使中断服务程序在单片机程序存储器中的任意位置编写。图4.3是MCS-51单片机的程序总体结构图。,图4.3MCS-51单片机程序总体结构,在MCS-51单片机汇编程序中,主程序是必须有的,而子程序及中断服务程序则根据具体系统可有可无。如果系统功能比较简单,则不需要子程序,一些具体功能在主程序中就可实现。对于中断服务程序也不是全用甚至一个也没有,在不用的中断入口处可什么都不写,同时也要在程序中将对应的中断关闭。值得注意的是在图4.3中,中断服务程序和功能子程序与主程序不是并列的,一般中断服务程序与功能子程序是依次安排在主程序的后面,如果有常数表的话,可将表安排在所有程序的后面。以下是一个实际汇编程序的结构程序片段。,ORG0000HAJMPMAIN;转主程序ORG0003HLJMPINT00ORG000BHLJMPT000ORG0030HMAIN:MOVTMOD,#01H;主程序初始化MOVTH0,#03HMOVTL0,#0F8H,MAIN1:LJMPKEY00;调键盘程序LJMPDISP;调显示程序AJMPMAIN1;主程序循环KEY00:;键盘程序RETDISP:;显示程序RETINT00:;外部中断服务程序RETIT000:;定时器0中断服务程序RETITAB:DB3FH,06H,5BH,4FH,66H;显示字模表END;汇编结束,4.3.2主程序MCS-51单片机的主程序一般是由一些顺序程序组成的,主程序的结构与单片机应用系统及编程者的习惯有关。不同的应用系统其主程序的结构是不同的,编程者的不同习惯也决定着主程序的结构。但无论哪一种习惯,一般在进入主程序后都要根据具体要求对所用的可编程的硬件资源进行初始化。如MCS-51单片机内部的中断、定时器、串行口以及一些RAM单元等。如有外部扩展可编程芯片也要对其进行初始化,使其工作在需要的工作状态下。,图4.4根据中断处理的主程序,图4.4是根据中断处理的标志决定执行哪一个功能模块。这种结构的主程序是在初始化后等待定时中断服务程序中处理的标志。如定时器0为10ms中断一次,每次将一个单元的内容加1,如有5个功能模块,单元内容由0加到4再回到0,而主程序可根据此单元的内容调用某一个功能模块。,图4.5是将各功能模块由主程序循环调用的一种结构。这种结构是在主程序初始化后根据系统的要求依次调用各子程序,最后一个子程序执行完后再转回调用第一个子程序。,图4.5在主程序中循环调用各子程序,中断方式与循环方式的主程序比较:中断方式比较复杂,而循环调用方式则相对来说要简单得多,并且程序调试时也相对容易。但由于定时中断方式各程序执行的时间间隔固定,而循环调用方式的时间由各子程序的运行时间决定。对于定时中断方式要注意功能模块程序的执行时间不能超过定时时间。无论是定时调用还是顺序调用方式,由于在主程序后大多会有一些子程序、中断服务程序、数据表等,主程序必须是一个无限循环程序,即主程序要在自己的程序内循环,不能一直执行下去,否则一旦不是在调用状态下进入其他程序,整个程序系统就会紊乱。,4.3.3子程序子程序是在MCS-51单片机系统中使用最多的公用程序段,它可被主程序或其他子程序调用,一般情况下不主张子程序调用自己(递归)。因单片机的内部RAM太小,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论