秒倒计时器(汇编版)
一、题目
在实验箱上利用单片机定时器/计数器(工作于中断方式)设计一个秒倒计时器,用数码管显示秒数,从100 倒计时至0 s 后从头开始,依次循环。利用实验箱上一个按键控制秒表的启、停,另一个按键作为复位键,返回初始工作状态,重新计时开始。
二、代码
GPIO:
MOV P0M1, #0
MOV P0M0, #0
MOV P1M1, #0
MOV P1M0, #0
MOV P2M1, #0
MOV P2M0, #0
MOV P3M1, #0
MOV P3M0, #0
MOV P4M1, #0
MOV P4M0, #0
MOV P5M1, #0
MOV P5M0, #0
MOV P6M1, #0
MOV P6M0, #0
MOV P7M1, #0
MOV P7M0, #0
RET
P0M1 DATA 0x93 ; P0M1.n,P0M0.n =00--->Standard, 01--->push-pull
P0M0 DATA 0x94 ; =10--->pure input, 11--->open drain
P1M1 DATA 0x91 ; P1M1.n,P1M0.n =00--->Standard, 01--->push-pull
P1M0 DATA 0x92 ; =10--->pure input, 11--->open drain
P2M1 DATA 0x95 ; P2M1.n,P2M0.n =00--->Standard, 01--->push-pull
P2M0 DATA 0x96 ; =10--->pure input, 11--->open drain
P3M1 DATA 0xB1 ; P3M1.n,P3M0.n =00--->Standard, 01--->push-pull
P3M0 DATA 0xB2 ; =10--->pure input, 11--->open drain
P4M1 DATA 0xB3 ; P4M1.n,P4M0.n =00--->Standard, 01--->push-pull
P4M0 DATA 0xB4 ; =10--->pure input, 11--->open drain
P5M1 DATA 0xC9 ; P5M1.n,P5M0.n =00--->Standard, 01--->push-pull
P5M0 DATA 0xCA ; =10--->pure input, 11--->open drain
P6M1 DATA 0xCB ; P6M1.n,P6M0.n =00--->Standard, 01--->push-pull
P6M0 DATA 0xCC ; =10--->pure input, 11--->open drain
P7M1 DATA 0xE1
P7M0 DATA 0xE2
AUXR DATA 0x8E
P6 DATA 0xE8
P7 DATA 0xF8
ORG 0x00
LJMP MAIN
ORG 000BH
LJMP T0IT
ORG 0200H
MAIN:
LCALL GPIO
ANL AUXR,#7FH ;定时器时钟12T模式
ANL TMOD,#0F0H ;设置定时器模式
MOV TL0,#0F0H ;设置定时初始值
MOV TH0,#0D8H ;设置定时初始值
CLR TF0 ;清除TF0标志
SETB TR0 ;开启TR0
SETB EA ;开启总中断
SETB ET0 ;开启定时器0允许标志位
MOV R7, #0 ;标志变量,为0时暂停,1时启动
MOV 50H,#9 ;50H存储个位数,初始值9
MOV 51H,#9 ;51H存储十位数,初始值9
MOV R0, #50H ;R0存入地址50H
LOOP:
LCALL NIXIE ;数码管显示
LCALL JUDGE ;按键检测函数
SJMP LOOP
JUDGE:
JB P3.2, Stop ;P32==1就停止
MOV A, R7 ;将A(R7)作为开始暂停的标志变量,每按一次P32,A加1
INC A
CJNE A, #2, FLAG ;A等于2就变为0暂停,等于1就启动
CLR A ;A等于2就A清0
FLAG:
MOV R7, A ;A将按键按完之后的标志变量值赋给R7
CJNE R7, #1, Stop ;R7为0停止运行,为1开始运行
Start: ;开启
CLR A ;A作为中断里面的计数,进入前要清0
SETB ET0 ;允许定时器中断请求
RET
Stop: ;暂停
CLR ET0 ;关闭定时器中断请求
CJNE R7, #0, Start ;R7为1时开始运行
RET
T0IT:
CIR:
LCALL NIXIE ;数码管显示
LCALL JUDGE
JNB TF0, CIR
CLR TF0
INC R4 ;R4记录5ms的次数
CJNE R4, #200, CIR ;当R4为200次,也就是1s的时候
MOV R4, #0 ;清空R4
MOV R0, #50H ;取个位数到A里面
MOV A, @R0
DEC A ;每200次(1s),个位数就减一
CJNE A, #-1, NOTNINE
MOV A, #9 ;减完结果是-1的话,A为9
NOTNINE:
MOV R3, A ;最终个位的值存入R3
CJNE R3, #9, CONTINUE ;减完结果为9的话,要把十位也减一
MOV R0, #51H
MOV A, @R0
DEC A ;十位减一
CJNE A, #-1, INIT ;十位为0的时候,把十位置为9
MOV A, #9
INIT:
MOV R5, A ;十位值存入R5
MOV 50H, R3 ;个位数减完等于9要记录R3和R5的值,存入50H和51H
MOV 51H, R5
RETI
CONTINUE:
MOV 50H, R3 ;个位数减完不等于9只用记录R3的值,存入50H
RETI
NIXIE:
MOV R0, #50H ;个位的值移到R0
MOV P7, #0FEH ;第一个数码管点亮
MOV A, @R0 ;把个位值存到A
MOV DPTR, #NUM
MOVC A, @A+DPTR ;读取数字
MOV P6, A ;显示
LCALL DELAY1MS
MOV P6, #0FFH ;消影
MOV P7, #0FDH ;点亮第二个数码管
INC R0 ;十位的值移到R0
MOV A, @R0
MOV DPTR, #NUM
MOVC A, @A+DPTR
MOV P6, A
LCALL DELAY1MS
MOV P6, #0FFH
RET
NUM:
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0BFH
DELAY1MS: ;延时1ms@24.000MHz
NOP
PUSH 30H
PUSH 31H
MOV 30H,#19
MOV 31H,#168
NEXT:
DJNZ 31H,NEXT
DJNZ 30H,NEXT
POP 31H
POP 30H
RET
$INCLUDE(gpio.inc)
END
总结
此篇文章是本人没有参考例程直接写的,中断里面的部分代码和标准的汇编中断有些区别,如若追求完美建议查找资料自行修改。
非常感谢各位观看!!!
系列文章——STC8H8K系列汇编51实战
基于ESP8266与STC单片机的天气时钟(包括DS18B20、TFT、串口、外部中断、ESP8266、STC、API等)
STC8H8K系列汇编和C51实战——实现键控不同方式数码管动态显示(C51版与汇编版)
STC8H8K系列汇编和C51实战——开关控制定时器秒表(C51版)
STC8H8K系列汇编和C51实战——开关控制定时器秒表(汇编版)
STC8H8K系列汇编和C51实战——双中断控制定时器流水灯
STC8H8K系列汇编和C51实战——秒倒计时器(可自行设定初值)(51版)
STC8H8K系列汇编和C51实战——按键允许按键计数(51版)
STC8H8K系列汇编和C51实战——按键允许按键计数(汇编版)
STC8H8K系列汇编和C51实战——按键允许按键计数(定时器去抖动51版)
STC8H8K系列汇编和C51实战——按键允许按键计数(利用下降沿中断控制)
STC8H8K系列汇编和C51实战——计算机串口控制单片机LED