北邮微机原理硬件实验二,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多移动一位就好,其他的还是按原来的样。
吐槽
上课之前,碰到一女生。她实验一的代码,是自己写的。(天啊,这是什么一个时代,抄袭代码竟然是常态。)
然后她上周的实验,辛辛苦苦写了半天代码,却因为功能不全,而得了低分。
像我这些,直接挪用学长代码,三下两下完成实验的,却得了高分。
所以她说,这次实验就改用别人代码了。
大学教育就是这么引导的?
我也因为这个实验没有按时完成,被老师不爽了一下。
不爽就不爽吧,反正学到的是自己的。