Proteus+汇编+8086实现电子时钟 第一篇 动态扫描

Proteus+汇编+8086实现电子时钟 第一篇 动态扫描

摘要

本专栏介绍在Proteus软件中使用汇编语言,8086作为控制器,实现电子时钟。以下是实现功能
要求
这是第一篇,介绍动态扫描的实现,分为原理,原理图和代码,原理解析(主要是为什么要关位码)三个部分。

动态扫描原理

动态扫描其实就是在很短的时间里快速闪过每一位数字,快到让人眼分辨不清,就实现了“同时”显示多位数字的效果。

原理图和代码

本文中采用的是共阳极数码管。

TABCODE DB	0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h,80h,90h		;共阳极数码管。0-9位码

显示模块

ABCDEGFG送位码,DP是小数点,12345678送段码。

数据段和堆栈段定义

;数据段
 DATA SEGMENT
 ORG 100H
	    PORTA EQU 8000H
	    PORTB EQU 8002H
	    PORTC EQU 8004H
	    TCONTRO   EQU 0A006H
	    TCON0     EQU 0A000H
	    TCON1     EQU 0A002H
	    A8259  EQU   0C000H 
	    B8259  EQU   0C002H
	    TABCODE DB	0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h,80h,90h		;共阳极数码管。0-9位码
	    TABADD  DB  80H,40H,10H,08H,02H,01H					;这里没有用所有数码管
	    
	    HOUR  DW  0203H;非压缩BCD数
	    MINUTE DW 0509H
	    SECOND DW 0502H
	    COUNT DB 00H
	    SELECTED DW 0000H
	    ALARMHOUR DW 0000H
	    ALARMMINUTE DW 0000H
	    ALARMSECOND DW 0000H
	    FLAG DB 00H    ;为0表示不设闹钟,为1表示输入时,为2输入分,为3输入秒
	    
DATA ENDS
;栈堆段

STACK   SEGMENT 
STA     DB  1000H DUP(0)
TOP     EQU LENGTH STA
STACK   ENDS     

 END START  

延时函数DELAY

;短延时函数,用于正常显示
DELAY:
	PUSH CX
	MOV CX,000Ah
	LOOP $
	POP CX
	RET	
	;长延时函数,用于闪烁
DELAY2:
	PUSH CX
	MOV CX,0200H
	LOOP $
	POP CX
	RET	

这里的CX数值选择很重要,可以多尝试一下,测试下来CX=000AH比较合适。

(这里在每一位输出之后有一个判断,决定是否去调用DELAY2,是我想根据标志位决定是否让时分秒实现类似闪烁的功能,可以先忽略)

SHOW:
	LEA BX, TABCODE			;用于动态扫描显示当前时间,这里如果想简化代码,可以在data segment hour前加address equ $,可以循环显示,但可读性较差,没有采用
	MOV DX,PORTB;送段码
	MOV AL,[TABADD][5]
	OUT DX,AL
	MOV DX,PORTA;送位码
	MOV AX, HOUR
	MOV AL,AH
	XLAT
	OUT DX,AL
	CMP COUNT,01H
	JZ FLICKERHOUR1
	 CALL DELAY;延时
RETURNHOUR1:
	MOV DX,PORTA;关位码
	 MOV AL,0ffH
	 OUT DX,AL
	
	MOV DX,PORTB;送段码
	MOV AL,[TABADD][4]
	OUT DX,AL
	MOV DX,PORTA;送位码
	MOV AX, HOUR
	XLAT
	OUT DX,AL
	CMP COUNT,01H
	JZ FLICKERHOUR2
	 CALL DELAY;延时
RETURNHOUR2:
	 MOV DX,PORTA;关位码
	 MOV AL,0FFH
	 OUT DX,AL
	
	MOV DX,PORTB;送段码
	MOV AL,[TABADD][3]
	OUT DX,AL
	MOV DX,PORTA;送位码
	MOV AX, MINUTE
	MOV AL,AH
	XLAT
	OUT DX,AL
	 CMP COUNT,02H
	JZ FLICKERMIN1
	 CALL DELAY;延时
RETURNMIN1:
	MOV DX,PORTA;关位码
	 MOV AL,0FFH
	 OUT DX,AL
	 
	 MOV DX,PORTB;送段码
	MOV AL,[TABADD][2]
	OUT DX,AL
	MOV DX,PORTA;送位码
	MOV AX, MINUTE
	XLAT
	OUT DX,AL
	 CMP COUNT,02H
	JZ FLICKERMIN2
	 CALL DELAY;延时
RETURNMIN2:
	MOV DX,PORTA;关位码
	 MOV AL,0FFH
	 OUT DX,AL
	 
	 MOV DX,PORTB;送段码
	MOV AL,[TABADD][1]
	OUT DX,AL
	MOV DX,PORTA;送位码
	MOV AX, SECOND
	MOV AL,AH
	XLAT
	OUT DX,AL
	 CMP COUNT,03H
	JZ FLICKERSEC1
	 CALL DELAY;延时
RETURNSEC1:
	MOV DX,PORTA;关位码
	 MOV AL,0FFH
	 OUT DX,AL
	 
	 MOV DX,PORTB;送段码
	MOV AL,[TABADD][0]
	OUT DX,AL
	MOV DX,PORTA;送位码
	MOV AX, SECOND
	XLAT
	OUT DX,AL
	 CMP COUNT,03H
	JZ FLICKERSEC2
	 CALL DELAY;延时
RETURNSEC2:
	MOV DX,PORTA;关位码
	 MOV AL,0FFH
	 OUT DX,AL
	 JMP DONESHOW
FLICKERHOUR1:
	 CALL DELAY2
	 JMP RETURNHOUR1
FLICKERHOUR2:
	 CALL DELAY2
	 JMP RETURNHOUR2
FLICKERMIN1:
	 CALL DELAY2
	 JMP RETURNMIN1
FLICKERMIN2:
	 CALL DELAY2
	 JMP RETURNMIN2
FLICKERSEC1:
	 CALL DELAY2
	 JMP RETURNSEC1
FLICKERSEC2:
	 CALL DELAY2
	 JMP RETURNSEC2

DONESHOW:	 RET

原理解析

可以看到SHOW函数基本就是在依次显示每一位的数据,在主循环中重复调用SHOW函数就实现了显示效果。

LEA BX, TABCODE	
	MOV DX,PORTB;送段码
	MOV AL,[TABADD][5]
	OUT DX,AL
	MOV DX,PORTA;送位码
	MOV AX, HOUR
	MOV AL,AH
	XLAT
	OUT DX,AL
	CMP COUNT,01H
	JZ FLICKERHOUR1
	 CALL DELAY;延时
RETURNHOUR1:
	MOV DX,PORTA;关位码
	 MOV AL,0ffH
	 OUT DX,AL

每一位的显示分为送段码,送位码,延时,关位码四个部分。
因为使用的8255有输出锁存功能,所以可以先送段码,再送位码。
在调用延时函数后需要有关位码这一操作,否则这一位显示不了,还会影响下一位的显示
共阳极数码管关位码的操作需要送0ffH。
如果送00H这一位也显示不了
影响下一位原因在于输出锁存功能,在进行下一位的显示之前,位选信号一直是上一位的输出,如果不关位码,下一位输出会先短暂的显示上一位的输出。
至于要显示的这一位为什么显示不了,可能是输出ffh才可以让这一位最后亮一下,利用余辉效应让在显示其他位的时候这一位也能亮一会(我猜的)
总之是在非当前显示位的位选信号设置为非激活状态,通常是高电平。

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值