单片机程序设计_第1页
单片机程序设计_第2页
单片机程序设计_第3页
单片机程序设计_第4页
单片机程序设计_第5页
已阅读5页,还剩42页未读 继续免费阅读

下载本文档

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

文档简介

汇编语言设计顺序结构循环结构2021/5/913.1汇编语言程序设计方法

汇编语言程序设计同高级语言程序设计一样,是有章可循的,只要按照一定的方法步骤去做,程序设计就会变成一件轻松愉快的事情,设计的程序也会规范、清晰、易读、易懂。使用汇编语言设计程序大致上可分为以下几个步骤。1.分析题意,明确要求。2.确定算法。3.画程序流程图。4.分配内存工作单元。5.编写源程序。6.程序优化。7.上机调试。2021/5/923.2顺序程序设计【例】程序初始化。初始化就是为变量、寄存器、存储单元赋一初值,是最简单、最常用的操作。如将R0-R3,P1,30H,40H单元初始化为00H,把R4,R5初始化为0FFH。参考程序如下:

ORG0000H ;PC起始地址

LJMPSTART ;转主程序

ORG0100H ;主程序起始地址START:MOVR0,#00H ;初始化

MOVR1,#00H MOVR2,#00H MOVR3,#00H MOVP1,#00H2021/5/93 MOVR4,#0FFH MOVR5,#0FFH MOV30H,#00HMOV40H,#00HHERE:SJMPHERE ;反复执行该指令,相当于等待

END用立即数比较直观,但用MOVA,#00H,MOVR0,A指令赋值,效果更好。2021/5/94【例】逻辑运算。逻辑操作是控制过程中经常使用的,掌握逻辑运算的特点是提高程序效率的重要途径。在逻辑运算中,进位标标志CY的地位很特殊,它是逻辑累加器,大多数逻辑操作要通过CY来完成。用程序实现图4-2所示的逻辑电路功能。图3-2逻辑电路2021/5/95参考程序如下:

ORG0000H LJMPSTART ORG0100H MOVP1,#0FFH ;P1口初始化LOOP:MOVC,P1.1ORLC,P1.2 ;P1.1与P1.2逻辑或运算

CPLC ;取反

ANLC,P1.0 ;C与P1.0逻辑与运算

CPLCMOV07H,C ;暂存于07H单元中

MOVC,P1.3ANLC,/P1.4 ;P1.3与P1.4的反逻辑与运算

CPLCORLC,07HMOVP1.5,C ;把结果在P1.5口输出

SJMP$END2021/5/963.3分支程序设计分支程序的主要特点是程序包含有判断环节,不同的条件对应不同的执行路径。编程的关键任务是合理选用具有逻辑判断功能的指令。由于选择结构程序的走向不再是单一的,因此,在程序设计时,应该借助程序框图(判断框)来明确程序的走向,避免犯逻辑错误。一般情况下,每个选择分支均需单独一段程序,并有特定的名字,以便当条件满足时实现转移。1.单分支选择结构当程序的判断是二选一时,称为单分支选择结构。通常用条件转移指令实现判断及转移。单分支选择结构有三种典型表现形式。2021/5/97图3-3单分支选择结构2021/5/98(a)当条件满足时执行分支程序1,否则执行分支程序2。(b)当条件满足时跳过程序段1,从程序段2顺序执行;否则,顺序执行程序段1和程序段2。(c)当条件满足时程序顺序执行程序段2;否则,重复执行程序段1,直到条件满足为止。由于条件转移指令均属相对寻址方式,其相对偏移量rel是个带符号的8位二进制数,可正可负。因此,它可向高地址方向转移,也可向低地址方向转移。对于第三种形式,可用程序段1重复执行的次数作为判断条件,当重复次数达到某一数值时,停止重复,程序顺序往下执行。这是分支结构的一种特殊情况,这实际是循环结构程序。用这种方式可方便实现状态检测。【例】:LOOP:JBP1.1,LOOP单分支程序一般要使用状态标志,应注意标志位的建立。2021/5/99【例】设a存放在累加器A中,b存放在寄存器B中,若a≥0,Y=a-b;若a<0,则Y=a+b。这里的关键是判a是正数,还是负数;可通过判断ACC.7确定。

