一段数码管动态显示一行六位数字的程序,求解析所有代码含义。越详细越好

一段数码管动态显示一行六位数字的程序,求解析所有代码含义。越详细越好,第1张

这个程序的基本流程是:

1.把content中的数字对应的断码找出,并依次存放到LEDBuf中

2.依次送LEDBuf中的断码到LED上,LED显示对应字符

OUTBIT equ 08002h 将位码送至此地址,位码表示显示哪一位LED管

OUTSEG equ 08004h 将断码送至此地址,断码表示在指定的LED管上显示什么字符

data segment

Content db 1,2,3,0dh,0eh,0fh 要显示的数字

LEDBuf db 6 dup(?) 要显示的数字对应的断码

LEDMAP给出的是断码表,表示16进制数到断码的映射。总共16个,分别表示0-f。

比如第一个3fh就是0的断码,断码送到LED中,LED会自动显示0。

LEDMAP:

db 3fh,06h,5bh,4fh,66h,6dh,7dh,,07h

db 7fh,6fh,77h,7ch,39h,5eh, 79h,71h

data ends

code segment

assume cs:code, ds:data

Delay的目的就是为了让LED灯上的内容停留,以便看清

Delay proc

push cx

mov cx,100h

loop $ 这里的循环目的是暂停一段时间,让LED上的数字停留,以便人看清

pop cx

ret

Delay endp

DisplayLED做的事:把LEDbuf中内容全部显示到LED灯上。LEDbuf中6个断码,对应6个LED灯。

DisplayLED proc near

mov bx, offset LEDBuf

mov cx, 6 总共显示6个断码

mov ah, 00100000b 位码,00100000b中1的位置指示了要显示的数位,当前是1在左起第六个,也就是显示6号LED灯

后面有shr指令会将这个00100000b右移,这样变成00010000,显示5号LED,以此类推。

DLoop: mov dx, OUTBIT

mov al, 0

out dx,al 将0送端位码端口,表示当前不选中任何LED,即关闭LED

mov al, [bx] 将LEDbuf中的一个断码,送入al

mov dx, OUTSEG

out dx,al 送断码,表示要在LED中显示这个字符

mov dx, OUTBIT

mov al, ah

out dx, al 送位码,表示要显示哪一个LED灯

call Delay 上面送完断码,位码后,在相应的LED上就显示相应的字符,Delay可以让这个字符停留一段时间,视觉滞留。

shr ah, 1 位码右移,显示下一个LED

inc bx bx加1,那么[bx]就指向LEDbuf中的下一个断码

loop Dloop 这个Dloop循环把LEDbuf中的六个断码依次全部送到对应LED上显示

ret

DisplayLED endp

Start:程序的入口,从这里开始运行程序

Start proc near

mov ax, data

mov ds, ax

mov cx,6 显示六个字符

mov ah,0 ah是content中的偏移量,从0->5,分别找出content中各个字节内容

mov si,offset ledbuf

redo: mov bx,offset content

mov al,ah 后面的xlat指令要使用al

xlat xlat的作用al<-[bx+al],也就是将bx这个地址(content)起的第al个字节内容送到al中

mov bx,offset ledmap

xlat 将此时al中的数字对应的断码找出,并放到al中。(数字a对应的断码就是ledmap起第a个字节的数据)

mov [si],al 将找到的断码放到LEDbuf中

inc si LEDbuf地址加1,存放下一个断码

inc ah 找content中下一个数字的断码

loop redo 整个redo循环做的事:把content中数字对应的断码放到LEDbuf中,循环最后结果是LEDbuf变成:06h,5bh,4fh,5eh,79h,71h

show: call displayled

jmp show 在LED上一直显示这6个字符

start endp

code ends

end start

DELAY5MS PROC ;延时子程序开始

MOV DX,0B000H ;所选计数器对应的端口地址送DX

MOV AX,5000 ;8253计数初值送AX

OUT DX,AL ;低8位送入计数器端口

MOV AL,AH ;把高八位先给AL,输入输出指令的必须格式

OUT DX,AL ;高8位计数器送入端口

HH:MOV DX,0F002H ;标号,把端口号给DX

IN AL,DX ;读地址端口值

AND AL,01H ;屏蔽端口值的D7~D1位,目的是保持AL中D0位不变,检测其值是否为0

JNZ HH ;若不为0,跳转到HH,否则顺序执行

LL:IN AL,DX ;读地址端口值

AND AL,01H ;功能与之前的相同

JZ LL ;检测是否低位为0 ,为0则跳转到LL,否则顺序执行

RET ;返回值

DELAY5MS ENDP ;子程序结束命令

这段8253的程序少了一段控制字送控制端口的命令,没有控制字送控制端口是不行的。

5000并不是5000ms 按你题目所给,应当是5ms 至于5000要根据CLK是多少MHZ来计算。

你想知道是如何实现5ms延时的,这个我懂得不多,没有控制字,我的知道范围内说不出来它的工作方式,8253一共6种工作方式,很复杂,我建议你不要那么深究,除非你将来确定要搞这方面的,否则只会8253的初始化编程就够了,我也是学生,对于我们用的教材和一些资料来说,都没有哪个书会去很深刻的剖析它,我觉得微型计算机原理这门课,你要选择性的学习一些东西。

先汗一个!

你要知道无论是8253,8255A,还是8259A,想对它们初始化编程都需要控制字,我想你如果学了8253就应该能知道什么是控制字。控制字的格式如下:

SC1, SC0———通道选择位.为00, 01, 10分别表示选择0, 1, 2通道.RL1, RL0———读/写 *** 作位.00 表示锁存数据,可随时读取计数器中的计数值01 表示只读/写低8位,高8位自动置为010表示只读/写高8位,低8位自动置为011表示读/写16位数据,先低8位,后高8位.M2,M1,M0———工作方式选择位。

根据控制字可以具体判断是选择哪一种工作方式,现在没有我就大体上说一说。

首先,计数初值=定时时间÷CLK周期 你算一算呵呵 对吧。

再说一下大体原理:

8253内部包括3个功能完全相同和 *** 作完全独立的计数通道,每个计数通道由16位减法计数器、16位计数初值寄存器和16位计数值锁存器组成。初始化时,向计数通道装入的计数初值,先送到计数初值寄存器中保存,然后送到减法计数器。计数器启动后,减法计数器对CLK的下降沿进行减1计数,在未锁定时把结果送入16位计数值锁存器中。当计数值减到0时,输出OUT信号,一次计数结束。计数初值寄存器的内容,在计数过程中保持不变。计数初值寄存器和计数值锁存器占用一个端口地址(即该计数通道口地址),CPU读取计数通道的当前计数值来自计数值锁存器。

不知道你懂不懂锁存,所存命令是在读取计数值时先用所存命令将其锁定,防止它改变,否则如果计数值有可能正处于变化中,这样得到的就是不确定的结果了。当cpu用读取所存命令后,锁存器就失效了,计数器将恢复工作。

没有控制字 但是你这个是一个延时程序那么就应该是将通道工作在定时器方式,此时确定频率的时钟脉冲从CLK输入,这正好与上面我说的频率,以及初值的计算吻合吧。

然后各通道的启动、禁止、允许计数与门控信号GATE有关,GATE的作用OUT的输出波形随各通道工作方式不同而不同。

没有控制字没法确定工作方式,也许有办法,但是我的知识有限,能知道的就这么多了,希望对你有所帮助。

PS:你算是把我榨干了!


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/7830474.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-10
下一篇2023-04-10

发表评论

登录后才能评论

评论列表(0条)

    保存