《PIC汇编语言程序设计基础ppt课件.ppt》由会员分享,可在线阅读,更多相关《PIC汇编语言程序设计基础ppt课件.ppt(84页珍藏版)》请在三一办公上搜索。
1、第四章 PIC汇编语言程序设计基础,4.0 序论4.1 MPASM汇编器的使用4.2 汇编语言的语句格式4.3 常用伪指令4.4 程序格式和程序流程图4.5 RAM数据存储器的体选寻址问题4.6 顺序程序结构4.7 分支程序结构4.8 循环程序结构4.9 子程序结构4.10 程序的跨页跳转和跨页调用问题4.11 延时程序设计4.12 查表程序设计,为什么要学习汇编语言,汇编语言是唯一一种面向机器的、最贴近及其硬件的编程语言。学习汇编语言能够帮助深入了解单片机的构成、工作过程和原理。因此特别适合初学阶段的学习;汇编语言程序可以最有效的节省CPU的运行时间和数据存储空间,代码使用效率最高。在简单的
2、控制场合是一种最佳选择;由于汇编语言是一种直接控制CPU的指令语言,所以可以产生精确的定时信号,这时其它语言所无法实现的;尽管C语言已经成为各类单片机重要的开发手段,但是汇编语言永远不会被淘汰,只有将汇编语言和C语言有机的结合起来才能高效的实现应用软件的设计。,4.0 序论,CPU所能识别的是由 “0”或“1”组成的二进制的 “机器语言”。如: “SLEEP”指令的机器语言:“00000001100011” 。但机器语言不便于人们编写、阅读。汇编语言是对机器语言的改进。使用了便于记忆、阅读的符号、字符串来表示指令的操作码、操作数和操作数地址。是一种符号语言,它与机器语言一一对应。汇编语言CPU
3、是不能识别的,因此必须使用一种工具将其“翻译”为机器语言,这个工具叫“汇编器”或“汇编程序”。使用“汇编器”或“汇编程序”帮助将汇编语言的源程序转换为机器语言,这一过程称之为“汇编”。,汇编语言的使用为我们提供了一种可以不涉及机器指令码和实际存储器地址的便捷条件。 但是要想正确使用汇编语言编程必须了解“编译器”所约定的内容,掌握如:语句格式、标号格式、数据进制的表示方法、伪指令和汇编器的使用等等。在下面的章节中将介绍MPASM编译器的使用、汇编语言的语句格式、几种常用伪指令、程序格式和流程图。,返回,4.1 MPASM汇编器的使用,MPASM汇编器是美国microchip公司为其单片机开发、应
4、用者设计的一套语言工具软件。它不仅能将汇编语言源程序“翻译”成机器语言,还能检查源程序中的语法错误或格式错误并向用户给出题示。MPASM汇编器有两种版本: DOS版本的 MPASM.EXE; WINDOWS的 MPASMWIN.EXE。 有关如何使用MPASM将在后面相关章节中介绍。,返回,4.2 汇编语言的语句格式,为了使编译器能够顺利的对用户编制的汇编语言源程序进行代码转换,在编制源程序时必须依照汇编器的约定进行书写。microchip公司提供的MPASM汇编器其汇编语言格式的一般格式由4个字段组成,这4个段不都是必要的,但顺序不能颠倒。,标号必须从左面第1列开始,后面至少用1个空格与操作
5、码隔离(注意:标号后面没有冒号);在无标号时,操作码前至少要保留一个或一个以上的空格(建议使用“Tab”键分割标号列);操作码与操作数之间至少要保留一个或一个以上的空格,如果有两个操作数时两者之间要由逗号(半角)隔开(建议使用“Tab”键分割) ;注释由分号(英文半角)引导,在标号、操作码和操作数之后。标号也可以单独占一行单必需由分号引导。,(一)标号,在指令前的标号实际上就是该指令的符号地址。并不是每条指令都需加标号的,只有那些欲被其它语句引用的语句之前才需要加标号。子程序第一条语句的标号实际上就是该子程序的名称;标号可以单独作为作为一行;标号的第1个字符必须由字母或下划线 “_” 开始,并
6、且从每一行的第1列开始写。标号最多可由32个字母、数字和其它符号组成。标号不能使用指令的助记符、寄存器名、或其它系统中已有固定用途的字符串(系统的保留字)。一个标号在系统中只能定义一次。,(二)操作码,在汇编语言语言源程序中,尽管其它3个字段有时是空的,但操作码字段无论在何时都不能是空的。操作码是指令的助记符,是指令功能的英文缩写,表示指令的操作类型、性质,是汇编语言语句中的“关键字”,因此是不能省略的。汇编器将操作码进行汇编时,将其与一个预先建立的操作码索引表相比较找出对应的机器码取而代之,这叫“代真”当操作码前无标号时,操作码前至少要留有一个空格以防汇编器将其误认为标号。,(三)操作数,操
7、作数是指令操作的对象,是数据或数据的地址。它们可以使用数值或标号形式表示。其中,数值可以使用二进制、八进制、十进制和十六进制或ASCII字符值(参见讲义88页表4.2);而标号可以是在此前定义或赋值的代表数字或地址标号或字符串。如果操作数有两个,中间应由逗号隔开。,(四)注释,注释部分用于对指令进行注解和说明。虽然注释可有可无,但对于一个编程者来说,为了便于程序的阅读、交流、修改和调试,在一些关键的语句上加标注释是一种好的编程习惯;注释由半角的引号“;”开始,它不是程序的功能部分,编译器对该部分不做任何处理。,返回,4.3 常用伪指令,所谓伪指令就是“假指令”的意思,它不是为CPU识别的指令、
8、没有对应的机器码。它是为编译器服务的指令,如确定指令的存储地址,为标号、字符串赋值等。伪指令的使用使程序在书写、阅读上更方便。对于一些没有说明意义的数字、RAM地址可以通过伪指令换为有意义的字符来取代,使程序具有很好的可读性。如:在PIC的指令中不能直接引用寄存器的名字取代地址,只能通过EQU伪指令定义后引用其寄存器的符号。伪指令只在汇编的过程中进行一些辅助工作,是程序设计人员向编译器发出的控制命令,告诉汇编器如何完成汇编过程和一些规定的操作,以及控制汇编的输入、输出和数据定位等。一旦汇编完成,伪指令就不存在了。,与指令类似,伪指令的格式也是由4个字符段组成。 符号名 伪指令助记符 操作数 ;
9、注释符号名:通常为寄存器名、变量名、常数名、标志位名或控制 位名、复位矢量或中断矢量的一个字符串。同标号一 样符号名必须从一行的第1列开始,后面与伪指令应至 少保留一个空格。但不能向标号那样独占一行。,(一)EQU - 符号名赋值伪指令,格式: 符号名 EQU n n 说明:使 EQU 两边的值相等。其中 nn 是长度不同的二进制数(可以分别作为寄存器名、位地址、8位的数据或常数、13位的复位或中断矢量等 )。一旦符号名被EQU赋值,其值就固定下来不能再重新改变。举例:STATUSEQU03H;定义寄存器名RP0EQU05H;定义位地址TMR0_bEQU00H;定义定时器的初值常数,【举例】:
10、在PIC指令系统中,没有寄存器寻址的方式,汇编程序也不允许直接使用寄存器的名字。所以与寄存器相关的操作只能通过“直接寻址”方式完成。 【如】:将W中的数据送PORTC寄存器: MOVWF 07H 因此,编写PIC的程序清单时,在程序的开头可以使用QEU伪指令现将相关的寄存器名进行定义,然后在程序中就可以直接引用寄存器的名字。 PORTCEQU07H;定义寄存器名 MOVWF PORTC ;将W中的数据送PORTC汇编时,编译器将用07H取代PORTC。,举例:经EQU伪指令定义后,汇编程序中直接使用寄存器的符号名来取代寄存器的地址,使程序具有更好的可读性。INDF EQU 00HTMR0 EQ
11、U 01HPCL EQU 02HSTATUS EQU 03HRP0 EQU 05H ;参见讲义48页RP1 EQU 06HPORTC EQU 07H : : : ORG 0000H GOTO MAIN ORG 0005HMAIN BSF STATUS,RP0 BCF STATUS,RP1 ;选择体 MOVLW 01H ;立即数01H送W MOVWF PORTC ;W内容送PORTC,(二)ORG - 程序起始地址定义伪指令,格式: ORG nnnn说明:用于指定该伪指令后面的源程序在ROM中存放 的起始地址。nnnn 为13位长的地址参数。,举例:ORG 0005HMAINCLRWCALL S
12、UB : MAIN是标号,也就是本行指令的符号地址。ORG伪指令又将该符号地址定义为单片机内部RAM的0005H单元,即CLRW的机器码存储在程序存储器ROM的0005H开始的单元中。,(三)END - 程序结束伪指令,格式 : END说明:该伪指令通知MPASM汇编器结束对源程序的汇编。注意:在一个源程序中必须有一个END伪指令,且只能在 程序的最后。,(四)LIST - 列表选项伪指令,格式 :LIST 可选项,可选项 ,可选项 说明:用于设置汇编参数来控制汇编过程,或对打印输出文件进行格式化。该伪指令的所有选项都应在一行内完成。 指令的可选项共有十余种,这里仅介绍2种。 P=设定单片机型
13、号。 例如:P = 16F877 R=定义默认的数值进制。例如:R=DEC(十进制) 或:R=HEX(十六进制),(五)INCLUDE - 调入外部程序文件伪指令,格式 :INCLUDE “文件名” 说明:用来告知汇编器,将一个预先编制好的外部程序文件包含进来。这样做可以减少重复劳动,提高编程效率。调入的外部程序文件通常是“定义文件”,即定义单片机的复位矢量、专用寄存器的地址及控制位和状态为地址等。,返回,4.4 程序格式和程序流程图,虽然书写源程序时没有统一的要求,但是一个良好的格式风格非常重要。在此推出一种风格的格式供参考:;-;符号定义和变量定义;-INDFEQU00H ;把后面程序指令
14、要用到的TMR0EQU 01H;寄存器单元地址用表义性很PCLEQU02H;强的符号名预先定义STATUSEQU03HFSREQU04HPORTAEQU05HTRISAEQU85HXEQU20H;对程序所需的变量预先定义YEQU 21H,;-;复位矢量和中断矢量的安排(PIC16F87X);-ORG 0000H;复位矢量入口GOTOMAIN;转跳到主程序ORG0004H;中断矢量入口GOTO INT_BODY;跳转到中断服务程序;-;主程序区;-ORG 0005H;主程序从0005H开始存放MAIN CLRWCALLSUB GOTOMAIN,标号,注释,;-;子程序区和中断服务程序区;-SUB
15、MOVLW01H;子程序 RETURN;子程序返回;INT_BODY;中断服务程序MOVLW0FFH RETFIE;中断服务程序返回;-END;全部程序结束从这个例子中,可以看出:纵向上将程序划分为几个功能块,层次清晰,便于阅读;横向上按4个字段划分并上下对齐,程序框图的图形符号,用图形来表示程序的结构和流向叫程序的“流程图”。流程图比程序本身更直观的体现出程序的特点。因此,在编制、书写程序本身之前应当首先画出流程图。通过图形将程序的每一个操作及操作的顺序、分支的结构等等一目了然的展现出来。在编写一个程序(特别是复杂的程序)事先通过流程图制定程序的结构、操作顺序等,然后将程序采用模块化,逐一编
16、制、调式,最后完成,这是编程者必须养成的良好习惯。,开始,操作1,操作2,条件判断,结束,条件成立,条件不成立,4.5 程序的四种结构及流程图,开始,操作1,操作2,操作3,操作n,结束,初始化,操作1,条件判断,开始,结束,初始化,循环体,循环控制,开始,结束,开始,操作1,Call A,Call A,结束,子程序A,操作n,1,顺序结构 2,分支结构 3,循环结构 4,子程序调用结构,操作2,返回,(一)顺序程序结构,结构中最简单的一种。流程图中的任务框按顺序自上而下的执行,最后结束;【例题】字节拆分将将RAM中20H单元中的8位数据拆分为高4位(A)、低4位( B ),并分别送入22H、
17、21H寄存器中。程序示意图:,20H,21H,22H,20H,21H,22H,流程图,结束,20H单元数据送W,将W中高4位清零,处理后数据送21H,将20H中的数据经半字交换后送W,将W的高4位清零,处理后数据送22H,MOVF 20H,0;将20H单元中的数据送WANDLW0FH;屏蔽数据的高四位MOVWF21H;送RAM的21H单元SWAPF20H,0;将20H单元中的数据交换送WANDLW0FH;屏蔽数据的高4位MOVWF22H;送RAM的21H单元(思考题)不使用半字交换指令SWAPF时,程序应当怎样编写?,20H,21H,22H,20H,21H,22H,(二)分支程序,在分支结构程
18、序的流程图中,包含一个判断框。判断框中有一个入口、两个出口,从而形成两个分支;判断框是由“条件判跳语句”实现的:当条件满足时 skip 跳一步;当条件不满足时顺序执行。,条件成立?,OP,成立时(skip),不成立时(顺序执行),【举例】:将RAM的20H、21H单元中的无符号数进行比 较,将大数送入22H单元。【算法】:将两个数进行一次减法操作,如果产生借位,则 表明:被减数小于减数。【注意】:减法指令SUBWF F,d 中:F为被减数、W为减数即: F - W在减法运算时:如果有借位则Cy=0;无借位Cy=1。这一点不同于常规系统的定义;使用“位测试”指令BTFSSSTATUS,C;如果C
19、y=1(无借位)时skip或BTFSCSTATUS,C;如果Cy=0(有借位)时skip,程序流程图,开 始,C=1(无借位),C=0(有借位),(21H)送22H单元,C=1?,(21H)-(22H),(20H)送22H单元,停 机,F21BIG,F20BIG,程序清单,STATUSEQU03HCEQU0MOVF20H,0;20H数据送WSUBWF 21H,0;21H-W送WBTFSSSTATUS,C;如果C=1(无借位)skip GOTO F20BIG;C=0(有借位)F21BIGMOVF 21H ,0;无借位时21H数大MOVWF22H GOTO STOP;跳转到停机F20BIGMOVF
20、20H ,0;有借位时20H数大MOVWF22HSTOPGOTOSTOP;停机,(三)循环程序结构,对于一些重复性的操作可以采用循环结构以简化程序;一个循环程序包含以下五个组成部分:循环计数器:由一个寄存器承担,用于循环次数的控制;数据指针:在处理数据块时,采用指针是一种唯一可行方法。通过“寄存器间接寻址”的方式来使用数据指针的;循环工作体:要重复执行的基本操作;修改数据指针:在循环体中每完成一次基本操作后,通过对指针的“加一”或“减一”为下次访问作好准备;循环控制:对于固定次数的循环,在每循环一次后,通过对“循环计数器”(或其它条件)进行处理、判断,当条件满足后即可退出循环,否则程序将会进入
21、“死循环”。,【举例】RAM存储器的数据填充。将地址30H开始的50个单元全部填充00H。【算法】程序采用循环结构:建立数据指针,即FSR做指针,原始=30H;选择一个寄存器作循环计数器,原始=50;循环体的基本操作是对内存RAM某一单元清零;修改数据指针,采用对FSR加一的方法实现;利用DECFSZ F,1实现循环次数的控制。,程序清单,COUNTEQU20HFSREQU04HINDFEQU00HMOVLWD50MOVWFCOUNTMOVLW30HMOVWFFSRNEXTCLRFINDF;注意采用间接寻址方式INCFFSR,1;修改指针DECSZCOUNT,1;循环控制语句GOTONEXTS
22、TOPGOTOSTOP,定次数循环程序流程图,开 始,NO,循环结束?,初始化,修改指针,停 机,YES,工作体,关于程序的几点说明,CLRF INDF 指令是“寄存器间接寻址”的寻址方式,且实际操作中是以文件选择寄存器FSR的内容为操作数的地址;程序中所遇到的寄存器(FSR)都在体0中,即系统上电复位后所默认的体,所以省去了访问FSR前的选体过程;在间接寻址中,RAM单元的9位地址:由FSR寄存器本身提供8位地址、STATUS中的IRP提供最高位地址。由于整个数据块(30H62H)都在体0中,且系统上电复位后STATUS中的IRP=0,所以省去了对IRP的设定;,数据存储器RAM的寻址示意图
23、,6 来自指令 0 PR1 PR0,IRP 7 FSR寄存器 0,RAM,单元选择,单元选择,间接寻址的体选,直接寻址的体选,00 01 10 11,体0 体1 体2 体3,STATUS寄存器,(四)子程序结构,在一个程序中,对于一些完全相同的计算或操作可以采用“子程序”结构以简化程序、节省存储空间;在PIC系列单片机是采用 CALL+ 子程序名 实现子程序的调用:在子程序的开头必须要有一个标号,此标号也是该子程序的名;子程序的最后是通过RETURU或RETLW(带参数返回)或RETIF(中断服务子程序的返回)。,在编制子程序时,要关注两个问题:参数的传递:主程序与子程序之间相关的数据。一般是
24、约定某一存储单元作为参数的存储空间。主程序调用之前将参数放入此单元;而子程序从该单元取出数据进行处理,最后再将处理后的数据送回(或约定另一个单元);返回主程序后主程序从对应单元得到数据。一般最常用的存储单元是工作寄存器W。现场保护:在运行子程序时,要用到一些寄存器来处理一些中间数据,而这些寄存器往往在调用子程序前已经被使用(存有数据,最常见的是工作寄存器W)。为了避免因调用子程序而破坏原有主程序的数据,就要对子程序所临时使用的寄存器(也称局部变量)的数据事先进行保护现场保护。一般保护指令放在子程序的最开始部分,待子程序返回前再使用指令恢复这些数据。,子程序结构应用举例,【举例】极值挑选:假设在
25、RAM的30H单元开始有三个无符号数。现编制一个程序将其中的最大数挑选出来并送如40H单元。【算法】编制一个比较两个数大小的子程序SUB。入口参数分别为X、Y(参加比较的两个数的存储单元)、出口参数为Z(挑选出来的大数存储单元),编制一个主程序两次调用SUB就可以跳出最大值。,程序流程图,停机,初始化,将两个数据送X、Y单元,将Z和第三个数送X、Y,调用SUB,得Z,调用SUB,得Z,MAIN,SUB,返回,(Y)-(X),(Y)送Z,(X)送Z,有借位?,YES(C=0),NO(C=1),将Z送指定最大单元,主程序流程图,SUB子程序流程图,程序清单(主程序),STATUSEQU 03HCE
26、QU00HXEQU 20H YEQU 21H ZEQU22HMAINMOVF30H,0MOVWFXMOVF31H,0MOVWFYCALLSUB; 比较30H、31H数据MOVFZ,0;最大数送Z单元MOVWFXMOVF32H,0MOVWFYCALLSUB;32H单元与Z单元比较MOVFZ,0;将最大数送40H单元MOVWF40HSTOPGOTOSTOP;停机,程序清单(子程序SUB),入口参数:X、Y单元;出口参数:Z单元存大数。SUBMOVFX,0SUBWFY,0;Y-X送WBTFSSSTATUS,C;如果无借位skip GOTOX_BIGY_BIGMOVFY,0MOVWFZGOTODONE
27、X_BIGMOVFX,0MOVWFZDONERETURN,4.5 RAM数据存储器的体选寻址问题,存储单元的物理地址由体选和体内地址两部分组成。将512个单元分成4个“体”,每个体为128个单元。在直接寻址的指令中的F(寄存器名)是一个7位的地址码,其寻址范围是128,通过该7位地址码F可以实现体内的128个单元寻址。,RAM,体0 体1 体2 体3,1FFH,00H,00H,7FH,80H,FFH,100H,17FH,180H,1FFH,4个体需要2位体地址寻址。在PIC单片机的硬件设计中体选按下面方法实现:使用“直接寻址”时(大多数场合),2位体选码来自状态寄存器STATUS的PR0、PR
28、1。采用“间接寻址”时,2位的体选码来自状态寄存器STATUS中的IRP位和FSR寄存器的最高位(如图)。,数据存储器RAM的寻址示意图,6 来自指令 0 PR1 PR0,IRP 7 FSR寄存器 0,RAM,单元选择,单元选择,间接选址的体选,直接选址的体选,体选 00 01 10 11,体0 体1 体2 体3,STATUS寄存器,00H01H02H03H04H05H06H07H08H09H0AH0BH0CH 1FH20H7FH,80H81H82H83H84H85H86H87H88H89H8AH8BH8CH 9FHA0HFFH,100H101H102H103H104H105H106H107H
29、108H109H10AH10BH10CH 11FH120H17FH,180H181H182H183H184H185H186H187H188H189H18AH18BH18CH 19FH1A0H1FFH,寄存器单元功能分配和地址分配图,从上面的图可以看出:有些寄存器具有4个不同的地址。如STATUS,不论在那个体内,都可以寻找到同一个寄存器STATUS。换句话,只要指令中的寄存器地址 F=03H(而不论RP0、RP1为何值)都可对STATUS进行定位。这种设计会给编程者在寻址上带来很大的方便。相类似的还有寄存器PCL等。本着“够用即可”的原则,在PIC16F87X系列单片机的000H1FFH的地址
30、中并没有配满512个存储空间,在不同的型号芯片中RAM的配置也不尽相同。特殊功能寄存器安排在4个体的上半部(小数地址),而通用寄存器占据着4个体的下半部(大数地址)。,举 例,单片机上电后RP0、RP1=00B,即指向体0。设对体1的TRISA寄存器进行写入一个0FH的操作。 首先要设置STATUS寄存器的PR0,完成操作后再恢复该体选码。程序段的代码如下(直接寻址):STATUSEQU03H ;将符号名进行定义PR0EQU05HTRISAEQU85HMOVLW0FH ;常数送WBSFSTATUS,PR0 ;将STATUS的PR0 ;置一以选择体1MOVWFTRISA ;WTRISABCFST
31、ATUS,PR0 ;清STATUS的PR0 ;以恢复选择体0,在上面的例子中,开头部分使用了三条伪指令用表义性很强的符号(直接选用寄存器的英文名称)来取代原来指令指令中的寄存器地址。这样增加了程序的可读性。如果不使用伪指令来取代寄存器的地址,则程序变为:MOVLW 0FH;将数据写入WBSF03H,5H ;设定体选位MOVWF85H;WTRISABCF 03H,5H;恢复体选位在PIC单片机的指令系统中没有向寄存器直接写数据的指令,只能先将数据写入W然后通过W将数据传到寄存器中。所以,上述操作必须由两条指令完成。,返回,4.6 程序的跨页跳转和跨页调用问题,在PIC16F87X的跳转和调用指令
32、: GOTO nnnn CALL nnnnnnnn为11位的绝对地址,即可直接对2K的程序存储单元进行寻址。然而PIC16F87X系列单片机的程序存储空间有三种类型: 870/871/872为2K的存储空间(000H-7FFH);873/874为4K的存储空间(000H-FFFH);876/877有8K的存储空间(0000H-1FFFH) 。 对于2K存储空间的单片机在使用GOTO或CALL指令时可以直接使用指令而不会出现任何问题,但对于程序存储空间大于2K的芯片在使用上述指令时就存在“跨页”的问题。,0000H,0004H,1FFFH,07FFH,0800H,第0页,第1页,第2页,第3页,
33、1800H,17FFH,1000H,0FFFH,对于大于2K的程序存储器,可以将其按每2K为1页而将程序存储器划分为若干个页。这样一个指令的实际物理地址就可以表达为: 页地址 + 页内地址。对于具有4K程序存储空间的873/874来说,页地址由PCLATH3来确定(如图所示);对于具有8K的程序存储空间的876/877而言,页地址由PCLATH 来确定(如图所示)。因此,在使用跨页跳转时,应事先将PCLATH 进行设置,12 11 10 8 7 0,PCH PCL,来自指令本身的11位地址,PCLATH,PC,执行GOTO 和 CALL指令时PC的形成,举例:在某一单片机的程序存储器中存放着这
34、样的一个程序,主程序存放在0页内,而要调用的子程序却在1页内。PCLATHEQU0AH;将符号为PCLATH定义0AHORG0000H;复位矢量入口地址GOTOMAIN;从入口地址转主程序MAINORG0500H;主程序地址MAINBSFPCLATH,3;设置PCLATH =1CALLSUB;调用1页的子程序SUBLOOP ;-ORG0900H;1页中的子程序起始地址SUBMOVLW 00H RETURNEND,通过这一例题(GOTO 、 CALL)要注意两点: 在程序出现“跨页”跳转时,一定要在跳转之前设定PCLATH ,然后再跳转; 使用CALL指令 “跨页”调用时,在调用前对PCLATH
35、进行设定。在子程序返回前不用恢复PCLATH的对应位。这时因为在子程序调用时,将原来PC中13位的内容全部压入(13位宽度)堆栈,然后再将PCLATH的页选位与指令中的11位地址形成跨页调用。这样在子程序返回时,从堆栈中弹出原完整的13位PC值,使程序直接返回到原来的断点。 参见讲义33页,返回,4.7 四种典型使用程序设计方法,PIC单片机的指令系统具有35条指令,方便学习和记忆。但是由于指令系统的特点和局限性其编程方法有其特殊性;本节就一些较常用的典型算法进行分解。这些算法有:初始化程序段;延时程序段;查表程序设计方法;散转程序设计。,(一)初始化程序设计,所谓“初始化”是指在程序执行某一
36、算法前的准备工作。它主要包括:对一些变量单元的初始值的设定;相关功能模块工作模式的设定等。初始化程序一般是一段顺序结构的程序段;单片机在上电、复位后PC值将引导CPU进入到ROM的0000H处执行程序,所以在0000H单元通过一条“跳板指令 GOTO 指令”转到真正的程序开始段;,0000H,0004H,1FFFH,07FFH,0800H,第0页,第1页,第2页,第3页,1800H,17FFH,1000H,0FFFH,GOTO 0010H,初始化程序一般包含下列任务:对汇编程序中所使用的变量和常数进行定义;对所使用的SFR(专用寄存器)进行符号地址的定义;复位矢量、中断矢量的设置;看门狗的设置
37、(如果启用WDT);对所使用模块的初始化设定(对相关寄存器的设定);程序中有关的各个中断允许位的设定;总的中断使能的设定。通过实际编程可以了解和掌握初始化的编程方法。,(二)延时程序设计,编程时常常会遇到需要在程序的某些地方插入延时时间,即编制一个延时程序。延时程序通常可以采用两种方法: 硬件资源调用法:如使用单片机内嵌的可编程定时器 tmr0或tmr1等.(类似于mcs-51的T0和T1); 软件编程法:插入一段小循环程序,利用这段程序所消 耗的时间达到延时目的。,在编写延时程序前必须了解PIC单片机的指令系统35条指令的执行时间。 PIC单片机内部采用“哈佛”总线结构,指令的读取总是提前一
38、个周期进行(如图)。,PIC单片机的指令时序,OSC1,Q1,Q2,Q3,Q4,PC,PC,PC+1,PC+2,提取第n条指令 执行第n-1条指令,提取第n+1条指令 执行第n条指令,提取第n+2条指令 执行第n+1条指令,取第n条指令与执行第n-1条指令的相互嵌套的“流水作业”模式,PIC单片机指令的执行时间 (三种情况),PIC的指令从取指到执行要占用两个机器周期(4个Q)。但由于采用了“流水”作业,取第n条指令的取指周期嵌入在前一条指令n-1的执行时间内。所以在一个顺序结构的程序中每一条指令的执行时间相当于单周期指令。5条无条件跳转指令因为其跳转改变了原来程序的执行顺序,原来提前读取的指
39、令必须丢掉,重新读一个新的指令后再执行,所以要多用一个周期,即两个周期。 这五条指令分别是: GOTO、CALL、RETURN、RETLW和RETFIE。,4个条件跳转指令的执行时间要随条件的不同而不同。 当条件满足发生跳转时,因改变原来程序执行的顺序而多用一个周期(2个周期); 当条件不满足时,程序按原来的顺序执行,所以仍为一个周期。 这四条指令分别是: DECFSZ、INCFSZ、BTFSC、BTFSS。,举例:本例提供3个采用不同方法实现的3个不同时间的延时子程序。为了便于计算,在每一条指令后用括号表明其时间。 (设系统使用4MH晶体,则指令周期Tcyc = 4*1/4s =1s)N E
40、QU20H;定义寄存器N的地址MEQU21H;定义寄存器M的地址DELAY1MOVLWX;(1)循环初值(待定)送WMOVWFN;(1)循环初值送N寄存器LOOPDECFSZN,1;(1/2) 寄存器减一并送回=0跳GOTOLOOP;(2) 无条件跳转到LOOPRETURN;(2)返回主程序,;-; 0.8ms延时子程序;-DELAY2MOVLWD100;(1)100送WMOVWFN;(1)100送寄存器NLOOPNOP;(1)NOP;(1)NOP;(1)NOP;(1) NOP;(1)DECFSZN,1;(1/2)寄存器N减一送回=0跳GOTOLOOP;(2) 0时转LOOPRETURN;(2
41、) 返回主程序,;-; 100ms延时子程序;-DELAY3MOVLWD133 ;(1)外层循环参数送MMOVWFM ;(1)LOOP1MOVLWD251 ;(1)内层循环参数送NMOVWFN ;(1)LOOP2DECFSZN,1 ;(1/2)GOTOLOOP2 ;(2)DECFSZM,1 ;(1/2)GOTOLOOP1 ;(2)RETURN ;(2)延时时间:251*3*133=100149s 100mS,DELAY1所产生的延时时间是: 周期数=1+1+(1+2)*(X-1)+2+2= 6 + 3*(X-1) 设X=1,则 T= 6 Tcyc = 6s【注意】循环参数X控制循环次数是X-1
42、。 由于循环参数X是存放在一个8位的RAM中,所以可选位为0255。DELAY2的原理基本同DELAY1 ,但是在循环体内填充NOP空操作来达到增加延时时间的目的。DELAY3的特点是采用双重循环来实现较长的时间延时。上述的各子程序如果考虑到CALL的执行时间的话,则还要加上2个周期即2 s。,返回,(三)查表程序设计,查表程序常用于实现代码转换、索引和翻译等场合,是一种较特殊而且非常有用的程序功能。在多种CPU的指令系统中都设计了专用的查表指令,可见其重要性。例如:用于显示数字和字符的LED数码管显示电路,把数据送给LED数码管显示前,必须先将数据转换为“字符码”后才能送LED显示电路。这种
43、为了显示而将数据转换成“字符码”的过程就是通过典型的查表操作完成的。PIC单片机的查表程序是利用“子程序带值返回”指令RETLW来实现。,字符字位驱动,PIC单片机,PORTB,字符码输出,abcdefg,dp,共阴极数码管内部结构与LED数字显示电路,字划端(阳极)输入高电平时,该字划亮。,共阴极结构LED数码管显示字符与输入字形码对应表,a,b,c,d,e,f,g,dp,查表程序的算法,将待查的数据作为查表的“偏移量”事先存入W;查表操作由一个子程序完成。子程序是由一条指令ADDWF PCL,1 和带参数返回“RETLW指令串”构成。返回指令串的内容是将所有包含的参数(字型码)的 RETL
44、W 指令按照字符的自然顺序排列。查表过程是利用ADDWF PCL,1指令将W(待查数字)与PCL(表头地址)相加,结果送PCL从而实现程序的跳转,跳转地址正好是一条与待查数字对应的包含字形码的RETLW返回指令(字形码包含在W中)。这样,返回主程序后便可从W中得到对应的字形码。,PCLEQU02HSTATUSEQU03HRP0EQU05HRBEQU06HTRISBEQU86H;-;主程序;-ORG0000HGOTOMIANMIANBSFSTATUS,RP0;选择体1CLRFTRISB;定义B口为全部输出BCFSTATUS,RP0;恢复为体0MOVF20H,0;将20H中的数据送WANDLW 0
45、FH;屏蔽高四位CALLCONVERT;调用查表子程序MOVWF RB;送到B口输出现实STOPGOTOSTOP;停机,;-; 查表转换子程序;-CONVERTADDWFPCL,1 ;W+PCLPCLTABLERETLW3FH ;“0”的字形码RETLW06H ;“1”的字形码RETLW5BH ;“2”的字形码RETLW4FH ;“3”的字形码RETLW66H ;“4”的字形码RETLW6DH ;“5”的字形码RETLW7DH ;“6”的字形码RETLW07H ;“7”的字形码RETLW7FH ;“8”的字形码RETLW6FH ;“9”的字形码RETLW77H ;“A”的字形码RETLW7CH
46、 ;“b”的字形码RETLW39H ;“C”的字形码RETLW5EH ;“d”的字形码RETLW79H ;“E”的字形码RETLW71H ;“F”的字形码END,由PIC单片机与共阴极LED数码管构成的显示电路(拉电流驱动模式),PIC16F877 RB7RB6RB5RB4RB3RB2RB1RB0,返回,注意:不是所有的单片机都具备“拉电流”能力!,(四)散转程序设计,与一般的条件转移指令不同,散转程序是实现多个转移分支的功能。散转是一种使用频率不高但又非常特殊的程序结构,在一些特定场合下是一种非常实用的处理手段;程序发生跳转的本质就是通过修改PC之实现的:无条件转移、条件转移是这样,而散转也
47、是通过修改PC值实现的;散转是利用PIC单片机所特有“ADDWFPCL,1 ”即 PCL寄存器可以作为操作数与W实现运算这一特点,实现程序的转移;,普通的分支程序与散转程序的区别,条件成立?,ADDWF PCL,1,普通的条件转移示意图,具有多分支的“散转”指令示意图,散转程序举例,现以20H单元的内容为转移标志字节,根据单元内容的不同(0、1、2N)实现不同的转移目标地址。CPLEQU 02HFLAGEQU 20HORG0000H MOVFFLAG,0ADDWF PCL,1TABGOTOBRANCH0GOTOBRANCH1GOTOBRANCH2 GOTOBRANCHn,BRANCH0 . G
48、OTOSTOP BRANCH1 . GOTOSTOPBRANCH2 . GOTOSTOP . BRANCHn . GOTOSTOP,几点说明,当CPU执行指令ADDWF PCL,1 指令时,PC已经提前指向下一条指令,即指向表头地址TAB。因此指令实际上是以TAB为基地址、以W为“偏移量”来实现真正的转移;这里ADDWF PCL,1 指令实际上起到一条转移指令的作用,因为指令执行后PC的值发生了变化;散转指令的核心部分只有MOVF和ADDWF两条指令。在本例中,TAB必须紧跟在ADDWF指令的下面。如果想要摆脱这种限制可使用下列指令来取代MOVF、ADDWF:MOVLWTABADDWFFLAG,0;表头地址+偏移量MOVWFPCL,1,程序中使用ADDWF PCL,1指令实现对PC值得修改,由于数据宽度的限制,W对PC的修改进限于PC中的低8位,而13位地址的高5位是通过PCLATH中的低5位实现自动装载,因此要注意TAB表的地址要在ADDWF指令相同的“段”中,否则会出现转移出错。当TAB表不是很大时可忽略此问题。,PCLATH,12 PCH 8 7 PCL 0,来自ALU(8位),执行以PCL为目标的指令时,也可以通过事先对PCLATH赋值的方法来改变TAB在ROM的起始位置,这下问题可通过实践去学习、掌握。,