740 likes | 1k Views
第 4 章. 汇编语言程序设计. 程序设计基本步骤. 本章主要内容. 常用伪指令的使用方法. 简单程序设计. 查表程序设计. 循环程序设计. 分支程序设计. 子程序设计与调用. 项目五:多路开关状态指示灯. 1 、项目内容. AT89C51 单片机的 P1.0 - P1.3 接四个发光二极管 L1 - L4 , P1.4 - P1.7 接四个开关 K1 - K4 , 编程将开关的状态反映到发光二极管上。 (开关闭合,对应的灯亮,开关断开,对应的灯灭)。. i /mA. u /V. O. 2. 2 、设计硬件电路. 1 )驱动 LED 设计.
E N D
第 4 章 汇编语言程序设计 程序设计基本步骤 本章主要内容 常用伪指令的使用方法 简单程序设计 查表程序设计 循环程序设计 分支程序设计 子程序设计与调用
项目五:多路开关状态指示灯 1、项目内容 AT89C51单片机的P1.0-P1.3接四个发光二极管L1-L4,P1.4-P1.7接四个开关K1-K4,编程将开关的状态反映到发光二极管上。(开关闭合,对应的灯亮,开关断开,对应的灯灭)。
i /mA u /V O 2 2、设计硬件电路 1)驱动LED设计 ▼顺向偏压时LED两端约有1.7V左右的压降。 ▼随着通过LED的顺向电流的增加,LED的亮度将更亮,而LED的寿命也将缩短。 ▼LED电流以10~20mA为宜。 LED特性曲线
VCC VCC R 内部上拉电阻 R 8051 8051 2、设计硬件电路 1)驱动LED设计 P1、P2与P3内部有30KΩ的上拉电阻, 想从此些端口流出10~20mA,有困难。 VCC 内部上拉电阻 R限流电阻 不适当的连接 适当的连接
VCC 5-1.7V VCC R= =330Ω R 内部上拉电阻 10mA 5-1.7V R= =220Ω 8051 15mA ▼如果希望流过LED的电流ID限制为10mA,则此限流电阻R为: ▼若想要LED亮一点,可使ID提高到15mA,则此限流电阻R改为: R限流电阻 ▼一般限流电阻R为200Ω~300Ω。
VCC VCC VCC VCC 内部上拉电阻 内部上拉电阻 4.7K PB PB 470Ω 8051 8051 2、设计硬件电路 ② 按钮开关的输入电路设计 通常将按钮开关接一个电阻到VCC或GND。 若是P0口则必须接上外部上拉电阻; 若是其它P1、P2、P3口则可接可不接外部上拉电阻。
3、程序设计内容 方案一:可轮流检测每个开关状态,根据每个开关的状态让相应的发光二极管指示,采用JBP1.X,REL或JNBP1.X,REL指令来完成,然后根据开关的状态,用SETBP1.X和CLRP1.X指令来完成发光二极管L1-L4的显示。 方案二:一次性检测四路开关状态,然后让其指示,可以采用MOVA,P1指令一次把P1端口的状态全部读入,然后取高4位的状态来指示。
读P1口内容到A中 将A内容右移4次 A内容与F0H相或 A内容送到P1口 4、程序流程图 程序开始 采用方案二相对简单 结束
置开关为输入状态 读P1口内容到A中 将A内容右移4次 A内容与F0H相或 A内容送到P1口 6、程序设计 程序开始 ORG 0000H AJMP MAIN ORG 0030H MAIN:SETB P1.4 SETB P1.5 SETB P1.6 SETB P1.7 MOV A,P1 RRA ORL A,#0F0H RRA MOV P1,A RRA 结束 RRA AJMP MAIN END
一、 程序设计概述-设计语言 ▼为了方便记忆,人们开始用助记符形式的汇编语言编写程序,称为低级语言。然后再用汇编系统将其翻译成机器语言,该过程称为汇编。 ▼为了用更接近人的语言编写程序,程序设计师们发明了高级语言,如: BASIC、FORTRAN、PASCAL、C、JAVA然后再用编译系统将其翻译成机器语言,该课程称为编译。 ▼机器只能识别机器语言,所以必须用编译系统将高级语言编写的源程序编译成机器语言,用汇编系统将用汇编语言编写的源程序汇编成机器语言。
▼由低级或高级语言构成的程序称为源程序。 ▼由机器语言构成的程序称作目标程序。 源程序 目标程序 汇编 低级语言 机器语言 编译 机器语言 高级语言
1、程序设计的基本步骤 1)分析题意,明确要求; 2)建立思路,确定算法或硬件电路设计; 3)画出流程图; 4)分配内存及端口; 5)编制源程序; 6)仿真、调试程序; 7)固化程序。
2、画程序流程图 画流程图是指用各种图形、符号、指向线等来说明程序设计的过程。 工作任务符号 开始或结束符号 判断分支符号 程序连接符号 程序流向符号
为什么要画流程图? ▼计算机从根本上来说,没有任何逻辑性,所以,你必须告诉它,先做什么,后做什么,遇到什么情况又该做什么,等等。 ▼用图形符号将总体设计思路及程序流向绘制在平 面图上,从而使程序的结构关系直观明了,便于检查和修改。 ▼流程图设计本身是一个逐步求精的过程,最终将任务划分为若干能由机器指令实现的小模块。
亮绿灯 判断 (P1.3)=1? 灭绿灯, 持续亮红灯报警 结束 绘制流程图实例 程序开始 N Y
3、源程序的编辑和汇编 1)源程序的编辑 源程序: ▼ORG和END是两条伪指令, 其作用是告诉汇编程序此汇编源程序的起止位置。 ORG 0000H AJMP MAIN ORG 0030H MAIN: MOV A,#7FH MOV R1,#44H END ▼编辑好的源程序应以“.ASM ”或“.A”扩展名存盘,以备汇编程序调用。
2)源程序的汇编 常用的方法有两种: ▼手工汇编:通过手工方式查指令编码表,逐个把助记符指令翻译成机器码,然后把得到的机器码程序键入到单片机开发机中,并进行调试。 ▼机器汇编:是在常用的个人计算机PC上,使用交叉汇编程序将汇编语言源程序转换为机器码形式的目标程序。生成的目标程序由PC机传送到开发机上,经调试无误后,再固化到单片机的程序存储器ROM中。
▼源程序经过机器汇编后,形成的若干文件中含有两个主要文件,一是列表文件,另一个是目标码文件。▼源程序经过机器汇编后,形成的若干文件中含有两个主要文件,一是列表文件,另一个是目标码文件。 ▼因汇编软件的不同,文件的格式及信息会有一些不同。 但主要信息如下: ①列表文件(扩展名.LST): LOC OBJ LINE SOURCE 0000 1 ORG 0000H 0000 0130 2 AJMP MAIN 0030 3 ORG 0030H 0030 747F 4 MAIN: MOV A,#7FH 0032 7944 5 MOV R1,#44H 6 END
源程序: ORG 0000H AJMP MAIN ORG 0030H MAIN: MOV A,#7FH MOV R1,#44H END ②目标码文件 (扩展名.HEX): :020000000130CD :04003000747F79441C :00000001FF
二、常用伪指令的使用方法 伪指令是汇编程序能够识别并对汇编过程进行某种 控制的汇编命令。它不是单片机执行的指令,所以 没有对应的可执行目标码,汇编后产生的目标程序 中不会再出现伪指令。 1)、ORG(Origin)定义程序的起始地址 2)、END程序结束标志 3)、DB(Define Byte)定义字节 4)、DW(Define Word)定义字 5)、EQU(Equate)表达式赋值
1)起始地址设定伪指令ORG ORG 表达式 向汇编程序说明下面紧接的程序段或数据段存放的起始地址。 ORG 0100H START: MOV A,#30H ▼在每一个汇编语言源程序的开始,都要设置一条ORG伪指令来指定该程序在存储器中存放的起始位置。 ▼在一个源程序中,可以多次使用ORG伪指令规定不同 程序段或数据段存放的起始地址,但要求地址值由小到大依序排列,不允许空间重叠。
2)汇编结束伪指令 END END 该指令的功能是结束汇编。 汇编程序遇到END伪指令后即结束汇编。 处于END之后的程序,汇编程序将不处理。
3)字节数据定义伪指令 DB [标号:] DB字节数据表 ▼功能是从标号指定的地址开始,在ROM中定义字节 数据。该伪指令将字节数据表中的数据根据从左到右 的顺序依次存放在指定的存储单元中。 一个数据占一个存储单元。 ▼该伪指令常用于存放数据表格。
字节数据定义伪指令 DB实例 DATA : DB 0C0H, 0F0H , 0A4H , 0B0H DB 99H, 92H, 82H, 0F8H ROM DATA: C0H 地址依次向下增长 F0H 数据存放示意图: A4H B0H DB “how are you?” 99H 把字符串中的字符以ASCII码 的形式存放在连续的ROM单元中。 92H 82H F8H
4)字数据定义伪指令 DB [标号:] DW字数据表 ▼该伪指令将字或字表中的数据根据从左到右的顺序 依次存放在指定的存储单元中。 ▼16位的二进制数,高8位存放在低地址单元, 低8位存放在高地址单元。
字数据定义伪指令 DW实例 ORG 1400H DATA:DW 324AH,3CH ROM DATA: 32H 1400H 4AH 1401H 数据存放示意图: 00H 1402H 3CH 1403H
5)空间定义伪指令 DS [标号:] DS表达式 ▼功能是从标号指定的地址单元开始,在程序存储器中保留由表达式所指定的个数的存储单元作为备用的 空间,并都填以零值。 ORG 0100H BUF:DS 50 汇编后,从地址3000H开始保留50个存储单元作为 备用单元。
6)赋值伪指令 EQU 符号名 EQU表达式 ▼功能是将表达式的值或特定的某个汇编符号定义为 一个指定的符号名。 LEN EQU 10 ▼将十进制数10赋给符号名LEN,在其后的编程中就可以用LEN来代替10。
赋值伪指令 EQU实例 ORG 0000H AJMP MAIN ORG 0030H LEN EQU 10 SUM EQU 21H BLOCK EQU 22H MAIN: CLR A MOV R7,#LEN MOV R0,#BLOCK LOOP:ADD A,@R0 INC R0 DJNZ R7,LOOP MOV SUM,A END ▼该程序的功能是: 把BLOCK单元开始存放的10个无符号数进行求和, 并将结果存入SUM单元。 ▼若改对15个无符号数进行求和,则只需将: LEN EQU 10 改为:LEN EQU 15
7)位地址符号定义伪指令 BIT 符号名 BIT位地址表达式 ▼功能是将位地址赋给指定的符号名。其中,位地址 表达式可以是绝对地址,也可以是符号地址。 ST BIT P1.0 ;将P1.0的位地址赋给符号名ST,在其后的编程中就可以用ST来代替P1.0。
三、简单程序设计 双字节无符号数加法(教材P77) 设计内容:被加数存放在内部RAM的51H、50H单元,加数存放在内部RAM的61H、60H单元,相加的结果存放在内部RAM的51H、50H单元,进位存放在位寻址区的00H位中。 (51H) (50H) + (61H) (60H) 结果保存到: (51H) (50H)
低字节相加 并保存低字节相加结果 修改指针 高字节相加 并保存高字节结果 保存进位 结束 程序开始 2、程序流程图 (51H) (50H) + (61H) (60H) 结果保存到: (51H) (50H)
低字节相加 并保存低字节相加结果 修改指针 高字节相加 并保存高字节结果 保存进位 结束 ORG 0000H 3、程序设计 程序开始 AJMP MAIN ORG 0030H MAIN:CLR C MOV R0,#50H MOV R1,#60H MOV A,@R0 ADD A,@R1 MOV @RO,A MOV A,@R0 ADD A,@R1 MOV @RO,A INC R0 INC R1 MOV 00H,C END
四、查表程序设计 1、设计内容: 有一变量存放在片内RAM的20H单元,其取值范围为: 00H~05H。要求编制一段程序,根据变量值求其平方值,并存入片内RAM的21H单元。 2、设计思路 在程序存储器的一片存储单元中建立起该变量的平方表。用数据指针DPTR指向平方表的首址,则变量与数据指针之和的地址单元中的内容就是变量的平方值。
取平方表首址 送到DPTR ( 20H ) A A 21H 结束 3、绘流程图 4、源程序 程序开始 ORG 0000H AJMP START ORG 0030H START:MOV DPTR,#TABLE MOV A,20H MOVC A,@A+DPTR MOV 21H,A SJMP $ TABLE:DB 00,01,04 DB 09,16,25 END (A+DPTR ) A
五、循环程序设计 ▼按某种控制规律重复执行的程序称为循环程序。 ▼常用于循环控制的指令有: DJNZ、CJNE、JC、JNC等控制类指令。 ▼通常有先执行后判断和先判断后执行两种基本结构 :
置循环初值 置循环初值 循环处理 循环处理 循环修改 循环修改 循环结束? 循环结束? 结束处理 结束 结束 先判断后执行 先执行后判断 程序开始 程序开始 Y N N Y 结束处理
1、先执行后判断循环程序实例 1、设计内容: 50ms延时子程序 2、设计思路: 若晶振频率为12MHz,则一个机器周期为1μs。执行一条DJNZ指令需要2个机器周期,即 2μs。采用循环计数法实现延时,循环次数可以通过计算获得,并选择先执行后判断的循环结构。
子程序入口 内循环初值R6置数 空操作 (R6)-1 R6 (R6)=0? (R7)-1 R7 (R7)=0? 返回 3、绘流程图 外循环初值R7置数 N Y N Y
4、50ms延时DELAY子程序 ;1 μs DELAY:MOV R7,#200 ;1 μs DEL1: MOV R6,#123 ;1 μs NOP ;2μs,计(2×123)μs DEL2: DJNZ R6,DEL2 DJNZ R7,DEL1;2μs RET 共计 [(2×123+2+ 2)×200+1] μs,即50.001ms
DELAY:MOV R7,# X ;1 μs DEL1:MOV R6,#Y ;1 μs NOP ;1 μs DEL2:DJNZ R6,DEL2;2μs,计(2×123)μs DJNZ R7,DEL1;2μs, RET 共计 [(2×Y+2+ 2)×X+1] μs 请设计100ms延时,X、Y分别为多少?
1s延时子程序 DELAY: MOV R2,#10 DEL3: MOV R3,#200 DEL2: MOV R4,#125 DEL1: NOP NOP DJNZ R4,DEL1 DJNZ R3,DEL2 DJNZ R2,DEL3 RET
先判断后执行循环程序实例 1、设计内容: 将内部RAM中起始地址为data的数据串传送到外部RAM中起始地址为buffer的存储区域内,直到发现‘$ ’字符停止传送。 2、设计思路: 由于循环次数事先不知道,但循环条件可以测试到。 所以,采用先判断后执行的结构比较适宜。 内部RAM单元用R0作为地址指针, 外部RAM单元用DPTR作为地址指针。
地址指针R0赋初值 地址指针DPTR赋初值 A ((R0)) (DPTR) (A) (A)=$? 地址指针R0和DPTR各加1 程序开始 3、画流程图: Y N 结束
A ((R0)) 地址指针DPTR赋初值 地址指针R0赋初值 (DPTR) (A) (A)=$? 地址指针R0和DPTR各加1 程序开始 ORG 0000H AJMP START ORG 0030H 4、源程序: START:MOV R0,#data MOV DPTR,#buffer QQ3: MOV A,@R0 CJNE A, $,QQ1 SJMP QQ2 Y QQ1: MOVX @DPTR,A N INC RO INC DPTR SJMP QQ3 QQ2: SJMP $ END 结束
六、分支程序设计 分支结构可以分成单分支、双分支和多分支几种情况。 条件成立? 条件成立? Y N Y N 程序段A 程序段A 程序段B 下条指令 单分支 双分支
K=0? K=1? K=2? 分支结构可以分成单分支、双分支和多分支几种情况。 Y 分支0 N Y 分支1 N Y 分支2 N 多分支
1、分支程序常用指令 ▼分支程序在单片机系统中有较多的应用。 ▼分支结构程序使用转移指令实现,即根据条件对程序的执行进行判断,满足条件是转移执行,否则顺序执行。 1)判A转移指令JZ、JNZ; 2)判位转移指令JB、JNB、JBC、JC、JNC; 3)比较转移指令 CJNE; 4)减1不为0转移指令DJNZ。