ORG0000H LJMPBR ORG0100HBR: JBACC.7,MINUS ;负数,转到MINUS CLRC ;清进位位

SUBBA,B ;A-B SJMPDONEMINUS:ADDA,B ;A+BDONE:SJMP$ ;等待

END2021/5/9102.双向分支程序设计举例【例4.3】设X存在30H单元中,根据下式

X+2 X>0Y= 100 X=0∣X∣ X<0求出Y值,将Y值存入31H单元。解:根据数据的符号位判别该数的正负,若最高位为0,再判别该数是否为0。程序流程如图4-4所示。

2021/5/911A为负数?取数,A←(30H)开始结束A=0?YNNA←|X|A←64HA←X+2存数,(31H)←A(30H)2021/5/912参考程序如下:ORG 1000H

MOV A,30H ;取数JB ACC.7,NEG;负数,转NEGJZ ZER0 ;为零,转ZER0ADD A,#02H ;为正数,求X+2AJMPSAVE ;转到SAVE,保存数据ZER0:MOV A,#64H ;数据为零,Y=100AJMPSAVE ;转到SAVE,保存数据NEG:DEC A CPL A ;求∣X∣SAVE: MOV 31H,A ;保存数据

SJMP $ ;暂停2021/5/9132.多分支选择结构当程序的判别输出有两个以上的出口流向时,称为多分支选择结构。8051的多分支结构程序还允许嵌套,即分支程序中又有另一个分支程序。汇编语言本身并不限制这种嵌套的层次数,但过多的嵌套层次将使程序的结构变得十分复杂和臃肿,以致造成逻辑上的混乱。多分支选择结构通常有两种形式,如图4-4所示。图4-4多分支选择结构2021/5/9148051的散转指令和比较指令均可以实现多分支转移。

散转指令JMP@A+DPTR

比较指令CJNEA,direct,rel(共有4条)使用散转指令前,先将各分支程序编写好,存放在程序存储器中,并将各分支程序的入口地址组成一个表格放在一起,把表首地址送入DPTR,把子程序的序号放入A中。在8051指令中,还有4条功能极强的比较转移指令:CJNEA,direct,rel CJNEA,#data,rel CJNERn,#data,relCJNE@Ri,#data,rel这4条指令对指定单元内容进行比较,当不相等时程序作相对转移,并指出其大小,以备作第二次判断;若两者相等,则程序顺序执行。2021/5/915【例】散转程序。编写程序,根据20H单元中的内容转入相应的分支,执行指定的操作,将结果存入指定存储器单元。程序流程框图如图4-5所示图3-5散转程序流程2021/5/916参考程序

ORG0000H LJMPMEMSRESULT EQU0050H ORG0100HMEMS: MOVA,20H MOVDPTR,#KKKK ;散转程序入口地 址表首址

RLA;分支号乘2,每个 入口地址均为2字节

JMP@A+DPTR;转移END1: SJMP$KKKK: AJMPMEMSP0;A=0加法

AJMPMEMSP1 ;A=1减法

AJMPMEMSP2 ;A=2乘法

SJMPMEMSP3 ;A=3除法

SJMPMEMSP4 ;A=4逻辑与

SJMPMEMSP5 ;A=5逻辑或2021/5/917MEMSP0:MOVA,R0 ;相加分支

CLRC ADDA,R1MOVRESULT,A LJMPEND1MEMSP1:MOVA,R0 ;相减分支

CLRC SUBBA,R1 MOVRESULT,ALJMPEND1MEMSP2:MOVA,R0 ;乘法分支

MOVB,R1 CLRC MULABMOVRESULT,AMOVRESULT+1,BLJMPEND12021/5/918MEMSP3:MOVA,R0 ;除法分支

MOVB,R1CLRCDIVABMOVRESULT,AMOVRESULT+1,BLJMPEND1MEMSP4:MOVA,R0 ;逻辑与分支

ANLA,R1MOVRESULT,ALJMPEND1MEMSP5:MOVA,R0 ;逻辑或分支

ORLA,R1MOVRESULT,ALJMPEND1END2021/5/919【例】两个无符号数比较大小。设外部RAM单元ST1和ST2中存放两个无符号二进制数,要找出其中的大数存入ST3单元中。程序流程框图如图3-6所示。图3-6求大数程序流程2021/5/920参考程序如下:

ORG0000HLJMPSTARTORG0100HSTART:MOVA,addr1 ;将addr1中内容送ACJNEA,addr2,LOOP1;两数比较,不相等则 转LOOP1LOOP3:AJMP$;结束LOOP1:JCLOOP2 ;当CY=1,转LOOP2MOVaddr3,A;CY=0,(A)>(addr2)SJMPLOOP3;转结束LOOP2:MOVaddr3,addr2 ;CY=1,(addr2)>(A)SJMPLOOP3 END2021/5/9213.4循环程序设计在实际应用中经常会遇到功能相同,需要多次重复执行某段程序的情况,这时可把这段程序设计成循环结构,这有助于节省程序的存储空间,提高程序的质量。循环程序一般由4部分组成。1.初始化。即设置循环过程中有关工作单元的初始值,如置循环次数、地址指针及工作单元清零等。2.循环体。即循环处理部分,完成主要的计算或操作任务,是重复执行的程序段。

3.循环控制。每循环一次,就要修改循环次数、数据及地址指针等循环变量。并根据循环结束条件,判断是否结束循环。

4.循环结束处理。对结果进行分析、处理、保存。2021/5/922循环程序结构有两种,如图3-7所示。图3-7循环程序结构2021/5/923图(a)是“先执行后判断”结构,适用于循环次数已知的情况。其特点是进入循环后,先执行循环处理部分,然后根据循环次数判断是否结束循环。图(b)是“先判断后执行”结构,适用于循环次数未知的情况。其特点是将循环控制部分放在循环的入口处,先根据循环控制条件判断是否结束循环,若不结束,则执行循环操作;若结束,则退出循环。2021/5/924【例】50ms软件延时程序。

软件延时程序一般都是由DJNZRn,rel指令构成。执行一条DJNZ指令需要两个机器周期。软件延时程序的延时时间主要与机器周期和延时程序中的循环次数有关,在使用12MHz晶振时,一个机器周期为1μs,执行一条DJNZ指令需要两个机器周期,即2μs。适当设置循环次数,即可实现延时功能。参考程序如下:

ORG0000H LJMPMEMS ORG0100HMEMS:DEL: MOVR7,#125 ;外循环次数,该指令为一个机器周期DEL1: MOVR6,#200 ;内循环次数DEL2: DJNZR6,DEL2 ;200×2=400μs(内循环时间) DJNZR7,DEL1 ;0.4ms×125=50ms(外循环时间) SJMP$ END2021/5/925例2.循环程序设计举例【例】有一数据块从片内RAM的30H单元开始存入,设数据块长度为10个单元。根据下式:

X+2X>0Y=100X=0求出Y值,并将Y值放回原处。

∣X∣X<0解:设置一个计数器控制循环次数,每处理完一个数据,计数器减1。程序流程如图4-8所示。2021/5/926A=0?YYNNYNA为负数?取数,A←((R1))开始结束A←∣X∣A←64HA←X+2存数,((R1))←A(30H)设置地址指针R1、计数器R0初值R1←R1+1;R0←R0-1R0=0?图4-8例4.5的程序流程图返回本节2021/5/927参考源程序如下:

ORG 2000H MOV R0,#10MOV R1,#30HSTART: MOV A,@R1 ;取数

JB ACC.7,NEG ;若为负数,转NEG JZ ZER0 ;若为零,转ZER0 ADD A,#02H ;若为正数,求X+2 AJMP SAVE ;转到SAVE,保存数据

ZER0: MOV A,#64H ;数据为零,Y=1002021/5/928 AJMP SAVE ;转到SAVE,保存数据NEG: DEC A CPL A ;求∣X∣SAVE: MOV @R1,A ;保存数据

INC R1 ;地址指针指向下一个地址

DJNZ R0,START ;数据未处理完,继续处理

SJMP $ ;暂停2021/5/929【例】排序程序。设在内部RAM中存一无符号数的数组,其长度为n,起始地址是30H,要求将它们按从大到小排序,排序后仍存放在原区域中。

