本文包含原理图、PCB、源代码、封装库、中英文PDF等资源
您需要 登录 才可以下载或查看,没有账号?注册会员
×
现在是这样的,我有K1和K2两个按键,程序写入后,显示00:00:00,按下K1键开始计时,再次按下K1键是暂停,再K1按继续计时,依次循环。如果按下K2,则复位,回到00:00:00。
现在,我想实现这样的功能,只用K1键,第一次按下计时,第二次按下暂停,第三次按下复位。不用K2,程序怎么改?
我现在的头绪是,设置一个累加器,一开始是0,按一次加1,当累加器到3时,自动清零,K1复位。请问程序怎么改?
我有电气原理图,K1接P2.0,K2接P2.1,其他按键不管。1602接P0口。
以下是之前的程序。
TLOW EQU 0CH ;定时器初值
THIGH EQU 0DCH
HOUR EQU 30H
MIN EQU 31H
SEC EQU 32H
SEC0 EQU 33H ;10ms计数值
KEY_D EQU 34H ;为键当前的端口状况
KEY_S EQU 35H ;为键上次的端口状况
X EQU 36H ;LCD 地址变量
KEY_C EQU 37H ;键计数单元
K1 EQU P2.0
K2 EQU P2.1
BEEP EQU P1.4
RS EQU P2.6 ;LCD控制端口定义
RW EQU P2.5
EN EQU P2.7
ORG 0000H
LJMP START
ORG 0BH
LJMP T0_INT
START: MOV R3,#00H
MOV SP,#60H
CLR EN
LCALL SET_LCD
LCALL INIT ;初始化变量
MOV KEY_S,#01H
LCALL INIT_TIMER ;初始化定时器
; CALL MENU
LOOP: LCALL CONV ;时间计数处理
LCALL SKEY
MOV KEY_S,KEY_D
JZ XP
MOV A, KEY_S
JB ACC.0,XP
CLR A
MOV B,A
INC R3
MOV A,R3
MOV B,#2
DIV AB
MOV A,B
LCALL BZ
JZ XPP
SETB TR0 ;启动中断
MOV DPTR,#MADJ ;显示执行信息
LCALL P_KEY
LJMP XP
XPP:
CLR TR0
MOV DPTR,#MADJ1
LCALL P_KEY
XP: JB K2,LOOP ;判清零键是否按?
MOV R3,#00H
LCALL BZ
LJMP START
;---------------------------------------
P_KEY: MOV A,#1 ;第一行显示
LCALL LCD_PRINT
RET
;---------------------------------------
SKEY: CLR A ;判是否有键按下子程序
MOV KEY_D,A
MOV C,K1
RLC A
ORL KEY_D,A
MOV A,KEY_D
XRL A,KEY_S ;有键按下,A 中内容不为零
RET
INIT: CLR A ;初始化控制变量
MOV SEC0,A
MOV SEC,A
MOV MIN,A
MOV HOUR,A
MOV KEY_D,A
MOV KEY_S,A
SETB BEEP
CLR TR0
RET
;------------------------------------------------------------
;初始化定时器接口
INIT_TIMER:MOV TMOD,#01H ;设置定时器0 工作模式为模式1
MOV IE, #82H ;启用定时器0 中断产生
MOV TL0,#TLOW
MOV TH0,#THIGH
RET
;-------------------------------------------------------------
T0_INT: PUSH ACC ;定时器0计时中断程序
MOV TL0,#TLOW
MOV TH0,#THIGH
INC SEC0
MOV A,SEC0 ;10ms 计数值加1
CJNE A,#100,TT
MOV SEC0,#0
INC SEC ;秒加1
MOV A,SEC
CJNE A,#60,TT
INC MIN ;分加1
MOV SEC,#0
MOV A,MIN
CJNE A,#60,TT
INC HOUR ;时加1
MOV MIN,#0
MOV A,HOUR
CJNE A,#24,TT
MOV SEC0,#0
MOV SEC,#0 ;秒、分、时单元清0
MOV MIN,#0
MOV HOUR,#0
TT: POP ACC
RETI
;-------------------------------------------------------
; 在第二行显示数字
;-------------------------------------------------------
;在 LCD 的第二行显示数字
SHOW_DIG2:MOV B,#10 ;设置被除数
DIV AB ;结果A存商数,B存余数
ADD A,#30H ;A为十位数,转换为字符
PUSH B ;B放入堆栈暂存
MOV B,X ;设置 LCD 显示的位置
LCALL LCDP0 ;由 LCD 显示出来
POP B ;
MOV A,B ;B为个位数
ADD A,#30H ;转换为字符
INC X ;LCD 显示位置加1
MOV B,X ;设置 LCD 显示的位置
LCALL LCDP0 ;由 LCD 显示出来
RET
;-------------------------------------------
;转换为 ASCII 码并显示
;-------------------------------------------
CONV:
MOV A,HOUR ;加载小时数据
MOV X,#5 ;设置位置
LCALL SHOW_DIG2 ;显示数据
INC X ;
MOV A,#':' ;
MOV B,X ;
LCALL LCDP0 ;
MOV A,MIN ;加载分钟数据
INC X ;设置位置
LCALL SHOW_DIG2 ;显示数据
INC X ;
MOV A,#':' ;
MOV B,X ;
LCALL LCDP0 ;
MOV A,SEC ;加载秒数数据
INC X ;设置位置
LCALL SHOW_DIG2 ;显示数据
INC X ;
MOV A,#':' ;
MOV B,X ;
LCALL LCDP0 ;
MOV A,SEC0 ;加载秒数数据
INC X ;设置位置
LCALL SHOW_DIG2
RET
;---------------------------------------------------------
; LCD CONTROL
;---------------------------------------------------------
SET_LCD: ;对 LCD 做初始化设置及测试
CLR EN
LCALL INIT_LCD ;初始化 LCD
MOV R5,#10
LCALL DELAY
MOV DPTR,#MMENU ;指针指到显示消息1
MOV A,#1 ;显示在第一行
LCALL LCD_PRINT
MOV DPTR,#SLF ;指针指到显示消息2
MOV A,#2 ;显示在第二行
LCALL LCD_PRINT
RET
;----------------------------------------------------------
INIT_LCD1: ;LCD 控制指令初始化
MOV A,#38H ;;双列显示,字形5*7点阵
LCALL WCOM ;
LCALL DELAY1
MOV A,#0CH ;;开显示,显示光标,光标不闪烁
LCALL WCOM ;
LCALL DELAY1
MOV A,#01H ;;清除 LCD 显示屏
LCALL WCOM ;
LCALL DELAY1
RET
;----------------------------------------------------------
ENABLE: ;写指令
CLR RS ;RS=L,RW=L,E=高脉冲
CLR RW ;D0-D7=指令码
SETB EN
LCALL DELAY1
CLR EN
RET
;----------------------------------------------------------
LCD_PRINT: ;在LCD的第一行或第二行显示字符
CJNE A,#1,LINE2 ;判断是否为第一行
LINE1: MOV A,#80H ;设置 LCD 的第一行地址
LCALL WCOM ;写入命令
LCALL CLR_LINE ;清除该行字符数据
MOV A,#80H ;设置 LCD 的第一行地址
LCALL WCOM ;写入命令
LJMP FILL
LINE2: MOV A,#0C0H ;设置 LCD 的第二行地址
LCALL WCOM ;写入命令
LCALL CLR_LINE ;清除该行字符数据
MOV A,#0C0H ;设置 LCD 的第二行地址
LCALL WCOM
FILL: CLR A ;填入字符
MOVC A,@A+DPTR ;由消息区取出字符
CJNE A,#0,LC1 ;判断是否为结束码
RET
LC1: LCALL WDATA ;写入数据
INC DPTR ;指针加1
LJMP FILL ;继续填入字符
RET
;-------------------------------------------------------
CLR_LINE: ;清除该行 LCD 的字符
MOV R0,#16
CL1: MOV A,#' '
LCALL WDATA
DJNZ R0,CL1
RET
;-------------------------------------------------------
DE: MOV R7,#250 ;延时500微秒
DJNZ R7,$
RET
;-------------------------------------------------------
EN1:
CLR RW
SETB EN ;短脉冲产生启用信号
LCALL DE
CLR EN
LCALL DE
RET
;------------------------------------------------------
INIT_LCD: ;8位I/O控制 LCD 接口初始化
MOV P0,#38H ;双列显示,字形5*7点阵
LCALL ENABLE
LCALL DELAY1
MOV P0,#38H ;双列显示,字形5*7点阵
LCALL ENABLE
LCALL DELAY1
MOV P0,#38H ;双列显示,字形5*7点阵
LCALL ENABLE
LCALL DELAY1
LCALL INIT_LCD1
RET
;-----------------------------------------------------
WCOM: ;以8位控制方式将命令写至LCD
MOV P0,A ;写入命令
LCALL ENABLE
RET
;-----------------------------------------------------
WDATA: ;以8位控制方式将数据写至LCD
MOV P0,A ;写入数据
SETB RS ;设置写入数据
LCALL EN1
RET
;-----------------------------------------------------
;第二行显示字符
;-----------------------------------------------------
LCDP0: ;在LCD的第二行显示字符
PUSH ACC ;
MOV A,B ;设置显示地址
ADD A,#0C0H ;设置LCD的第二行地址
CALL WCOM ;写入命令
POP ACC ;由堆栈取出A
LCALL WDATA ;写入数据
RET
;----------------------------------------------------
DELAY: ;延时10MS
MOV R6,#50
D1: MOV R7,#100
DJNZ R7,$
DJNZ R6,D1
DJNZ R5,DELAY
RET
;-----------------------------------------------------
DELAY1: ;延时5MS
MOV R6,#25
D2: MOV R7,#100
DJNZ R7,$
DJNZ R6,D2
RET
;-----------------------------------------------------
BZ: ;蜂鸣器
MOV R6,#100
B1: LCALL DEX
CPL BEEP
DJNZ R6,B1
MOV R5,#10
LCALL DELAY
RET
DEX: MOV R7,#180
DE1: NOP
DJNZ R7,DE1
RET
;-------------------------------------------------
MMENU: DB " SECOND-CLOCK ",00H
SLF: DB "TIME: ",00H ;LCD 第二行显示消息
MADJ: DB " BEGIN COUNT ",00H
MADJ1: DB " PAUST COUNT ",00H
END |