实验1 开发环境使用及常用指令功能
一、实验目的
1、掌握集成开发环境的使用;
2、初步了解实验装置的使用方法;
3、熟悉常用指令的功能;
4、熟悉程序调试的方法;
5、学习自己编写、调试计算程序。
二、实验说明
利用单片机及Keil uVision4软件实现程序的编译、运行、调试,学会利用软件硬件的几次开发使用。
三、实验内容
1、自行编写一段计算程序,实现双字节二进制数除以单字节二进制数,将所编程序录入、编译加载并调试。分析运行过程
2、用排线将单片机P2口与通用板上LED指示灯连接,单步执行下列指令:
SETB P2.0
CLR P2.0
CPL P2.1
CPL P2.1
MOV A,#55H
MOV P2,A
XRL A,#0FFH
MOV P2,A
RLC A
MOV P2,A
观察指令执行后,指示灯的亮、熄现象,理解指令的功能。在实验报告中记录实验现象和分析。
四、实验程序
1、双字节二进制数除以单字节二进制数程序如下:
ORG 0000H
START: LJMP CLATE
ORG 0030H
CLATE: MOV 34H,#10 ;被除数高位34H设为10
MOV 33H,#0 ;被除数低位33H设为0
MOV 35H,#10 ;除数35H设为10
MOV R3,34H ;被除数高位移至R3
MOV R2,33H ;被除数高位移至R2
MOV R4,35H ;除数移至R4
MOV 32H,0 ;设置商存放在32H
MOV B,#8 ;设置循环次数
LOOP: CLR C ;
MOV A,R3 ;被除数高位移至A
SUBB A,R4 ;R3-R4
MOV 31H,A ;余数暂存31H
JNC LOOP1 ;若够减,则跳转LOOP1
MOV A,R2 ;若不够减,则R3R2整体左移
RLC A ;
MOV R2,A ;
MOV A,R3 ;
RLC A ;
MOV R3,A ; 至此R3R2整体左移
LJMP LOOP2 ;
LOOP1: INC 32H ;够减商增1
MOV R3,31H ;余数存回至除数高位
LOOP2: MOV A,32H
RL A
MOV 32H,A
DJNZ B,LOOP ;未做完除法,则转LOOP继续
MOV R6,32H
END
五、实验现象
1、双字节二进制数除以单字节二进制数程序:
运行结束后,R6为Ox0a,即商为10
2、P2口与LED指示灯亮暗实验:
SETB P2.0 L1 L2 L3 L4 L5 L6 L7 L8
CLR P2.0 亮 暗 暗 暗 暗 暗 暗 暗
CPL P2.1 亮 亮 暗 暗 暗 暗 暗 暗
CPL P2.1 亮 暗 暗 暗 暗 暗 暗 暗
MOV A,#55H
MOV P2,A
XRL A,#0FFH 暗 亮 暗 亮 暗 亮 暗 亮
MOV P2,A
RLC A 亮 暗 亮 暗 亮 暗 亮 暗
MOV P2,A
END 亮 亮 暗 亮 暗 亮 暗 亮
六、思考题
1、跨越式单步运行方式和进入式单步运行方式有什么区别?
答:进入式单步:在调试状态下,点击图标,或执行快捷键F11,或者使用“Debug”菜单栏“Step Into”选项,可以执行进入式单步操作。每进行一次操作,程序将运行一条指令。每执行一行指令,表征PC指针的图标都会向下移动一行,已执行过的语句呈现绿色。进入式单步当遇到子程序调用时,将会跟踪到子程序中执行。
跨越式单步:点击图标,或者执行快捷键F10,或者使用“Debug”菜单栏的“Step over”选项,可以执行跨越式单步。跨越式单步当遇到子程序调用指令时,不跟进子程序中执行,直接把整个子程序一步执行完。对于其它指令来说,跨越式单步和进入式单步的作用相同。
2、如何设置程序指针到光标所在程序行?
答:(1)移动PC到光标所在行
在光标所在程序行,点击鼠标右键,弹出一个菜单,选中“Set Program Counter”选项,可以将程序指针PC 图标强行移到光标所在行。
调试程序时,如果希望改变程序的起始运行地址,可以利用此功能移动程序指针PC指向需运行的程序位置。
(2)执行到光标所在行
点击图标,或者使用快捷键Ctrl+F10,或者使用“Debug”菜单栏中的 “Run to Cursor line”选项,可以使程序从当前图标所在行执行到光标所在行。
3、如何修改内部RAM存储单元的值?
答: 通过打开数据存储器观察窗口,用户可以观察指定范围内的数据存储器内容。指定一个内部RAM存储单元所包含的一个地址,将鼠标放到该地址数值上,在右键弹出的窗口中,可以人为强行修改相应地址单元的值。程序调试时,也可以采用指令给RAM单元赋值,也可以人为强行修改RAM中的值。
实验2 “跑马灯”实验
一、实验目的
1、 了解发光二极管的使用方法;
2、 熟悉串行、并行输出扩展接口的方法;
3、 学习常用指令用法和简单程序编写技巧。
二、实验说明
利用单片机的P1口低4位,通过一片74HC595控制8位发光二极管,方法是在实验箱通用板上将P1口的低4位与74HC595的输入信号相连,将74HC595的输出分别与发光二极管相连,由此构成的实验电路原理如图3.1.1所示。
图3.1.1 发光二极管串行控制电路
在图3.1.1中,74HC595的SI(串行数据输入端)、SCLK(串行移位时钟输入端)、RCLK(输出寄存器锁存时钟端)、/OE(输出引脚使能端)分别与单片机的P1.0、P1.1、P1.2、P1.3引脚相连。74HC595输出低电平时点亮发光二极管。图3.1.1中595的输出使能引脚(/OE)已直接连接到“地”,使输出总是使能。
三、实验内容
1、 按图3.1.1连接电路,调试参考程序,单步执行部分指令,观察有关寄存器中值的变化,理解指令的功能和执行效果;
2、 自行对实验箱核心板上的发光二极管电路进行编程,采用并行接口控制的方法,实现“跑马灯”的功能,画出实验电路,记录实验程序。
四、实验程序
利用图3.1.1电路实现“跑马灯”功能的参考程序如下:
LIGHT EQU 62H ;定义指示灯数据存放地址单元
ORG 0000H
AJMP START
ORG 0030H
START: MOV SP,#30H ;初始化堆栈指针
CLR P1.0
CLR P1.1
CLR P1.2
CLR P1.3 ;初始化有关I/O口
;P1.3始终为0,输出使能恒有效
MOV LIGHT,#01H ;初始化指示灯数据
NOP
MAIN: LCALL FLY_LED ;调用指示灯循环点亮子程序
LCALL DELAY ;延时子程序同参考例程一
AJMP MAIN ;循环执行主程序
;******************************************************
;通过595循环点亮指示灯子程序
;*****************************************************
FLYLED: MOV A,LIGHT
CLR C
RLC A ;累加器A中最高位移到C
CPL C ;因低电平点亮,故取反
MOV P1.0,C ;LIGHT中数据最高位送到SER输入端
SETB P1.1
NOP
CLR P1.1 ;产生一个输入锁存脉冲
SETB P1.2
NOP
CLR P1.2 ;产生一个寄存器锁存脉冲
CJNE A,#0,FLYCON ;A中不为0则继续
MOV A,#01H ;A中为0,循环完一轮
;重新赋初值
FLYCON: MOV LIGHT ,A
RET
;延时子程序
DELAY: MOV R7,#20 ;将R7赋值20
DELAY1: MOV R6,#0 ;将R6赋值0,相当于赋值256
DELAY2: DJNZ R6,$ ;R6中的值减1不为0则循环执行当前行
DJNZ R7,DELAY1 ;R7中的值减1不为0则循环
RET
五、实验现象
LED灯从L1到L8依次循环点亮,实现了“跑马灯”的功能
六、思考题
1、什么是LED?LED的工作电流一般为多大?为什么在LED电路上要串联一个电阻?串联电阻的取值应为多少?
答: LED(Light Emitting Diode)是发光二极管的英文缩写。单个LED在各种仪器、仪表中常用作各种指示灯,根据外形直径的大小,常用的有Φ3、Φ5(mm)等型号,每一种直径下,还有普通亮度、高亮度、超高亮度等种类。普通亮度发光二极管工作电流一般为十几个毫安,高亮和超亮发光二极管在同样工作电流下,亮度更高。在LED电路上要串联一个电阻,称为限流电阻,起到了限流的作用,其阻值约为500欧,实际使用中,选择330到510欧的限流电阻,都是可行的。
2、串行接口器件和并行接口器件各有什么优缺点?
答:串行接口需要的CPU口线要少一些,但是占用CPU的时间要长一些;并行接口需要的CPU口线要多一些,但是占用CPU的时间要少一些。
3、单片机的晶振为12MHz,参考程序中的延时子程序的延时时间约为多少?如何修改延时时间?
答:=1μs,如下列出了延时子程序中各条指令的机器周期数:
延时子程序
DELAY: MOV R7,#20 ;1
DELAY1: MOV R6,#0 ;1
DELAY2: DJNZ R6,$ ;2
DJNZ R7,DELAY1 ;2
RET ;2
整个程序执行所用的机器周期数为:
1+(1+2256+2)20+2=10303
因此延时时间约为10.3ms
可以通过修改R6或R7的值来改变程序循环次数,从而修改延时时间。
实验3 数码管显示功能的实现
一、实验目的
1、 了解数码管显示器的特性和使用方法;
2、 进一步熟悉常用指令和编程技巧;
3、 熟悉单片机I/O口的使用方法。
二、实验说明
1、数码管电路结构
内部8个LED处于不同的位置,每个LED显示一个笔画,称为一段;通过外接电路控制点亮不同的LED组合,显示一位相应的数字(符号)。
对于单个数码管来说,一般有十个引脚。8个发光二极管的阳极连接在一起称为共阳极数码管显示器。实验箱上通用版上的数码管即为共阳极的。若将所有发光二级管的极性调换一下,所有的阴极连接到一起则称为共阴极数码管。
2、数码管显示器的动态控制电路
实验箱的核心板上,有6个共阴极数码管显示器,被设计成既可为并行接口动态控制,又可为串行接口动态控制。
三、实验内容
1、 读懂串行接口和并行接口的LED显示参考示例程序;
2、 分别运行并验证参考示例程序
3、 要让次低位LED数码管显示中总是带有小数点,即显示的6位数值中包括一位小数,修改参考程序实现;
四、实验程序
1、并行接口LED显示
D_DAT0 EQU 6AH
D_DAT1 EQU 6BH
D_DAT2 EQU 6CH
D_DAT3 EQU 6DH
D_DAT4 EQU 6EH
D_DAT5 EQU 6FH ;定义显示数据单元
ORG 0000H
AJMP START
ORG 0030H
START: MOV SP, #30H ;初始化堆栈指针
MOV D_DAT0, #0
MOV D_DAT1, #1
MOV D_DAT2, #2
MOV D_DAT3, #3
MOV D_DAT4, #4
MOV D_DAT5, #5 ;初始化显示数据
MOV P0, #0 ;
CLR P1.1 ;初始化有关I/O口
CLR P1.2
MOV R0, # D_DAT0 ;初始化显示数据指针寄存器R0
;指向第一位需显示数字
MOV R1, #01H ;初始化需点亮数码管位置代码
NOP
MAIN: LCALL DISP ;调用数码管循环点亮子程序
LCALL DELAY ;延时子程序同前,应修改延时时间
AJMP MAIN ;循环执行主程序
;****************************************************
;通过574显示6位数字子程序
;****************************************************
DISP: MOV A, R1 ;取位代码
MOV P0, A ;位代码送P0抠(用于产生位选信号)
SETB P1.2
NOP
CLR P1.2
MOV A, @R0 ;取需显示的数字值
MOV DPTR, #DISPD ;装载笔画编码表首地址
MOVC A, @A+DPTR ;取需显示数字笔画代码
MOV P0, A ;笔画代码送到P0口(勇于产生段选信号)
SETB P1.1
NOP
CLR P1.1 ;产生一个锁存脉冲,锁存输出笔画代码
INC R0 ;R0增1指向下一个需显示数字
MOV A, R1
CLR C
RLC A
MOV R1, A ;R1中的值左移一位,指向下一位数码管
CJNE R1, #40H, DISP1 ; R1中不为40H(未显示完6位)继续
MOV R0, #D_DAT0 ;R1中为40H,循环完一轮
;重新赋初值
MOV R1, #1 ;位置代码初值
DISP1: NOP
RET
;数字笔画代码表
; 0 1 2 3 4 5 6 7 8 9 熄
DISPD: DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH, 0
;延时子程序
DELAY: MOV R7,#20 ;将R7赋值20
DELAY1: MOV R6,#0 ;将R6赋值0,相当于赋值256
DELAY2: DJNZ R6,$ ;R6中的值减1不为0则循环执行当前行
DJNZ R7,DELAY1 ;R7中的值减1不为0则循环
RET
2、串行LED显示程序
D_DAT0 EQU 6AH
D_DAT1 EQU 6BH
D_DAT2 EQU 6CH
D_DAT3 EQU 6DH
D_DAT4 EQU 6EH
D_DAT5 EQU 6FH ;定义显示数据单元
ORG 0000H
AJMP START
ORG 0030H
START: MOV SP, #30H ;初始化堆栈指针
MOV D_DAT0, #0
MOV D_DAT1, #1
MOV D_DAT2, #2
MOV D_DAT3, #3
MOV D_DAT4, #4
MOV D_DAT5, #5 ;初始化显示数据
MOV P0, #0 ;
CLR P1.1 ;初始化有关I/O口
;以上内容与前面相同
CLR P1.3
CLR P1.1
CLR P1.2 ; 初始化有关I/O口
MOV R0, #D_DAT0 ; 初始化数据指针
; R0指向第一位显示数字
MOV R1, #01H ;初始化需点亮数码管位置代码
NOP
MAIN: LCALL DISP ;调用数码管循环点亮子程序
LCALL DELAY ;延时子程序同前
AJMP MAIN ;死循环
;*********************************************
;通过595显示4位数字子程序
;*********************************************
DISP: MOV A, R1 ;取位代码数据
MOV R2, #8 ;R2中为循环次数
DISP1: CLR C
RLC A
MOV P1.3, C ;一个位选信号送到SER的输入端
SETB P1.1
NOP
CLR P1.1 ;产生一个串行移位时钟脉冲
DJNZ R2, DISP1 ;一次将8个位选信号移入
;实际只有6位有用
MOV A,@R0 ;取需显示的数字
MOV DPTR,#DISPD ;笔画编码表同前
MOVC A,@A+DPTR ;去需显示数字笔画代码(段选信号)
MOV R2,#8
DISP2: CLR C
RLC A
MOV P1.3, C ;段选信号送到SI引脚
SETB P1.1
NOP
CLR P1.1 ;产生一个移位时钟脉冲
DJNZ R2, DISP2 ;依次将8个笔画信号(段选信号)移入
SETB P1.2
NOP
CLR P1.2 ;产生一个输出锁存脉冲
INC R0 ;R0中不为40H则继续
MOV A,R1
CLR C
RLC A
MOV R1, A ;R1中的值左移1位,指向下一位数码管
CJNE R1, #40, DISP3 ;R1中不为40H则继续
MOV R0, #D_DAT0 ;R1中为40H,循环完一轮
;重新赋初值
MOV R1, #01H ;位选数据重新赋初值
DISP3: RET
;延时子程序
DELAY: MOV R7,#20 ;将R7赋值20
DELAY1: MOV R6,#0 ;将R6赋值0,相当于赋值256
DELAY2: DJNZ R6,$ ;R6中的值减1不为0则循环执行当前行
DJNZ R7,DELAY1 ;R7中的值减1不为0则循环
RET
3、带小数点LED显示:将代码表中4对应的66H改为0E6H即可。
五、实验现象
1、并行LED显示程序实验:六个数码管依次显示0 1 2 3 4 5
2、串行LED显示程序实验:六个数码管依次显示0 1 2 3 4 5
3、带小数点LED显示实验:六个数码管依次显示0 1 2 3 4. 5
六、思考题
1、要让LED数码管显示A、b、C、d、E、F六个字母,请列写笔画代码表。
;数字笔画代码表
; A b C d E F
DISPD: DB 77H 7CH 39H 5EH 79H 71H
2、LED数码管动态显示和静态显示各有什么优缺点?
动态:需要器件数量少,功率低,印刷电路面积少,但占用CPU时间多
静态:需要器件数量多,功率大,印刷电路面积多,但占用CPU时间少
实验5 按键功能的实现
一、实验目的
1、 理解按键电路的作用;
2、 学习按键功能的编程方法;
3、 熟悉单片机I/O口连接独立式按键的编程应用方法。
二、实验说明
实验箱核心板上有4个按键,其一端全部与地线相连,另一端顺次与P1.4~P1.7相连,本实验需要用到核心板上的3个按键,3个指示灯和6个数码管,所用到的实验电路原理如图所示。
本实验中3个按键设计的功能,是一个使用的简单温度控制系统的按键功能,要求通过按键设定一个温度上限值和一个温度下限值。本实验只涉及按键和显示功能,在今后的试验中,将进一步增加硬件和软件功能,利用单片机实现实际的温度控制系统,是温度维持在上、下限值之间。
①“功能”键:在内存数据区定义一个名称为“KRM”的字节,存放功能编号,共有3种功能,分别对应编号为0,1,2。每按一次“功能”键,“KRM”中的值在这三个数字中循环改变一次。与三种功能对应,设计三个LED(发光二极管)指示灯,有单片机P3口控制,当处于某种功能状态时,相应的指示灯亮。本实验的内容,实际上是后面进一步做温度测量控制系统的一部分。三种功能的含义如下:
功能号0:显示测量的温度值;
功能号1:对温度上限值进行修改;
功能号2:对温度下限值进行修改。
②“↑”键:每按一次“↑”键,内存数据区中指定变量单元的值增1,持续按住则连续增1。
③“↓”键:与“↑”键对应,每按一次“↓”,内存数据区中指定变量单元的值减1,持续按住则连续减1。
功能号为0时,数码管显示被测温度值,此时按另外两个按键不起作用。功能号为1时,数码管显示设定温度的上限值,按两外两个按键可以修改温度上限值,功能号为2时,数码管显示设定温度的下限值,此时按另外连个按键可以修改温度上限值。
三、实验任务
1、 理解单片机I/O口与按键,指示灯和LED数码管的综合使用方法;
2、 理解如图所示电路,读懂参考程序;
3、 自行设计按键显示功能(比如将6位数码管分成三组,分别显示上限、下限、测量值),并编程实现所设计的功能。
四、实验程序
实现按键和显示参考程序如下:
D_DAT0 EQU 60H
D_DAT1 EQU D_DAT0+1
D_DAT2 EQU D_DAT1+1
D_DAT3 EQU D_DAT2+1
D_DAT4 EQU D_DAT3+1
D_DAT5 EQU D_DAT4+1 ;定义显示数据单元
LIGHT EQU D_DAT5+1
H_DAT0 EQU LIGHT+1
H_DAT1 EQU H_DAT0+1
KBM EQU H_DAT1+1 ;定义按键功能号存放单元
D_MAX EQU KBM+1 ;定义上限值存放单元
D_MIN EQU D_MAX+1 ;定义下限值存放单元
T_DAT0 EQU D_MIN+1
T_DAT1 EQU T_DAT0+1 ;定义测量值存放单元
ORG 0000H
AJMP START
ORG 0030H
START: MOV SP,#30H ;初始化堆栈指针
MOV D_DAT0, #0
MOV D_DAT1, #0
MOV D_DAT2, #0
MOV D_DAT3, #0
MOV D_DAT4, #0
MOV D_DAT5,#0 ;初始化显示数据
MOV LIGHT, #80H
CLR P1.0
CLR P1.1
CLR P1.2
CLR P1.3 ;初始化有关I/O口
MOV R0,#D_DAT0 ;初始化数据指针,R0指向第一位显示数字
MOV R1,#01H ;初始化需点亮数码管位置代码
MOV KBM,#0 ;初始化功能号
MOV D_MAX, #80
MOV D_MIN, #70 ;初始化上、下限值
MOV T_DAT0, #66
MOV T_DAT1,#0 ;目前人为赋给测量值一个值,将来有实际测量值就存放在此
MOV H_DAT0, T_DAT0
MOV H_DAT1, T_DAT1
LCALL HTD ;将测量值二进制数转换为十进制数
MAIN: LCALL DISP ;刷新显示
LCALL DELAY ;显示、延时子程序同前
;******************************************************
;按键处理程序
;*****************************************************
JB P1.7,KEY1 ;查询K0,若K0未按下则跳转
LCALL DISP
LCALL DELAY ;延时去抖动,顺便刷新显示
JB P1.7,KEY1 ;若K0未真正按下则跳转
INC KBM ;K0真正按下,功能号增1
MOV A,KBM
CJNE A,#3,KEY01
MOV KBM,#0 ;若功能号为3,则清0
KEY01: NOP
AJMP KEND ;跳转至按键结束处理程序
KEY1: JB P1.6,KEY2 ;查询K1
LCALL DISP
LCALL DELAY
JB P1.6,KEY2
MOV A,KBM
CJNE A,#1,KEY11 ;功能号不为1则跳转
INC D_MAX ;功能号1,上限值加1
AJMP KEND
KEY11: CJNE A,#2,KEY12 ;功能号不为2则跳转
INC D_MIN ;功能号2,下限值加1
KEY12: AJMP KEND ;跳转至按键结束处理程序
KEY2: JB P1.5,KEND ;查询K2
LCALL DISP
LCALL DELAY
JB P1.5,KEND
MOV A,KBM
CJNE A,#1,KEY21
DEC D_MAX ;功能号1,上限值减1
AJMP KEND
KEY21: CJNE A,#2,KEND
DEC D_MIN ;功能号2,下限值减1
KEND: NOP ;以下程序根据功能号显示不同内容
MOV A, KBM
CJNE A, #0, KEND1
MOV H_DAT0, T_DAT0
MOV H_DAT1,T_DAT1 ;功能号0,准备显示测量数据
MOV LIGHT,#0BFH ;点亮相应指示灯
AJMP KEND3 ;跳转到刷新显示处
KEND1: NOP
CJNE A, #1, KEND2
MOV H_DAT0, D_MAX
MOV H_DAT1,#0 ;功能号1,准备显示上限值
MOV LIGHT,#7FH ;点亮相应指示灯
AJMP KEND3 ;跳转到刷新显示处
KEND2: NOP
CJNE A, #2,KEND3
MOV H_DAT0, D_MIN
MOV H_DAT1,#0 ;功能号2,准备显示下限值
MOV LIGHT,#0DFH ;点亮相应指示灯
KEND3: MOV P0, LIGHT
SETB P1.0
NOP
CLR P1.0 ;产生一个指示灯输出锁存脉冲
LCALL HTD ;将需显示数据转换成4个十进制数
MOV R4, #80H
KEND4: LCALL DISP
LCALL DELAY ;刷新显示,延时
DJNZ R4,KEND4 ;此处循环延时是为了避免按键多次重入
LJMP MAIN ;跳转到主程序开始处循环执行
;******************************************************
;通过595显示4位数字子程序
;*****************************************************
DISP: MOV A,R1 ;取位代码数据
MOV R2,#8
DISP1: CLR C
RLC A
MOV P1.3,C ; 位代码送到SER的输入端
SETB P1.1
NOP
CLR P1.1 ;产生一个输入锁存脉冲
DJNZ R2,DISP1 ;依次将8位位代码移入,实际只有6位有用
MOV A,@R0 ;取需显示的数字
MOV DPTR,#DISPD ;笔画编码表同前
MOVC A,@A+DPTR ;取需显示数字笔画代码
MOV R2, #8
DISP2: CLR C
RLC A
MOV P1.3,C ;笔画代码送到SER的输入端
SETB P1.1
NOP
CLR P1.1 ;产生一个输入锁存脉冲
DJNZ R2,DISP2 ;依次将8位笔画代码(段代码)移入
INC R0 ;R0增1指向下一个需显示数字
MOV A,R1
RL A
MOV R1,A ;R1中的值左移1位,指向下一位数码管
CJNE R1,#40H,DISP3 ;R0中不为70H则继续
MOV R0, #D_DAT0
MOV R1,#01H ;R0中为70H,循环完一轮
;重新赋初值
DISP3: SETB P1.2
CLR P1.2
RET
;数字笔画代码表
; 0 1 2 3 4 5 6 7 8 9 熄
DISPD: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,0
;**********************************************
;延时子程序
;**********************************************
DELAY: MOV R7,#2
DELY1: MOV R6,#0FFH
DELY2: DJNZ R6,$ ;$代表当前行(与DJNZ R6,DELY2相同)
DJNZ R7, DELY1
RET
;二进制转换十进制子程序
HTD: MOV D_DAT5,#00H ;将结果千位清0
MOV D_DAT4, #00H
MOV D_DAT3, #00H
MOV D_DAT2, #00H
H1000: CLR C ;进位位C清0
MOV A,H_DAT0 ;源数据低位装载到累加器A中
MOV R6,A ;备份源数值低位到寄存器R6中
SUBB A,#0E8H ;源数值低位减去1000的低位0E8H
MOV H_DAT0,A ;余数存回到源数值低位存储单元
MOV A,H_DAT1 ;源数值高位装载到累加器A中
MOV R7,A ;备份源数值高位到寄存器R7中
SUBB A,#03H ;源数值高位带借位减1000的高位03H
MOV H_DAT1,A ;余数存回到源数值低位存储单元
INC D_DAT2 ;千位增1
JNC H1000 ;如果没有借位则利用余数循环再减
;有借位表明为最后一次无效减
;程序顺序执行,应还原最后一次修改值
MOV H_DAT0,R6
MOV H_DAT1,R7 ;用备份值作为新的源数值(余数)
DEC D_DAT2 ;千位数减1,去掉最后一次无效减的影响
H100: MOV A,H_DAT0 ;源数值低位装载到累加器A中
MOV R6,A ;备份源数值低位到寄存器R6中
CLR C ;清0进位位C
SUBB A,#100 ;减去100
MOV H_DAT0,A ;存回余数低位
MOV A,H_DAT1 ;取源数值高位
SUBB A,#00H ;减100的高位0,实际上是减去借位位
MOV H_DAT1,A ;存回余数高位
JC H10 ;有借位则跳到下一步继续运算
INC D_DAT3 ;没有借位,百位增1
AJMP H100 ;没有借位继续减
;注意本轮循环中最后一次减时百位未增1
;所以不存在还原的问题
;进入下一轮时,源数值(余数)都在R6中
H10: CLR C
MOV A,R6 ;源数值(低位)装载到累加器A中
;到此源数值高位已经为0,不用再参加计算
MOV D_DAT5,A ;存回源数值低位
;如果是最后一次减,则此值即为个位
SUBB A,#10 ;减去10
MOV R6,A ;保存余数
JC H1 ;有借位,运算结束
INC D_DAT4 ;没有借位,十位增1
LJMP H10 ;没有借位继续减
H1: RET ;子程序返回
END
五、实验现象
功能号为0时,数码管显示被测温度值66,此时按另外两个按键不起作用。
功能号为1时,数码管显示设定温度的上限值80,按两外两个按键可以修改温度上限值
功能号为2时,数码管显示设定温度的下限值60,此时按另外连个按键可以修改温度上限值。
每按一次“↑”键,内存数据区中指定变量单元的值增1,持续按住则连续增1。
每按一次“↓”,内存数据区中指定变量单元的值减1,持续按住则连续减1。
六、思考题
1、 要求单片机P0口连接8个LED指示灯,每个指示灯代表一位二进制数值,利用核心板上的4个按键,实现下述功能:K1按下时指示灯所代表的数值增1,K2减1,K3指示灯左移一位,K4右移一位。画出电路图,并编写实现程序。
LIGHT EQU 64H ;定义LED显示数值存放单元
ORG 0000H
AJMP START
ORG 0030H
START: MOV SP,#30H ;初始化堆栈指针
MOV LIGHT,#0H ;初始化显示数据
ORL P1,#0F0H ;准备读入P1.7,P1.6,P1.5,P1.4的引脚信号
JNB P1.4,KEY1 ;判断K1是否按下,若按下,则P1.4为0,跳转到KEY1
JNB P1.5,KEY1 ;判断K2是否按下,若按下,则P1.5为0,跳转到KEY2
JNB P1.6,KEY1 ;判断K3是否按下,若按下,则P1.6为0,跳转到KEY3
JNB P1.7,KEY1 ;判断K4是否按下,若按下,则P1.7为0,跳转到KEY4
KEY1: INC LIGHT ;K1按下,指示灯所代表值增1
LCALL FLYLED
KEY2: DEC LIGHT ;K2按下,指示灯所代表值减1
LCALL FLYLED
KEY3: MOV A,LIGHT ;K3按下,指示灯所代表值左移1位
RLC A
MOV LIGHT,A
LCALL FLYLED
KEY4: MOV A,LIGHT ;K4按下,指示灯所代表值右移1位
RRC A
MOV LIGHT,A
LCALL FLYLED
;**********************************************
;指示灯点亮程序
;**********************************************
FLYLED: MOV A, LIGHT
CJNE A,#0,FLYCON ;A中不为0则继续
MOV A,#01H ;A中为0,循环完一轮
FLYCON: MOV LIGHT, A
RET
;**********************************************
;延时子程序
;**********************************************
DELAY: MOV R7, #2
DELY1: MOV R6, #0FFH
DELY2: DJNZ R6,$ ;$代表当前行
;与DJNZ R6,DELY2相同
DJNZ R7, DELY1
RET
END
2、 结合程序实例,说明按键防重入,应该如何把握?
如下程序所示
KEND4: LCALL DISP
LCALL DELAY ;刷新显示,延时
DJNZ R4,KEND4 ;此处循环延时是为了避免按键多次重入
LJMP MAIN ;跳转到主程序开始处循环执行