📄 clock24.asm
字号:
;*****************************************
;程序功能:在MCU#3中的数码管上显示一个时钟
;程序是用中断方式来处理的,也可以自己改写为查询方式
;*****************************************
ORG 0000H
AJMP START
;=============================================
;中断入口
ORG 000BH
AJMP T0INT
;=============================================
;RAM区变量定义
DISBUF EQU 30H ;显示参数传递
POSIT EQU 38H ;位选
NUM EQU 40H ;秒循环次数
SEC EQU 50H ;秒
MIN EQU 51H ;分钟
HOR EQU 52H ;小时
;=============================================
;程序开始部分(主函数)
ORG 0100H
START:
MOV SP, #60H ;设置堆栈指针位置
MOV TMOD, #01H ;设置定时器T0的工作方式为定时器模式,方式一
MOV TH0, #42H ;给定时器赋初值
MOV TL0, #0A0H
MOV DISBUF+2, #16 ;给显示部分赋值"-"
MOV DISBUF+5, #16
MOV SEC, #0 ;设置秒的初值
MOV MIN, #59 ;设置分钟的初值
MOV HOR, #23 ;设置小时的初值
MOV NUM, #19 ;设置定时器循环的次数,也就是确定循环多少次为一秒
SETB TR0 ;启动定时计数器T0
SETB ET0 ;开启定时计数器T0的中断
SETB EA ;开启单片机的总中断
LOOP: LCALL CHANGE ;调用小时,分秒处理子程序
LCALL DISPLAY ;调用显示程序
AJMP LOOP
;=============================================
;8路数码管驱动
DISPLAY:
MOV POSIT, #80H ;用于指示数码管位选,初始化为第一个数码管亮
MOV R1, #08H ;用于指示程序循环,8个数码管每个送一次数后,本子程序结束
MOV DPTR, #DISCODE ;指向数码管的码表
MOV R0, #DISBUF ;指向显示数组
DISLOOP: ;为方便起见,只将第一个数码管的执行过程讲明,其余依次类推
MOV A, @R0 ;当R0=#DISBUF时,通过间接寻址将DISBUF中的内容放入A中
MOVC A, @A+DPTR ;通过查表,A为地址偏移量,找出A中的数所对应的码值(即段码),还放在A中
MOV P0, A ;将A中的数送至P0端口,单此时并未送至数码管
SETB P1.3 ;使能573锁存器,此时,段码才送至数码管的段选端
CLR P1.3 ;关闭573锁存器,此时,数据锁存在数码管的段选端
MOV P0, POSIT ;送位选至P0,以便指示哪一个数码管亮
SETB P1.2 ;使能573锁存器,此时,位选信号才送至数码管的位选端,相应的数码管亮
CLR P1.2 ;关闭573锁存器,此时,数据锁存在数码管的位选端
CALL DELAY ;使相应数码管亮一段时间
MOV P0, #00H ;送位选为00至P0口,即关闭所有的数码管,一产生消隐作用,避免数码管上产生重影现象
SETB P1.2
CLR P1.2
MOV A, POSIT ;当一个数码管完成显示后,对位选进行移位操作,以便为下一个数码管
RR A ;的显示作好准备,此时,位选指向下一个数码管
MOV POSIT, A
INC R0 ;使R0的数自加一,指向下一个要显示的数字,若上一次指向DISBUF,则
DJNZ R1, DISLOOP ;本次指向DISBUF+1,并受R1控制,完成8个数在数码管上的显示
RET ;所以,在使用此显示程序时,只需将欲显示的数字放入对应的DISBUF即可
;================================================
;延时程序
DELAY:
MOV R3, #0FH
DJNZ R3, $
RET
;================================================
;显存更新程序
CHANGE:
PUSH ACC ;保护现场,将累加器A入栈
MOV A, SEC ;将秒变量分十位和个位,分别存放在两个显存空间中
MOV B, #10
DIV AB
MOV DISBUF+6, A
MOV DISBUF+7, B
MOV A, MIN ;将分变量分十位和个位,分别存放在两个显存空间中
MOV B, #10
DIV AB
MOV DISBUF+3, A
MOV DISBUF+4, B
MOV A, HOR ;将小时变量分十位和个位,分别存放在两个显存空间中
MOV B, #10
DIV AB
MOV DISBUF, A
MOV DISBUF+1, B
POP ACC ;释放累加器A
RET
;================================================
;定时器T0中断服务程序
T0INT:
PUSH ACC ;保护现场,将累加器A入栈
MOV TL0, #0A0H ;重新赋初值
MOV TH0, #42H
DJNZ NUM, OUT ;判断1秒时间是否到达
MOV NUM, #19
INC SEC ;如果1秒时间到达,对秒加一
MOV A, SEC
CJNE A, #60, OUT ;判断秒是否超过60
MOV SEC, #0 ;如果超过60,将秒变量清零,同时将分变量加一
INC MIN
MOV A, MIN
CJNE A, #60, OUT ;判断分变量是否超过60
MOV MIN, #0 ;如果超过60,将分变量清零,同时将小时变量加一
INC HOR
MOV A, HOR
CJNE A, #24, OUT ;判断小时变量是否超过23
MOV HOR, #0 ;超过23,对小时变量清零
OUT:
POP ACC ;释放累加器A
RETI
;================================================
;共阳数码管码表
DISCODE:
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
; 0 1 2 3 4 5 6 7 8 9
DB 88H,83H,0C6H,0A1H,86H,08EH,0BFH,0FFH,0F7H
; A B C D E F - 消隐 _
;================================================
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -