微型计算机数码管显示实验,微机原理硬件实验二:数码管动态显示

北邮微机原理硬件实验二,8255A并行接口应用。基于8086的汇编编程实现。

嗯,已经第二次实验了。第一次实验看了学长的代码,已经学到不少东西了,这一次该自己好好写了!

实验要求

简要说明

在方式0(输入/输出)下,以A口为输出口,B口为输出口, A口接六个共阴极数码管的八位段码,高电平点亮数码管的某一段, B口接数码管的位选(即要使哪个数码管亮),高电平选中某一位数码管点亮。

8255A中 A端口地址 EE00H

B端口地址 EE01H

C端口地址 EE02H

控制地址 EE03H

八段数码管的显示规律及数码管的位选规律自己查找,可用实验一中,学过的I、O命令来做。

6位数码管静态显示

在数码管电路上静态地显示6位学号,当主机键盘按下任意键时,停止显示,返回DOS。提示:该电路6个数码管的同名阳极段已经复接,当段选寄存器寄存了一个字型编码之后,6个数码管都有可能显示出相同的数字。如果要使6个数码管“同时”显示不同的数字,必须采用扫描显示的方法,通过选位寄存器选择某一位数码管,显示其数字(对应段值为1),然后关闭此数码管,再选择下一位数码管进行显示;如果在一秒钟内,每一位数码管都能显示30次以上,则人眼看到的是几位数码管同时在显示。

实验证明,在扫描显示过程中,每一位显示延迟1ms是最佳选择。

6位数码管动态显示

要求在数码管电路1-6位数码管上按图3.2所示的规律,动态显示字符串HELLO,当主机键盘按下任意键时结束。

提示:

①本实验应在上面实验的基础上完成

②在数据段,按下列规律设置12个字型码:

MESG DB 0,0,0,0,0,0,3DH,0DCH,8CH,8CH,0EDH,0

POINT DW MESG

… …

POINT单元存放MESG单元的有效地址,程序取出POINT单元的内容→BX,然后用BX间址取数送数码管电路,扫描显示6个字符。每过0.5s将POINT单元的内容加1,再将POINT单元的内容→BX,……。POINT单元内容加1,使字符串显示的首地址向高地址移动一个单元,从而使6位字符串向“左”移动一位,实现动态显示。

③动态显示的速度可控制(快或慢),利用实验一读入端口的功能

编程思路

要干掉这么一坨东西,还真是很头痛。

实验一已经学习过怎么对程序进行分块了,也知道如何使用变量了。

要实现6个数显管“同时显示数字”,出于节省引脚的考虑,我们也只能运用时分复用,每次只亮一个数显管,显示该数显管的数字,然后切换到下个数显管显示下一个数字,当扫频速度足够快时,就可以做出“同时显示”的效果了。嗯,各种实验都做过很多次数显管显示了,网上也有很多资料,不累赘了。

本实验还要使用8255A用作输出,可以下载到它的Data Sheet用作参考。

伪代码:

int main()

{

initialize();

while(1){

read_switch(); // Read switch state.

out_cat(); // Turn the next ONE Nixie-tube on.

out_led(); // Display the current number.

delay(); // Have some delay.

return_to_DOS(); // Check if switch state acquires exit.

}

return 0;

}

源代码

; Exercise 2: Nixie_tube Display

; AUTHOR: feichashao

; DATE: 2013-12-7

DATA SEGMENT

CatState DB 01H

STUDENT DB 00H,0F4H,21H,0EDH,0F1H,61H,61H,00H

HELLO DB 00H,03DH,0DCH,8CH,8CH,0EDH,00H,00H

DIGIT DB 00H

COUNT DW 0000H

SwState DB 0

DATA ENDS

STACK SEGMENT STACK 'STACK'

DB 100 DUP(?)

STACK ENDS

CODE SEGMENT

ASSUME CS:CODE,DS:DATA,SS:STACK

Main PROC

PUSH DS

XOR AX,AX

PUSH AX

MOV AX,DATA

MOV DS,AX

MOV CatState,1H

MOV DIGIT,1H

CALL Initialize

CALL EndlessRepeat

RET

Main ENDP

Initialize PROC

PUSH DX

PUSH AX

MOV AL,80H

MOV DX,0E803H

OUT DX,AL

POP AX

POP DX

RET

Initialize ENDP

EndlessRepeat PROC

EndlessLoop: CALL ProcToRepeat

JMP EndlessLoop

RET

EndlessRepeat ENDP

ProcToRepeat PROC

CALL readSw

CALL outCat

CALL outLED

CALL excuteDelay

CALL returnToDOS

ProcToRepeat ENDP

readSw PROC

PUSH AX

PUSH DX

MOV DX,0E8E0H

IN AL,DX

MOV SwState,AL

POP DX

POP AX

readSw ENDP

DivFreq PROC

PUSH CX

MOV CX,0100H

MyLoop: PUSH CX

MOV CX,0800H

MyNestedLoop: DEC CX

JNZ MyNestedLoop

POP CX

DEC CX

JNZ MyLoop

POP CX

RET

DivFreq ENDP

outCat PROC

CMP COUNT,00FFH

JZ MOVECAT

ROL CatState,01H

PUSH DX

PUSH AX

MOV AL,CatState

MOV DX,0E801H

OUT DX,AL

POP AX

POP DX

RET

MOVECAT: ROL CatState,01H

ROL CatState,01H

MOV COUNT,0000H

RET

outCat ENDP

outLED PROC

INC DIGIT

; TEST DIGIT,06H

CMP DIGIT,08H

JNC CLEAR

PUSH DX

PUSH AX

PUSH BX

MOV BL,DIGIT

MOV BH,0H

TEST SWSTATE,01H

JNZ printHello

MOV AL,STUDENT[BX]

MOV DX,0E800H

OUT DX,AL

POP BX

POP AX

POP DX

RET

printHello: MOV AL,HELLO[BX]

; MOV AL,DS:[BX]

MOV DX,0E800H

OUT DX,AL

; MOV DX,0E8E0H

; OUT DX,AL

POP BX

POP AX

POP DX

RET

CLEAR: MOV DIGIT,00H

RET

outLED ENDP

excuteDelay PROC

CALL DIVFREQ

TEST SWSTATE,01H

JZ exitDelay

INC COUNT

exitDelay: RET ; Do Nothing this time.

excuteDelay ENDP

returnToDOS PROC

TEST SWSTATE,02H

JZ exitReturnToDOS

CALL exereturnToDOS

exitReturnToDOS: RET

returnToDOS ENDP

exereturnToDOS PROC

MOV AX,4C00H

INT 21H

exereturnToDOS ENDP

CODE ENDS

END MAIN

数显管亮灭控制

控制6位数显管的亮灭,1为亮,0为灭。

我们可以用一个8bits的变量,来记录和控制这6位数显管的状态。

初始状态

CatState DB 00000001B

要显示下一个数字的时候,只要对CatState进行左移一位就可以了。

但是,这个数据是8位的,但实际只显示6位,所以学号的数据一定要有8位,填充两个无意义的字符即可。

(前后的00H都是不显示的,占个坑就好。)

STUDENT DB 00H,0F4H,21H,0EDH,0F1H,61H,61H,00H

动态显示“HELLO”

要求显示的“HELLO”看上去是移动的。

实现的方法其实很简单,只要每隔1秒,将数显管的控制变量CatState多移动一位就好,其他的还是按原来的样。

吐槽

上课之前,碰到一女生。她实验一的代码,是自己写的。(天啊,这是什么一个时代,抄袭代码竟然是常态。)

然后她上周的实验,辛辛苦苦写了半天代码,却因为功能不全,而得了低分。

像我这些,直接挪用学长代码,三下两下完成实验的,却得了高分。

所以她说,这次实验就改用别人代码了。

大学教育就是这么引导的?

我也因为这个实验没有按时完成,被老师不爽了一下。

不爽就不爽吧,反正学到的是自己的。