求助!一个51单片机长按键调整定时时钟,调节位闪烁的一...
时间:10-02
整理:3721RD
点击:
我写了一个程序,是单片机P2.4按键复用,长按可以开始使设定位(R6)闪烁,其余正常显示,短按则不管,正常显示4位数码管。昨天调了一天,今天早上又调了,仍然没有找到最根本的问题!真心求助!
这段程序思想是,长按键则启动定时器1,使得每到一定时间闪烁标志位取反,为0时正常显示我设定的MIN,SEC,为1时除设定位R6灭,其余都正常显示,数码管在设定某计时位时就可以闪烁了
这是程序:
MIN EQU 34H ;分钟显示
SEC EQU 35H ;秒显示
BUF EQU 36H ;MIN,SEC加载进buf
FLASHFLAG EQU F0 ;闪烁标志位
COUNT EQU 37H ;中断计数器,计满100次则取反闪烁标志位
COUNTER EQU 38H ;按键计数器,大于此值为长按,小于为短按
FN EQU P2.4 ;功能键,长按后进入闪烁显示
ORG 0000H
AJMP MAIN
ORG 001BH
AJMP T1_SURV
ORG 0100H
MAIN:
MOV R1,#40H ;把字模表放在R1为地址的内部ram里
MOV @R1,#3fH
INC R1
MOV @R1,#06H
INC R1
MOV @R1,#5bH
INC R1
MOV @R1,#4fH
INC R1
MOV @R1,#66H
INC R1
MOV @R1,#6dH
INC R1
MOV @R1,#7dH
INC R1
MOV @R1,#07H
INC R1
MOV @R1,#7fH
INC R1
MOV @R1,#6fH
INC R1
MOV @R1,#77H
INC R1
MOV @R1,#7cH
INC R1
MOV @R1,#39H
INC R1
MOV @R1,#5EH
INC R1
MOV @R1,#79H
INC R1
MOV @R1,#71h
MOV R1,#40H
CLR C
MOV MIN,#21 ;这为了调试方便,直接设要显示的为21,56
MOV SEC,#56
MOV R6,#3 ;为了方便,设要调的是第3位,也就是要闪烁的一位
MAIN_LOOP:
ACALL CONV1 ;调用加载函数
ACALL DISP1 ;调用显示函数
JNB FN,FUN2
AJMP MAIN_LOOP
FUN2:
INC COUNTER ;COUNTER计数中
ACALL DELAY1
JB FN,FUN1
AJMP FUN2
FUN1: ;计数完判断长按/短按
CLR C
PUSH ACC
MOV A,COUNTER
MOV COUNTER,#0
CJNE A,#50,UNEQUAL
POP ACC
ACALL MODULATE
UNEQUAL: JC MAIN_LOOP
MODULATE: ACALL INT_TIMER1 ;长按启动定时器1
AJMP MAIN_LOOP
/*时间加载函数*/
CONV1:
MOV R1,#40H
MOV A,MIN
MOV B,#10
div AB
ADD A,R1
MOV R1,A
MOV A,@R1
MOV BUF,A
MOV R1,#40H
MOV A,B
ADD A,R1
MOV R1,A
MOV A,@R1
MOV BUF+1,A
MOV R1,#40H
MOV A,SEC
MOV B,#10
div AB
ADD A,R1
MOV R1,A
MOV A,@R1
MOV BUF+2,A
MOV R1,#40H
MOV A,B
ADD A,R1
MOV R1,A
MOV A,@R1
MOV BUF+3,A
MOV R1,#40H
RET
/*显示函数*/
DISP1:
MOV R0,#buf
PUSH 36H
S1:
JNB FLASHFLAG,STABLE_DISP ;如果FLASHFLAG=0,则越过闪烁部分
FLASH_DISP:
CJNE R6,#1,GOTO1 ;R6记录调整位
FLASH_BIT1:
MOV BUF,#00H ;第一位灭时段码0x00
AJMP STABLE_DISP
GOTO1:
CJNE R6,#2,GOTO2
FLASH_BIT2:
MOV BUF+1,#00H
AJMP STABLE_DISP
GOTO2:
CJNE R6,#3,GOTO3
FLASH_BIT3:
MOV BUF+2,#00H
AJMP STABLE_DISP
GOTO3:
CJNE R6,#4,STABLE_DISP
FLASH_BIT4:
MOV BUF+3,#00H
STABLE_DISP:
MOV R2,#4
MOV ACC,#0F7H
S0: PUSH ACC
MOV A,@R0
MOV P0,#0 ;避免叠影,先清端口
MOV P0,A
POP ACC
MOV P2,ACC
ACALL DELAY1
RR A
INC R0
DJNZ R2,S0
POP 36H
RET
/*延时子程序*/
DELAY1: MOV R3,#1 ;延时2ms
D2:MOV R4,#10
D1:MOV R5,#100
DJNZ R5,$
DJNZ R4,D1
DJNZ R3,D2
RET
/*定时器1初始化*/
INT_TIMER1: //中断后,闪烁标志位取反
MOV TMOD,#10H //定时器1的工作方式1
MOV TH1,#0F8H
MOV TL1,#2fH
MOV COUNT,#0
SETB EA
SETB ET1
SETB TR1
RET
/*定时器1中断服务程序*/
T1_SURV: //50ms中断
PUSH ACC
MOV TH1,#0F8H
MOV TL1,#2FH
INC COUNT
MOV A,COUNT
CJNE A,#250,RNT
CPL FLASHFLAG ;取反调时闪烁标志位
RNT: POP ACC
MOV COUNT,#0
RETI ;中断返回
END
这段程序思想是,长按键则启动定时器1,使得每到一定时间闪烁标志位取反,为0时正常显示我设定的MIN,SEC,为1时除设定位R6灭,其余都正常显示,数码管在设定某计时位时就可以闪烁了
这是程序:
MIN EQU 34H ;分钟显示
SEC EQU 35H ;秒显示
BUF EQU 36H ;MIN,SEC加载进buf
FLASHFLAG EQU F0 ;闪烁标志位
COUNT EQU 37H ;中断计数器,计满100次则取反闪烁标志位
COUNTER EQU 38H ;按键计数器,大于此值为长按,小于为短按
FN EQU P2.4 ;功能键,长按后进入闪烁显示
ORG 0000H
AJMP MAIN
ORG 001BH
AJMP T1_SURV
ORG 0100H
MAIN:
MOV R1,#40H ;把字模表放在R1为地址的内部ram里
MOV @R1,#3fH
INC R1
MOV @R1,#06H
INC R1
MOV @R1,#5bH
INC R1
MOV @R1,#4fH
INC R1
MOV @R1,#66H
INC R1
MOV @R1,#6dH
INC R1
MOV @R1,#7dH
INC R1
MOV @R1,#07H
INC R1
MOV @R1,#7fH
INC R1
MOV @R1,#6fH
INC R1
MOV @R1,#77H
INC R1
MOV @R1,#7cH
INC R1
MOV @R1,#39H
INC R1
MOV @R1,#5EH
INC R1
MOV @R1,#79H
INC R1
MOV @R1,#71h
MOV R1,#40H
CLR C
MOV MIN,#21 ;这为了调试方便,直接设要显示的为21,56
MOV SEC,#56
MOV R6,#3 ;为了方便,设要调的是第3位,也就是要闪烁的一位
MAIN_LOOP:
ACALL CONV1 ;调用加载函数
ACALL DISP1 ;调用显示函数
JNB FN,FUN2
AJMP MAIN_LOOP
FUN2:
INC COUNTER ;COUNTER计数中
ACALL DELAY1
JB FN,FUN1
AJMP FUN2
FUN1: ;计数完判断长按/短按
CLR C
PUSH ACC
MOV A,COUNTER
MOV COUNTER,#0
CJNE A,#50,UNEQUAL
POP ACC
ACALL MODULATE
UNEQUAL: JC MAIN_LOOP
MODULATE: ACALL INT_TIMER1 ;长按启动定时器1
AJMP MAIN_LOOP
/*时间加载函数*/
CONV1:
MOV R1,#40H
MOV A,MIN
MOV B,#10
div AB
ADD A,R1
MOV R1,A
MOV A,@R1
MOV BUF,A
MOV R1,#40H
MOV A,B
ADD A,R1
MOV R1,A
MOV A,@R1
MOV BUF+1,A
MOV R1,#40H
MOV A,SEC
MOV B,#10
div AB
ADD A,R1
MOV R1,A
MOV A,@R1
MOV BUF+2,A
MOV R1,#40H
MOV A,B
ADD A,R1
MOV R1,A
MOV A,@R1
MOV BUF+3,A
MOV R1,#40H
RET
/*显示函数*/
DISP1:
MOV R0,#buf
PUSH 36H
S1:
JNB FLASHFLAG,STABLE_DISP ;如果FLASHFLAG=0,则越过闪烁部分
FLASH_DISP:
CJNE R6,#1,GOTO1 ;R6记录调整位
FLASH_BIT1:
MOV BUF,#00H ;第一位灭时段码0x00
AJMP STABLE_DISP
GOTO1:
CJNE R6,#2,GOTO2
FLASH_BIT2:
MOV BUF+1,#00H
AJMP STABLE_DISP
GOTO2:
CJNE R6,#3,GOTO3
FLASH_BIT3:
MOV BUF+2,#00H
AJMP STABLE_DISP
GOTO3:
CJNE R6,#4,STABLE_DISP
FLASH_BIT4:
MOV BUF+3,#00H
STABLE_DISP:
MOV R2,#4
MOV ACC,#0F7H
S0: PUSH ACC
MOV A,@R0
MOV P0,#0 ;避免叠影,先清端口
MOV P0,A
POP ACC
MOV P2,ACC
ACALL DELAY1
RR A
INC R0
DJNZ R2,S0
POP 36H
RET
/*延时子程序*/
DELAY1: MOV R3,#1 ;延时2ms
D2:MOV R4,#10
D1:MOV R5,#100
DJNZ R5,$
DJNZ R4,D1
DJNZ R3,D2
RET
/*定时器1初始化*/
INT_TIMER1: //中断后,闪烁标志位取反
MOV TMOD,#10H //定时器1的工作方式1
MOV TH1,#0F8H
MOV TL1,#2fH
MOV COUNT,#0
SETB EA
SETB ET1
SETB TR1
RET
/*定时器1中断服务程序*/
T1_SURV: //50ms中断
PUSH ACC
MOV TH1,#0F8H
MOV TL1,#2FH
INC COUNT
MOV A,COUNT
CJNE A,#250,RNT
CPL FLASHFLAG ;取反调时闪烁标志位
RNT: POP ACC
MOV COUNT,#0
RETI ;中断返回
END