该实验使用了8259A,ADC0809,数码管来完成一个数据采集系统的设计,目的是了解中断方式的A/D采集数据的实现方法,掌握硬件设计和中断程序的编写方法,是对学生综合实验能力的训练。
使用ADC0809的通道0,接入0-5V的直流电压,用“直流信号”电位器调整模拟电压值,A/D的转换结束信号EOC接在主8259A的MIR3上,采集100个数据并存入内存中,同时将采集的16进制数据显示在数码管上。请多次调整0-5V的电压值(旋动“直流信号”旋钮),进行A/D采集,并观测内存中的数据的变化情况。
每次采集的100个数据可能是相同的(数码管的数据也可能不变),当“直流信号”旋钮旋动时可以采到不同的数据。
1、 根据原理图正确连接实验线路(需要连接红线)。
线路图如下:
2、 正确理解实验原理。
将298H作为了A/D0809的端口,将280H作为了8255A的端口。
将A/D0809数据转换结束时EOC的高电平作为了8259A的中断源,连接到了MIRQ3,主片的IR3。另外8255A的A口在0方式下输出段码,B口在0方式下输出位码,使数码管得以显示。
主程序的流程图如下:
3、 编写实验程序,并上机调试,观察实验结果。
实验程序如下:
STACKS SEGMENT
STA DW 512 DUP(?)
TOP EQU LENGTH STA
STACKS ENDS
DATA SEGMENT
IO0809A EQU 298H
LED DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H
TMP_1 DB ?
TMP_2 DB ?
TMP DB ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACKS
START:
MOV AX,CS
MOV DS,AX
MOV DX,OFFSET INT3 ;系统功能调用、设置中断向量、由DS:DX指向四个字节地址
MOV AX,250BH ; AL=中断类型号(=0BH---0B*4=向量表地址)
INT 21H ; (实现向中断性量表中添置INT3的地址)
MOV DX,283H ;8255命令口地址,进行初始化
MOV AL,10001001B ;设置工作方式,A工作在0方式输入,B口0方式输出
OUT DX,AL
MOV AX,STACKS ;设定堆栈段寄存器SS
MOV SS,AX
MOV SP,TOP ;设定堆栈指针SP的初值
IN AL,21H ;设置中断屏蔽字(采用"读-与-写"方式使能)
AND AL,0F7H ;使能IRQ3
OUT 21H,AL ;写入OCW1(屏蔽字)
MOV SI,0 ;建立一个标志,原始=0
MOV AX,DATA
MOV DS,AX
MOV DX,IO0809A ;启动A/D转换器
OUT DX,AL
LOOP1:
STI ;开中断(IF置1)
IN AL,DX
MOV CX,0FFFFH ;设定延时常数
CMP SI,01 ;查询标志、判断是否转换完成
JNE LOOP1 ;未完成时:返回等待
LOOP3:
LOOP LOOP3 ;转换完成时首先延时
CLI
MOV DX,IO0809A ;再次启动A/D转换器
OUT DX,AL
JMP LOOP1 ;返回继续等待下一次中断
INT3:
PUSH AX ;中断服务程序
PUSH DX
PUSH CX
MOV SI,1 ;建立一个转换完成的标志(SI=1)
MOV DX,IO0809A
IN AL,DX ;从A/D转换器输入数据
;处理采集的数据:将8位二进制数拆分为两位十六进制数以待显示
MOV TMP,0
MOV TMP,AL ;将AL保存到BL
MOV CL,4
SHR AL,CL ;将AL右移四位
CALL DISP1 ;调显示子程序显示其高四位
MOV AL,TMP
AND AL,0FH
CALL DISP2 ;调显示子程序显示其低四位
MOV DL,20H ;(空格符)
INT 21H
MOV DL,20H ;(空格符)
INT 21H
PUSH DX
MOV AH,06H ;判断是否有键按下
MOV DL,0FFH ;DX=FF时 输入字符
INT 21H ;AL=输入的字符
POP DX
JE LOOP2 ;若没有键盘操作(AL=0)则转START
IN AL,21H ;中断屏蔽字OCW1操作 ;
OR AL,08H ;将IMR中的IRQ3屏蔽
OUT 21H,AL
MOV AH,4CH ;退出
INT 21H
LOOP2:
STI ;返回主程序之前开中断
MOV AL,20H ;写OCW2,发EOI命令
OUT 20H,AL ;使ISR相应位清零
POP CX
POP DX
POP AX
IRET ;中断返回
DISP1 PROC NEAR ;显示子程序
MOV TMP_1,AL
MOV AL,00H
MOV DX,281H
OUT DX,AL
MOV AL,TMP_1
MOV BX,OFFSET LED ;BX为数码表的起始地址
XLAT ;求出相应的段码
MOV DX,280H ;从8255的A口输出
OUT DX,AL
MOV AL,02H
MOV DX,281H ;
OUT DX,AL
RET
DISP1 ENDP
DISP2 PROC NEAR ;显示子程序
MOV TMP_2,AL
MOV AL,00H
MOV DX,281H;
OUT DX,AL
MOV AL,TMP_2
MOV BX,OFFSET LED ;BX为数码表的起始地址
XLAT ;求出相应的段码
MOV DX,280H ;从8255的A口输出
OUT DX,AL
MOV AL,01H
MOV DX,281H ;
OUT DX,AL
RET
DISP2 ENDP
CODE ENDS
END START
虽然设置的时候是在两位数码管上输出,但是因为数码管一次只能输出一位,而且考虑到数据存在波动,所以我们没有在程序中设置延时,希望可以通过高频率的数据显示呈现出真实的数据情况。
我们的实验箱性能较好,所以在实验的过程中我们可以观察到从00到FF的完整数据范围,上图就是最大值的情况,不过因为数据闪的太快, 照片上只有一个F。
在实验过程中,遇到的一个主要的难点是数码管的显示,这里是通过网上找到的XLAT指令,可以将BX + AL的结果再送给AL,LED是之前在数据段定义的一个数组,存储的是一系列的数字的段码表示,BX是LED的偏移地址,那么BX + AL就是AL这个二进制数所对应的十六进制数段码的地址,送到A口即可得到正确的数字显示。