;定义一个输出专用的宏,PORT表示端口地址,DATA表示要输出的数据(8位)
OUT_PORT MACRO PORT,DATA
MOV DX, PORT
MOV AL, DATA
OUT DX, AL
ENDM
;====================================================================
;中断向量设置,X为中断向量,Y为中断子程序名
SET_INT MACRO X,Y
PUSH DS
MOV AX,0
MOV DS,AX
MOV DI,X*4
MOV AX,OFFSET Y
MOV [DI],AX
MOV AX,SEG Y
MOV [DI+2],AX
POP DS
ENDM
; INI_A为偶数口地址,ICW1,ICW2,ICW4为对于要写入的命令,适合与单片8259初始化
INIT_8259 MACRO INI_A,ICW1,ICW2,ICW4
OUT_PORT INI_A,ICW1
OUT_PORT INI_A+2,ICW2
OUT_PORT INI_A+2,ICW4
ENDM
;====================================================================
;8253初始化,INT8253C为命令口地址,X为命令内容,A8253为计数器N的端口,Y为计数初值
INIT_8253 MACRO INT8253C,X,A8253,Y
OUT_PORT INT8253C,X ;命令口
MOV AX,Y
MOV DX,A8253
OUT DX,AL
MOV AL,AH
OUT DX,AL
ENDM
;====================================================================
;X用于表示当前计数单元,NUM用于当前计时最大值(60,24),Y表示下一计数单元,Z为转换的LED编码存储单元
INT_PRO MACRO X,NUM,Y,Z
LOCAL AA
XOR BX,BX
MOV AX,BX ;
MOV AL,X
CMP AL,NUM ;比较秒计数是否到60
JNE AA ;不是,则转AA
INC Y ;是,则分钟加一
MOV AL,0 ;令秒=0
MOV X,AL
AA:
MOV BL,10
DIV BL
MOV BL,AL
MOV AL,LED[BX] ;转换秒的高位
MOV Z,AL
MOV BL,AH
MOV AL,LED[BX] ;转换秒的低位
MOV Z+1,AL
ENDM
;====================================================================
DATA SEGMENT
;4-16译码器输出对应端口
IO1 EQU 10H
IO2 EQU 20H ;8259端口
IO3 EQU 30H ;8255 A口地址
IO4 EQU 40H ;8253 计数器0端口地址
IO5 EQU 50H
IO6 EQU 60H
IO7 EQU 70H
;....
IOA EQU 0A0H
TIMERS EQU 1000 ;计数初值
LED DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H ;0--F对应编码,共阴极
;LED1 DB 0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h,80h,90h,90h,90h,90h,90h,90h
PORTA EQU IO3 ;8255 A口地址
PORTB EQU IO3+2
PORTC EQU IO3+4
PORT_CON EQU IO3+6
T_HOUR DB 0 ;用于小时计数
T_MIN DB 0 ;用于分计数
T_SEC DB 0 ;用于秒计数
TEMP DB 0
HOUR DB 0,0,40H ;用于存放LED显示编码/小时
MINTU DB 0,0,40H
SEC DB 0,0
DATA ENDS
STACK SEGMENT PARA STACK 'STACK' ;堆栈段
DW 1024 DUP (?)
STACK ENDS
CODE SEGMENT PUBLIC 'CODE'
ASSUME CS:CODE,DS:DATA,SS:STACK
START:
MOV AX, DATA
MOV DS, AX ;数据段设置
MOV AX,STACK
MOV SS,AX ;堆栈段设置
CLI ;关中断
;设置中断向量
SET_INT 80H,INT_0 ;接IR0,若要接其他引脚,注意修改中断向量
;初始化8259,按次序写ICW1,ICW2,ICW4
INIT_8259 IO2,13H,80H,03H ;ICW1,边沿触发,单片,需要ICW4,ICW2=80H,ICW4,自动结束
OUT_PORT IO3+6,80H ;8255初始化
INIT_8253 IO4+6,36H,IO4,TIMERS ;8253初始化,方式3,计数器0
INIT_8253 IO4+6,76H,IO4+2,TIMERS ;8253初始化,方式3,计数器1
OUT_PORT IO2+2,00H ;OCW1,全开放
STI ;开中断
L:
CALL DISPLAY ;
JMP L
NOP
INT_0 PROC ;中断服务程序
CLI
PUSH AX
INC T_SEC
INT_PRO T_SEC,60,T_MIN,SEC ;秒
INT_PRO T_MIN,60,T_HOUR,MINTU ;分
INT_PRO T_HOUR,24,TEMP,HOUR ;小时
POP AX
STI
IRET
INT_0 ENDP
DISPLAY PROC NEAR ;LED显示
MOV CX,7F08H ;CH用于控制,CL用于循环
LEA DI,HOUR
DISP_L:
OUT_PORT PORTA,[DI]
OUT_PORT PORTB,CH ;CH决定第几位显示
CALL DELAY
OUT_PORT PORTB,0FFH
INC DI
ROR CH,1
DEC CL
JNZ DISP_L
RET
DISPLAY ENDP
DELAY PROC NEAR
PUSH CX
MOV CX,100 ;延时,根据需要调整
LP2:
LOOP LP2
POP CX
RET
DELAY ENDP
CODE ENDS
END START
放大的地方报错,是为什么呢?
|