实验5 按键功能的实现
一、实验目的
1、理解按键电路的作用;
2、学习按键功能的编程方法;
3、熟悉单片机I/O口连接式按键的编程应用方法。
二、实验说明
按键在单片机应用系统中实现向单片机输入数据、传送命令等功能,是人工干预单片机工作的主要手段。如果需要较多数量的按键,可以采用按键矩阵和专门的接口器件扩展按键。实际的单片机应用系统中,用到的按键数量一般不多,通常采用单片机I/O口和式按键即能满足需要。
实验箱核心板上有 4 个按键,其一端全部与地线相连,另一端顺次与 P1.4~P1.7 相连。本实验需要用到核心板上的 3 个按键、3 个指示灯和 6 个数码管,所用到的实验电路原理如图 3.1.6 所示。
本实验中 3 个按键设计的功能,是一个实用的简单温度控制系统的按键功能,要求通过按键设定一个温度上限值和一个温度下限值。本实验只涉及按键和显示功能,在今后的实验中,将进一步增加硬件和软件功能,利用单片机实现实际的温度控制系统,使温度维持在上、下限值之间。
①“功能”键:在内存数据区定义一个名称为“KBM”的字节,存放功能编号,共有 3 种功能,分别对应编号为 0,1,2。每按一次“功能”键,“KBM”中的值在这三个数字中循环改变一次。与三种功能对应,设计三个 LED(发光二极管)指示灯,由单片机 P3 口控制,当处于某种功能状态时,相应的指示灯亮。本实验的内容,实际上是后面进一步做温度测量控制系统的一部分。三种功能的
含义如下:
功能号 0:显示测量的温度值;
功能号 1:对温度上限值进行修改;
功能号 2:对温度下限值进行修改。
②“↑”键:每按一次“↑”键,内存数据区中指定变量单元的值增 1,持续按住则连续增 1。
③“↓”键:与“↑”键对应,每按一次“↓”,内存数据区中指定变量单元的值减 1,持续按住则连续减 1。
功能号为 0 时,数码管显示被测温度值,此时按另外两个按键不起作用。功能号为 1 时,数码管显示设定温度的上限值,按另外两个按键可以修改温度上限值。功能号为 2 时,数码管显示设定温度的下限值,此时按另外两个按键可以修改温度下限值。
3、实验任务
1、理解单片机I/O口与按键、指示灯和LED数码管的综合使用方法;
2、理解图3.1.6所示的电路,读懂参考程序;
3、自行设计按键显示功能(比如将6位数码管分成三组,分别显示上限、下限、测量值),并编程实现所设计的功能。
4、程序流程图及代码分析
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
定义显示数据单元KBM=3?是KBM置零否定义按键功能号存放单元定义上限值存放单元、下限值、测量值初始化堆栈指针否KBM=0?否KBM=1?否KBM=2?是是准备显示测量数据点亮相应指示灯准备显示上限值点亮相应指示灯准备显示下限值点亮相应指示灯初始化显示数据、有关I/O口初始化数据指针,R0指向第一位显示数字及其数码管位置代码;产生一个指示灯输出锁存脉冲调用HTD子程序设定循环次数R4=40H调用DISP初始化功能号,上、下限值调用DELAY将测量值二进制数转换为十进制数调用DISP子程序调用DELAY子程序否R4=0?是KBM=2?否是是是DEC D_MIN否P1.5=0?否KBM=1?DEC D_MAXP1.7=0?否是P1.6=0?是KBM=1?否是INC D_MAX功能号增1KBM=2?是否INC D_MIN
5、实验现象
数码管能正确显示,能正确实现按键的功能。
6、实验小结
本实验重在掌握按键电路的实现,实验程序较为复杂,需要多花功夫理解。
思考题:
1、 实验程序如下:
MOV A,#12H
MOV P0,A
MAIN:JNB P1.4,K1
JNB P1.5,K2
JNB P1.6,K3
JNB P1.7,K4
AJMP MAIN
K1: INC A
MOV P0,A
LCALL DELAY
LOOP1:JNB P1.4,LOOP1
AJMP MAIN
K2: DEC A
MOV P0,A
LCALL DELAY
LOOP2:JNB P1.5,LOOP2
AJMP MAIN
K3: RL A
MOV P0,A
LCALL DELAY
LOOP3:JNB P1.6,LOOP3
AJMP MAIN
K4: RR A
MOV P0,A
LCALL DELAY
LOOP4:JNB P1.7,LOOP4
AJMP MAIN
DELAY:MOV R7,#255
DELAY1:MOV R6,#0
NOP
NOP
NOP
DJNZ R6,$
NOP
NOP
NOP
NOP
DJNZ R7,DELAY1
RET
END