按“冒泡法”对n个数排序时,可能用不到n-1次循环,排序就结束了。为了提高排序速度,程序中可设一交换标志位,如10H位,每次循环中,若有交换则执行SETB10H,表明排序未完成;若无交换,则执行CLR10H,表明排序已经完成。每次循环结束时,测10H位,判断排序是否结束。参考程序如下:

ORG0000H LJMPBUBBLE ORG0100HBUBBLE:MOVR0,#30H MOVB,#64H CLR10HDECB ;长度计数2021/5/930LOOP:MOVA,@R0 ;内循环的入口

MOV20H,A ;暂存,为交换作准备

INCR0MOV21H,@R0CJNEA,21H,BUEU ;若(20H)≠(21H)转移BUEU:JNCBUNEXT ;(20H)≥(21H)转移

MOVA,@R0 ;若(20H)<(21H)则交换

MOV@R0,20HDECR0 ;使R0退格指向小地址

MOV@R0,AINCR0 ;恢复R0指向大地址

SETB10H ;置交换标志BUNEXT:DJNZB,LOOP ;内循环是否结束 的判断

JB10H,BUBBLE ;判断标志位为1否?外循 环结束的判断

END2021/5/9313.5子程序设计在实际应用中,一些特定的运算或操作经常使用,例如多字节的加、减、乘、除处理,代码转换、字符处理等。如果每次遇到这些运算或操作,都重复编写程序,不仅会使程序烦琐冗长,而且也会浪费编程者大量时间。因此经常把这些功能模块按一定结构编写成固定的程序段,存放在内存中,当需要时,调用这些程序段。通常将这种能够完成一定功能、可以被其它程序调用的程序段称为子程序。调用子程序的程序称为主程序或调用程序。调用子程序的过程,称为子程序调用,用ACALLaddr11和LCALLaddr16两条指令完成。子程序执行完后返回主程序的过程称为子程序返回,用RET指令完成。2021/5/9321.在编写子程序时要注意以下几点:①要给每个子程序赋一个名字。它是子程序入口地址的符号,便于调用。②明确入口参数、出口参数。所谓入口参数,即调用该子程序时应给哪些变量传递数值,放在哪个寄存器或哪个内存单元,通常称为参数传递。出口参数则表明了子程序执行的结果存在何处。例如,调用开平方子程序,计算。在调用子程序之前,必须先将x值送到主程序与子程序的某一交接处N(如累加器A),调用子程序后,子程序从该交接处取得被开方数,并进行开方计算,求出的值。在返回主程序之前,子程序还必须把计算结果送到另一交接处M。这样在返回主程序之后,主程序才可能从交接处M得到的值。③注意保护现场和恢复现场。在执行子程序时,可能要使用累加器、PSW或某些工作寄存器,而在调用子程序之前,这些寄存器中可能存放有主程序的中间结果,这些中间结果在主程序中仍然有用,这就要求在子程序使用这些资源之前,要将其中的内容保护起来,即保护现场。当子程序执行完毕,即将返回主程序之前,再将这些内容取出,恢复到原来的寄存器,这一过程称为恢复现场。2021/5/933

保护现场通常用堆栈来完成。并在子程序的开始部分使用压栈指令PUSH,把需要保护的寄存器内容压入堆栈。当子程序执行结束,在返回指令RET前边使用弹栈指令POP,把堆栈中保护的内容弹出到原来的寄存器。要注意,由于堆栈操作是“先入后出”。因此,先压入堆栈的参数应该后弹出,才能保证恢复原来的数据。 为了做到子程序有一定的通用性,子程序中的操作对象,尽量用地址或寄存器形式,而不用立即数、绝对地址形式。另外,子程序中如含有转移指令,应尽量用相对转移指令。2.子程序的调用与返回主程序调用子程序是通过子程序调用指令LCALLadd16和ACALLadd11来实现的。前者称为长调用指令,指令的操作数部分给出了子程序的16位入口地址;后者为绝对调用指令,它的操作数提供了子程序的11位入口地位,此地址与程序计数器PC的高5位并在一起,构成16位的调用地址(即子程序入口地址)。它们的功能,首先是将PC中的当前值(调用指令下一条指令地址,称断点地址)压入堆栈(即保护断点),然后将子程序入口地址送入PC,使程序转入子程序运行。2021/5/934子程序的返回是通过返回指令RET实现的。这条指令的功能是将堆栈中返回地址(即断点)弹出堆栈,送回到PC,使程序返回到主程序断点处继续往下执行。子程序调用过程如图3-8所示图3-8子程序调用过程2021/5/935

