1、单片机程序设计3、1汇编语言程序设计方法汇编语言程序设计方法汇编语言程序设计同高级语言程序设计一样,就是有章可循得,只要按照一定得方法步骤去做,程序设计就会变成一件轻松愉快得事情,设计得程序也会规范、清晰、易读、易懂。使用汇编语言设计程序大致上可分为以下几个步骤。1、分析题意,明确要求。2、确定算法。3、画程序流程图。4、分配内存工作单元。5、编写源程序。6、程序优化。7、上机调试。3、2 顺序程序设计【例】程序初始化。初始化就就是为变量、寄存器、存储单元赋一初值,就是最简单、最常用得操作。如将R0-R3,P1,30H,40H单元初始化为00H,把R4,R5初始化为0FFH。参考程序如下:OR
2、G 0000H ;PC起始地址 LJMP START;转主程序 ORG 0100H;主程序起始地址START:MOV R0,#00H ;初始化 MOV R1,#00H MOV R2,#00H MOV R3,#00H MOV P1,#00H MOV R4,#0FFH MOV R5,#0FFH MOV 30H,#00H MOV 40H,#00HHERE:SJMP HERE;反复执行该指令,相当于等待 END用立即数比较直观,但用MOV A,#00H,MOV R0,A 指令赋值,效果更好。【例】【例】逻辑运算。逻辑操作就是控制过程中经常使用得,掌握逻辑运算得特点就是提高程序效率得重要途径。在逻辑运算
3、中,进位标标志CY得地位很特殊,它就是逻辑累加器,大多数逻辑操作要通过CY来完成。用程序实现图4-2所示得逻辑电路功能。图3-2 逻辑电路参考程序如下:ORG 0000H LJMP START ORG 0100H MOV P1,#0FFH ;P1口初始化LOOP:MOV C,P1、1 ORL C,P1、2 ;P1、1与P1、2逻辑或运算 CPL C ;取反 ANL C,P1、0 ;C与P1、0逻辑与运算 CPL C MOV 07H,C ;暂存于07H单元中 MOV C,P1、3 ANL C,/P1、4 ;P1、3与P1、4得反逻辑与运算 CPL C ORL C,07H MOV P1、5,C ;
4、把结果在P1、5口输出 SJMP$END3、3 分支程序设计分支程序得主要特点就是程序包含有判断环节,不同得条件对应不同得执行路径。编程得关键任务就是合理选用具有逻辑判断功能得指令。由于选择结构程序得走向不再就是单一得,因此,在程序设计时,应该借助程序框图(判断框)来明确程序得走向,避免犯逻辑错误。一般情况下,每个选择分支均需单独一段程序,并有特定得名字,以便当条件满足时实现转移。1 1、单分支选择结构、单分支选择结构当程序得判断就是二选一时,称为单分支选择结构。通常用条件转移指令实现判断及转移。单分支选择结构有三种典型表现形式。图3-3 单分支选择结构(a)当条件满足时执行分支程序1,否则执
5、行分支程序2。(b)当条件满足时跳过程序段1,从程序段2顺序执行;否则,顺序执行程序段1与程序段2。(c)当条件满足时程序顺序执行程序段2;否则,重复执行程序段1,直到条件满足为止。由于条件转移指令均属相对寻址方式,其相对偏移量rel就是个带符号得8位二进制数,可正可负。因此,它可向高地址方向转移,也可向低地址方向转移。对于第三种形式,可用程序段1重复执行得次数作为判断条件,当重复次数达到某一数值时,停止重复,程序顺序往下执行。这就是分支结构得一种特殊情况,这实际就是循环结构程序。用这种方式可方便实现状态检测。【例】:LOOP:JB P1、1,LOOP单分支程序一般要使用状态标志,应注意标志位
6、得建立。大家学习辛苦了,还是要坚持继续保持安静继续保持安静【例】设a存放在累加器A中,b存放在寄存器B中,若a0,Y=ab;若a0nY=100X=0 n XX0nY=100 X=0 求出Y值,并将Y值放回原处。n X X0n解:设置一个计数器控制循环次数,每处理完一个数据,计数器减1。程序流程如图4-8所示。A=0?YYNNYNA为负数?取数,A(R1)开始结束AXA64HAX+2存数,(R1)A(30H)设置地址指针R1、计数器R0初值R1R1+1;R0R0-1R0=0?图4-8 例4、5得程序流程图返回本节n参考源程序如下:nORG2000H n MOVR0,#10n MOVR1,#30H
7、n START:MOVA,R1;取数n JBACC、7,NEG;若为负数,转NEG n JZZER0;若为零,转ZER0n ADDA,#02H;若为正数,求X+2n AJMPSAVE;转到SAVE,保存数据n ZER0:MOVA,#64H;数据为零,Y=100 nAJMP SAVE;转到SAVE,保存数据nNEG:DECA n CPLA;求XnSAVE:MOVR1,A;保存数据n INCR1;地址指针指向下一个地址n DJNZ R0,START;数据未处理完,继续处理n SJMP;暂停【例】排序程序。设在内部RAM中存一无符号数得数组,其长度为n,起始地址就是30H,要求将它们按从大到小排序,
8、排序后仍存放在原区域中。按“冒泡法”对n个数排序时,可能用不到n-1次循环,排序就结束了。为了提高排序速度,程序中可设一交换标志位,如10H位,每次循环中,若有交换则执行SETB 10H,表明排序未完成;若无交换,则执行CLR 10H,表明排序已经完成。每次循环结束时,测10H位,判断排序就是否结束。参考程序如下:ORG 0000H LJMP BUBBLE ORG 0100HBUBBLE:MOV R0,#30H MOV B,#64H CLR 10H DEC B ;长度计数LOOP:MOV A,R0 ;内循环得入口 MOV 20H,A ;暂存,为交换作准备 INC R0 MOV 21H,R0 C
9、JNE A,21H,BUEU ;若(20H)(21H)转移 BUEU:JNC BUNEXT ;(20H)(21H)转移 MOV A,R0 ;若(20H)(21H)则交换 MOV R0,20H DEC R0 ;使R0退格指向小地址 MOV R0,A INC R0 ;恢复R0指向大地址 SETB 10H ;置交换标志BUNEXT:DJNZ B,LOOP;内循环就是否结束得判断 JB 10H,BUBBLE ;判断标志位为1否?外循环结束得判断 END3、5 子程序设计n在实际应用中,一些特定得运算或操作经常使用,例如多字节得加、减、乘、除处理,代码转换、字符处理等。如果每次遇到这些运算或操作,都重复
10、编写程序,不仅会使程序烦琐冗长,而且也会浪费编程者大量时间。因此经常把这些功能模块按一定结构编写成固定得程序段,存放在内存中,当需要时,调用这些程序段。通常将这种能够完成一定功能、可以被其它程序调用得程序段称为子程序。调用子程序得程序称为主程序或调用程序。调用子程序得过程,称为子程序调用,用ACALL addr11与LCALL addr16两条指令完成。子程序执行完后返回主程序得过程称为子程序返回,用RET指令完成。1 1、在编写子程序时要注意以下几点在编写子程序时要注意以下几点:要给每个子程序赋一个名字。它就是子程序入口地址得符号,便于调用。明确入口参数、出口参数。所谓入口参数,即调用该子程
11、序时应给哪些变量传递数值,放在哪个寄存器或哪个内存单元,通常称为参数传递。出口参数则表明了子程序执行得结果存在何处。例如,调用开平方子程序,计算。在调用子程序之前,必须先将x值送到主程序与子程序得某一交接处N(如累加器A),调用子程序后,子程序从该交接处取得被开方数,并进行开方计算,求出得值。在返回主程序之前,子程序还必须把计算结果送到另一交接处M。这样在返回主程序之后,主程序才可能从交接处M得到得值。注意保护现场与恢复现场。在执行子程序时,可能要使用累加器、PSW或某些工作寄存器,而在调用子程序之前,这些寄存器中可能存放有主程序得中间结果,这些中间结果在主程序中仍然有用,这就要求在子程序使用
12、这些资源之前,要将其中得内容保护起来,即保护现场。当子程序执行完毕,即将返回主程序之前,再将这些内容取出,恢复到原来得寄存器,这一过程称为恢复现场。保护现场通常用堆栈来完成。并在子程序得开始部分使用压栈指令PUSH,把需要保护得寄存器内容压入堆栈。当子程序执行结束,在返回指令RET前边使用弹栈指令POP,把堆栈中保护得内容弹出到原来得寄存器。要注意,由于堆栈操作就是“先入后出”。因此,先压入堆栈得参数应该后弹出,才能保证恢复原来得数据。为了做到子程序有一定得通用性,子程序中得操作对象,尽量用地址或寄存器形式,而不用立即数、绝对地址形式。另外,子程序中如含有转移指令,应尽量用相对转移指令。2、子
13、程序得调用与返回子程序得调用与返回 主程序调用子程序就是通过子程序调用指令LCALL add16与ACALL add11来实现得。前者称为长调用指令,指令得操作数部分给出了子程序得16位入口地址;后者为绝对调用指令,它得操作数提供了子程序得11位入口地位,此地址与程序计数器PC得高5位并在一起,构成16位得调用地址(即子程序入口地址)。它们得功能,首先就是将PC中得当前值(调用指令下一条指令地址,称断点地址)压入堆栈(即保护断点),然后将子程序入口地址送入PC,使程序转入子程序运行。n子程序得返回就是通过返回指令RET实现得。这条指令得功能就是将堆栈中返回地址(即断点)弹出堆栈,送回到PC,使
14、程序返回到主程序断点处继续往下执行。子程序调用过程如图3-8所示图3-8 子程序调用过程 主程序在调用子程序时要注意以下问题。n在主程序中,要安排相应指令来传递子程序得入口参数,即提供子程序得入口数据。n在主程序中,要安排相应得指令,处理子程序提供得出口数据,即操作结果。n在主程序中,不希望被子程序更改内容得寄存器,也可以在调用前由主程序安排压栈指令来保护现场,子程序返回后再安排弹栈指令恢复现场。n在主程序中,要正确地设置堆栈指针。3、子程序嵌套子程序嵌套子程序嵌套就是指在子程序执行过程中,还可以调用另一个子程序。子程序嵌套过程如图3-9所示。图3-9 子程序嵌套过程4、子程序得特性子程序得特
15、性编写子程序应注意以下问题:通用性。为使子程序能适应各种不同程序、不同条件得调用,子程序应具有较好得通用性。可浮动性。可浮动性就是指子程序段可设置在存储器得任何地址区域。假如子程序只能设置在固定得存储器地址段,这在编制主程序时要特别注意存储器地址空间得分配,防止两者重叠。为了能使子程序段浮动,必须在子程序中避免选用绝对转移地址,而应选用相对转移类指令,子程序首地址亦应采用符号地址。可递归与可重入性。子程序能自己调用自己得性质,称为子程序得可递归性,而子程序能同时被多个任务(或多个用户程序)调用得性质,称为子程序得可重入性。这在比较复杂得程序中经常用到。子程序说明文件。对于通用子程序,为便于各种
16、用户选用,要求在子程序编制完成后提供一个说明文件,使用户不必详读源程序,只需阅读说明文件就能了解子程序得功能及应用。【例】求平方。用程序实现 Ca*ab*b。设a、b均小于10,a存在31H单元,b存在32H单元,把C存入33H单元。因本题两次用到平方值,所以在程序中采用把求平方编为子程序得方法。子程序名称:SQR。功能:求X2,通过查平方表来获得。入口参数:某数在A中。出口参数:某数得平方在A中。参考主程序与子程序如下:主程序:ORG 0000HLJMP MAINORG 0100H MAIN:MOV SP,#3FH ;设堆栈指针(调用与返回指令要用到堆栈)MOV A,31H ;取a值LCAL
17、L SQR ;第一次调用,求a2MOV R1,A ;a2 值暂存R1中 MOV A,32H ;取b 值LCALL SQR ;第二次调用,求b2 ADD A,R1 ;完成 a2b2MOV 33H,A ;存结果到33HSJMP$;暂停 子程序:ORG 0200HSQR:ADD A,#01H ;查表位置调整,RET为一字节指令MOVC A,A+PC ;查表取平方值RET ;子程序返回TAB:DB 0,1,4,9,16,25DB 36,49,64,81 END求平方得子程序在此采用得就是查表法,用伪指令DB将09得平方值以表格得形式定义到ROM中。子程序中A之所以要加1,就是因为RET指令占了一个字节
18、。实 践题目:十字路口交通灯 要求:通过单片机得P1口控制实验仪上6个LED按 照交通灯得变化规律循环发光,模拟十字路口交通灯。实验电路如下,L5、L4、L3模拟东西方向交通灯,L2、L1、L0模拟南北方向交通灯。通过一条SETB 指令,可使某一灯亮,通过一条CLR 指令,可使某一灯灭。硬件:画出硬件电路原理图。软件:画出程序流程图,编写源程序。调试:记录调试过程,分析调试结果。n南北方向绿灯亮:东西方向红灯亮n南北方向绿灯闪:东西方向红灯亮n南北方向黄灯亮:东西方向红灯亮n南北方向红灯亮:东西方向绿灯亮n南北方向红灯亮:东西方向绿灯闪n南北方向红灯亮:东西方向黄灯亮nSR EQU P1、0;
19、南北红灯nSY EQU P1、1;南北黄灯nSG EQU P1、2;南北绿灯nER EQU P1、3;东西红灯nEY EQU P1、4;东西黄灯nEG EQU P1、5;东西绿灯nORG 00h nST1:SETB SG;南北方向绿灯亮n CLR SY n CLR SR n CLR EG n CLR EY n SETB ER;东西方向红灯亮n MOV R3,#20;长延时n CALL DELAY n MOV R4,#8;南北方向绿灯闪4 次nST2:CPL SGn MOV R3,#2 ;短延时n CALL DELAY n DJNZ R4,ST2n CLR SG ;南北方向绿灯灭n SETB S
20、Y ;南北方向黄灯亮n MOV R3,#20 ;延时n CALL DELAY nST3:CLR SY ;南北方向黄灯灭n SETB SR ;南北方向红灯亮n CLR ER ;东西方向红灯灭n SETB EG ;东西方向绿灯亮n MOV R3,#20 ;长延时n CALL DELAY nST4:MOV R4,#8 ;东西方向绿灯闪4 次nLP:CPL EG n MOV R3,#2 ;短延时n CALL DELAY n DJNZ R4,LP n CLR EG ;东西方向绿灯灭n SETB EY ;东西方向黄灯亮n MOV R3,#20 ;延时n CALL DELAY n SJMP ST1 ;转ST1 nDELAY:MOV R1,#0;延时子程序nDELAY1:MOV R0,#0 nDELAY2:DJNZ R0,DELAY2 nDJNZ R1,DELAY1 nDJNZ R3,DELAY nRET本章小结n本章介绍得基本内容有:MCS-51指令系统得伪指令、汇编语言程序设计步骤、简单程序、循环程序、子程序、查表及散转程序得基本结构以及设计方法与技巧,并列举了大量具有实用价值得子程序实例。n通过本章学习应达到如下要求:n、掌握MCS-51汇编语言程序设计得基本思路;n、掌握汇编语言常用伪指令得功能、格式以及使用方法;