主程序在调用子程序时要注意以下问题。在主程序中,要安排相应指令来传递子程序的入口参数,即提供子程序的入口数据。在主程序中,要安排相应的指令,处理子程序提供的出口数据,即操作结果。在主程序中,不希望被子程序更改内容的寄存器,也可以在调用前由主程序安排压栈指令来保护现场,子程序返回后再安排弹栈指令恢复现场。在主程序中,要正确地设置堆栈指针。2021/5/9363.子程序嵌套 子程序嵌套是指在子程序执行过程中,还可以调用另一个子程序。子程序嵌套过程如图3-9所示。图3-9子程序嵌套过程2021/5/9374.子程序的特性编写子程序应注意以下问题:①通用性。为使子程序能适应各种不同程序、不同条件的调用,子程序应具有较好的通用性。②可浮动性。可浮动性是指子程序段可设置在存储器的任何地址区域。假如子程序只能设置在固定的存储器地址段,这在编制主程序时要特别注意存储器地址空间的分配,防止两者重叠。为了能使子程序段浮动,必须在子程序中避免选用绝对转移地址,而应选用相对转移类指令,子程序首地址亦应采用符号地址。③可递归和可重入性。子程序能自己调用自己的性质,称为子程序的可递归性,而子程序能同时被多个任务(或多个用户程序)调用的性质,称为子程序的可重入性。这在比较复杂的程序中经常用到。④子程序说明文件。对于通用子程序,为便于各种用户选用,要求在子程序编制完成后提供一个说明文件,使用户不必详读源程序,只需阅读说明文件就能了解子程序的功能及应用。2021/5/938【例】求平方。用程序实现C=a*a+b*b。设a、b均小于10,a存在31H单元,b存在32H单元,把C存入33H单元。因本题两次用到平方值,所以在程序中采用把求平方编为子程序的方法。子程序名称:SQR。功能:求X2,通过查平方表来获得。入口参数:某数在A中。出口参数:某数的平方在A中。参考主程序和子程序如下:主程序:

ORG0000H LJMPMAIN ORG0100HMAIN:MOVSP,#3FH ;设堆栈指针(调用和返回指令要用到堆栈) MOVA,31H ;取a值

LCALLSQR ;第一次调用,求a2 MOVR1,A ;a2值暂存R1中

MOVA,32H ;取b值

LCALLSQR ;第二次调用,求b2 ADDA,R1 ;完成a2+b2 MOV33H,A ;存结果到33H SJMP$ ;暂停2021/5/939子程序:

ORG0200HSQR:ADDA,#01H ;查表位置调整,RET为 一字节指令

MOVCA,@A+PC ;查表取平方值

RET ;子程序返回TAB:DB0,1,4,9,16,25 DB36,49,64,81 END

求平方的子程序在此采用的是查表法,用伪指令DB将0~9的平方值以表格的形式定义到ROM中。子程序中A之所以要加1,是因为RET指令占了一个字节。2021/5/940

实践 题目:十字路口交通灯要求:通过单片机的P1口控制实验仪上6个LED按照交通灯的变化规律循环发光,模拟十字路口交通灯。实验电路如下,L5、L4、L3模拟东西方向交通灯,L2、L1、L0模拟南北方向交通灯。通过一条SETB指令,可使某一灯亮,通过一条CLR指令,可使某一灯灭。 硬件:画出硬件电路原理图。 软件:画出程序流程图,编写源程序。 调试:记录调试过程,分析调试结果。2021/5/941南北方向绿灯亮:东西方向红灯亮南北方向绿灯闪:东西方向红灯亮南北方向黄灯亮:东西方向红灯亮南北方向红灯亮:东西方向绿灯亮南北方向红灯亮:东西方向绿灯闪南北方向红灯亮:东西方向黄灯亮2021/5/942SREQUP1.0;南北红灯SYEQUP1.1;南北黄灯SGEQUP1.2;南北绿灯EREQUP1

温馨提示

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

评论

0/150

提交评论