微型计算机可编程并行接口输入/输出实验
一、实验目的
1.掌握8255工作方式1时的使用及编程。
2.进一步掌握中断处理程序的编写。
二、实验设备与环境
TPC-2003A通用微机接口实验箱,windows XP运行环境
三、实验内容、程序清单及运行结果
- 实验内容
1)按图10(A)8255方式1的输出电路连好线路。
2)编程:每按一次单脉冲按钮产生一个正脉冲使8255产生一次中断请求,让CPU进行一次中断服务:依次输出01H、02H,04H,08H,10H,20H,40H,80H使L0~L7依次发光,中断8次结束。
3)按图10(B)8255方式1输入电路,连好线路。
4)编程:每按一次单脉冲按钮产生一个正脉冲使8255产生一次中断请求,让CPU进行一次中断服务:读取逻辑电平开关预置的ASCII码,在屏幕上显示其对应的字符,中断8次结束。
- 流程图
3. 程序清单
1)参考程序1:
code segment
assume cs:code
start: mov ax,cs ;CPU首先执行start处的数据传送指令。将cs代码段的段地址传送给ax寄存器。
mov ds,ax ;CPU执行数据传送指令。将ax寄存器的数据也就是代码段的段地址,传送给dx寄存器。
mov dx,offset int_proc;CPU执行特殊数据传送指令,将标号为int_proc的中断服务子程序的首地址偏移量传送到dx寄存器中。这里offset是取偏移量的意思。
mov ax,250fh ;CPU执行数据传送指令。将立即数250fh传送到ax寄存器。这样ah的值为25h,al的值为0fh。
int 21h;CPU执行中断指令。CPU根据中断类型号21h,从内存的中断向量表中确定存放中断向量的起始地址,然后取前两个单元的数据给IP寄存器,取出后两个单元的数据给CS寄存器,这样CPU根据CS和IP的值,转到DOS功能调用的中断服务子程序中。CPU在执行DOS功能调用的中断服务子程序时,根据入口参数ah提供的功能号为25h,再转到设置中断向量的子模块。CPU在执行设置中断向量的子模块时,根据入口参数al寄存器,提供的中断类型号为0fh,从内存的中断向量表中,确定存放该中断向量的起始地址,然后将入口参数dx寄存器的值,也就是需设置中断向量的偏移地址,写到前两个单元中,再将入口参数ds寄存器的值,也就是中断向量的段地址,写到后两个单元中,这样就完成了中断向量的设置。
cli ;CPU执行清中断标志位指令cli,使IF标志位为0,CPU不响应中断。其目的是为了保证后续内部的初始化设置不受外界的干扰。
mov dx,21h ;CPU执行数据传送指令,将立即数21h传送给dx寄存器。
in al,dx ;CPU执行IO的读指令。根据dx寄存器提供的21h,也就是8259中断控制器奇地址端口的地址,读取8259的屏蔽寄存器IMR的屏蔽字OCW1到al寄存器中。
它的每一位,可以对相应的中断请求输入进行屏蔽,若OCW1的某一位为1,则相应的中断请求输入被屏蔽;反之,则相应的中断请求输入呈现允许状态。
即若Mi=1,则表示8259A对IRi的中断请求呈屏蔽状态;否则若Mi=0,则表示8259A对IRi的中断请求呈允许状态。
and al,07Fh ;CPU执行与运算指令,将al寄存器的屏蔽字OCW1和7fh(01111111)进行与运算。实际上是将屏蔽字的最高位强制置为0。也就是强制开放IR7号的中断。
out dx,al;CPU执行IO的写指令。根据dx寄存器提供的奇地址端口的地址21 h,将经过处理的屏蔽字,写到屏蔽寄存器IMR中。这样就开放了IR7号中断。
mov dx,28bh ;CPU执行数据传送指令。将立即数028bh,传送给dx寄存器。028bh是8255控制端口的端口地址。028bh为什么是8255控制端口的端口地址?8255A的CS片选信号引脚连接的是0288H对应的译码器输出端Y1,决定了8255端口的起始地址。A1、A0 是端口选择信号。A1、A0为00,选中A端口;为01时,选中B端口;为10时,选中C端口;为11时,选中控制口。
mov al,0a0h;CPU执行数据传送指令,将立即数0a0h传送给al寄存器。
out dx,al;CPU执行IO的写指令。根据dx寄存器提供的8255控制端口的端口地址028bh,将al寄存器的数据a0h(10100000),也就是方式选择控制字(这是由于最高位为1),通过控制端口写到模式寄存器中,根据方式选择控制字的格式,D6D5为01,设置A组工作在方式1。D4为0,设置A口为输出,由于只用到A口作为输出。因此D3~D0可为任意值。
mov al,0dh ;CPU执行数据传送指令。将立即数0dh传送给al寄存器。
out dx,al ;CPU执行IO的写指令。根据dx寄存器提供的8255控制端口的端口地址028bh,将al寄存器的数据0dh(00001101),也就是C口的置位复位控制字(由于最高位为零),通过控制端口,写到存放C口的置位复位控制字的寄存器中。根据c口的置位复位控制字的格式,D3D2D1为110,选择的是PC6,D0为1表示对PC6置位,实际上是设置8255的方式1输出的中断允许控制INTEA为1,即8255允许产生中断。
mov bl,1;CPU执行数据传送指令将立即数1传送给bl寄存器.
sti ;CPU执行置中断标志位指令sti,使IF标志位为1,CPU开始响应中断。
ll: jmp ll ;然后CPU执行无条件跳转指令jmp进入死循环。
此时当按下单脉冲按钮,代替外设产生一个外设的响应信号ACK给8255。8255接收到ACK响应信号后,首先是输出缓冲器满信号OBF产生一个无效的高电平,同时对A组控制电路中的与门的一端置为1(PC7),由于与门的另一端已设置中断允许INTEA为1,此时8255通过PC3产生一个高电平的有效中断请求信号,提供给8259控制器IRQ7。
8259控制器的IR7,得到一个高电平的请求信号时,实际上是由低到高的上升沿触发中断请求信号。那么8259中断控制器的中断请求寄存器IRR锁存相应的位,D7置为1。然后优先级比较器就会从中断请求寄存器IRR中选择优先级别高的,假定此时只有一个IRR的中断请求,那么优先级比较器选择IR7,和当前服务寄存器ISR正在服务的优先级最高的中断源进行比较。由于IR7的优先级最低,所以IR7的中断源,是要等到当前服务寄存器ISR中所有的中断源执行完,8259控制器才可以选择IR7,通过INT引脚,向CPU发出有效的中断请求信号,CPU通过INTR引脚,收到中断请求信号后,若状态字PSW中的中断允许标志位IF为1,也就是CPU处于开中断状态,则CPU执行完当前指令后,开始响应中断,通过INTA引脚向8259控制器连续发出两个负脉冲。
当8259控制器通过INTA引脚收到第1个负脉冲时,就会对IRR锁存功能失效,使IRR寄存器的相应位D7置0,即清除中断请求。然后使当前服务寄存器ISR相应位D7置为1。当8259收到第2个负脉冲时,8259就会从存放中断类型码初始化命令字ICW2的寄存器中得到中断类型码的高5位,根据响应的中断源IR7,得到中断类型码的低三位,也就是111。然后8259控制器将得到的中断类型码0fh,放到数据总线上。那么CPU在连续的发出两个负脉冲后,就会从数据总线上读取中断类型码0fh,然后CPU根据获取的中断类型码0fh在内存的中断向量表中,确定存放该中断向量的起始地址。取出前两个单元的数据到IP寄存器,取出后两个单元的数据到CS寄存器。这样CPU根据CS和IP的值,转到标号为int_proc的中断服务子程序中。
。
int_proc: mov al,bl;CPU执行标号为int_proc的中断服务子程序时。CPU执行数据传送指令将BL寄存器的数据1传送给al寄存器。
mov dx,288h ;CPU执行数据传送指令将立即数0288h(也就是A口的端口地址)传送给DX寄存器。为什么0288h是A口的端口地址?
out dx,al;CPU执行IO的写指令,根据DX寄存器提供的A口的端口地址0288h,将al寄存器的数据写到A口的输出寄存器中,此时通过A口的引脚PA0-PA7,将数据输出到发光二极管L0~L7,点亮对应的灯。
mov al,20h;CPU执行数据传送指令,将立即数20h传送给al寄存器。
out 20h,al;CPU执行IO的写指令,根据提供的8259的偶地址端口的地址20h,将al寄存器的数据,写到操作命令字OCW2中。这是由于D4D3为00,决定了访问的是OCW2。根据OCW2的格式,由于D5为1,8259产生EOI中断结束命令,使当前服务寄存器ISR对应的D7这一位清零。
shl bl,1;CPU执行逻辑左移指令,将bl寄存器的数据左移一位,最低位补0,最高位移入到CF标志位。
jnc next ;CPU执行jnc条件转移指令。由于CF为零,条件满足,转到标号为next处,执行中断返回指令,返回到死循环。当再次按下单脉冲按钮CPU又响应中断服务子程序,通过A口输出数据,点亮对应的LED灯。
然后执行逻辑左移指令,将bl寄存器数据左移一位,CPU再执行jnc条件转移指令,条件满足,转到标号为next处,执行中断返回指令又返回到死循环。
当连续的按下单脉冲按钮第8次时,CPU在执行中断服务子程序中的逻辑左移指令时,CF标志位已置为1。CPU在执行jnc条件转移指令时,条件不满足。
in al,21h;CPU顺序执行IO的读指令,根据提供的8259奇地址端口的端口地址21h,读取8259屏蔽寄存器IMR的屏蔽字OCW1到al寄存器中。
or al,80h ;CPU执行或运算指令,将al寄存器中的数据最高位D7强制置为1,也就是强制关闭IR7号中断。
out 21h,al;然后CPU执行IO的写指令,根据提供的8259奇地址端口的端口地址21h,将经过处理后的屏蔽字,写到屏蔽寄存器IMR中,这样就关闭了IR7号中断。
sti ;接着CPU执行置中断标志位指令sti,此时IF标志位为1,CPU开始响应中断。
mov ah,4ch ;然后CPU执行数据传送指令,将立即数4ch传送给ah寄存器。
int 21h;接着CPU执行中断指令,根据中断类型号21h,转到DOS功能调用的中断服务子程序中,CPU在执行DOS功能调用的中断服务子程序时,根据入口参数ah提供的功能号4ch,CPU再转到返回DOS的子模块,结果返回操作系统。
next: iret
code ends
end start
2)参考程序2:
code segment
assume cs:code
start: mov ax,cs ;CPU首先执行start处的数据传送指令。将cs代码段的段地址传送给ax寄存器。
mov ds,ax ;CPU执行数据传送指令。将ax寄存器的数据也就是代码段的段地址,传送给dx寄存器。
mov dx,offset int_proc;CPU执行特殊数据传送指令,将标号为int_proc的中断服务子程序的首地址偏移量传送到dx寄存器中。这里offset是取偏移量的意思。
mov ax,250fh ;CPU执行数据传送指令。将立即数250fh传送到ax寄存器。这样ah的值为25h,al的值为0fh。
int 21h;CPU执行中断指令。CPU根据中断类型号21h,从内存的中断向量表中确定存放中断向量的起始地址,然后取前两个单元的数据给IP寄存器,取出后两个单元的数据给CS寄存器,这样CPU根据CS和IP的值,转到DOS功能调用的中断服务子程序中。CPU在执行DOS功能调用的中断服务子程序时,根据入口参数ah提供的功能号为25h,再转到设置中断向量的子模块。CPU在执行设置中断向量的子模块时,根据入口参数al寄存器,提供的中断类型号为0fh,从内存的中断向量表中,确定存放该中断向量的起始地址,然后将入口参数dx寄存器的值,也就是需设置中断向量的偏移地址,写到前两个单元中,再将入口参数ds寄存器的值,也就是中断向量的段地址,写到后两个单元中,这样就完成了中断向量的设置。
cli ;CPU执行清中断标志位指令cli,使IF标志位为0,CPU不响应中断。其目的是为了保证后续内部的初始化设置不受外界的干扰。
mov dx,21h ;CPU执行数据传送指令,将立即数21h传送给dx寄存器。
in al,dx ;CPU执行IO的读指令。根据dx寄存器提供的21h,也就是8259中断控制器奇地址端口的地址,读取8259的屏蔽寄存器IMR的屏蔽字OCW1到al寄存器中。
它的每一位,可以对相应的中断请求输入进行屏蔽,若OCW1的某一位为1,则相应的中断请求输入被屏蔽;反之,则相应的中断请求输入呈现允许状态。
即若Mi=1,则表示8259A对IRi的中断请求呈屏蔽状态;否则若Mi=0,则表示8259A对IRi的中断请求呈允许状态。
and al,07Fh ;CPU执行与运算指令,将al寄存器的屏蔽字OCW1和7fh(01111111)进行与运算。实际上是将屏蔽字的最高位强制置为0。也就是强制开放IR7号的中断。
out dx,al;CPU执行IO的写指令。根据dx寄存器提供的奇地址端口的地址21 h,将经过处理的屏蔽字,写到屏蔽寄存器IMR中。这样就开放了IR7号中断。
mov dx,28bh ;CPU执行数据传送指令。将立即数028bh,传送给dx寄存器。028bh是8255控制端口的端口地址。028bh为什么是8255控制端口的端口地址?8255A的CS片选信号引脚连接的是0288H对应的译码器输出端Y1,决定了8255端口的起始地址。A1、A0 是端口选择信号。A1、A0为00,选中A端口;为01时,选中B端口;为10时,选中C端口;为11时,选中控制口。
mov al,0B8h;CPU执行数据传送指令,将立即数0B8h传送给al寄存器。
out dx,al;CPU执行IO的写指令。根据dx寄存器提供的8255控制端口的端口地址028bh,将al寄存器的数据0B8h(10111000),也就是方式选择控制字(这是由于最高位为1),通过控制端口写到模式寄存器中,根据方式选择控制字的格式,D6D5为01,设置A组工作在方式1。D4为1,设置A口为输入,由于只用到A口作为输入。因此D3~D0可为任意值。
mov al,09h;CPU执行数据传送指令。将立即数09h传送给al寄存器。
out dx,al ;CPU执行IO的写指令。根据dx寄存器提供的8255控制端口的端口地址028bh,将al寄存器的数据09h(00001001),也就是C口的置位复位控制字(由于最高位为零),通过控制端口,写到存放C口的置位复位控制字的寄存器中。根据c口的置位复位控制字的格式,D3D2D1为100,选择的是PC4,D0为1表示对PC4置位,实际上是设置8255工作在方式1的输入的中断允许控制INTEA为1,即8255允许产生中断。
mov bl,8 ;bl为中断次数计数器CPU执行数据传送指令将立即数8传送给bl寄存器,实际上是给定中断的次数.
sti ;CPU执行置中断标志位指令sti,使IF标志位为1,CPU开始响应中断。
ll: jmp ll ; ;CPU执行无条件跳转指令jmp进入死循环。
此时当按下单脉冲按钮时,代替外设产生一个外设的数据选通信号STB给8255。8255当接收一个低电平有效的STB选通信号后,8255将PA0~PA7引脚上的开关状态的值锁存到A口的输入寄存器中,同时产生IBF输入缓冲器满信号,并对A组控制电路中与门的一端置为1,由于与门的另一端已设置中断允许INTEA为1,此时8255通过PC3产生一个高电平的有效的中断请求信号,提供给8259控制器IRQ7。
8259控制器的IR7,得到一个高电平的请求信号时,实际上是由低到高的上升沿触发中断请求信号。那么8259中断控制器的中断请求寄存器IRR锁存相应的位,D7置为1。然后优先级比较器就会从中断请求寄存器IRR中选择优先级别高的,假定此时只有一个IR7的中断请求,那么优先级比较器选择IR7,和当前服务寄存器ISR正在服务的优先级最高的中断源进行比较。由于IR7的优先级最低,所以IR7的中断源,只有等到当前服务寄存器ISR中所有的中断源执行完,8259控制器才可以选择IR7,通过INT引脚,向CPU发出有效的中断请求信号,CPU通过INTR引脚,收到中断请求信号后,若状态字PSW中的中断允许标志位IF为1,也就是CPU处于开中断状态,则CPU执行完当前指令后,开始响应中断,通过INTA引脚向8259控制器连续发出两个负脉冲。
当8259控制器通过INTA引脚收到第1个负脉冲时,就会对IRR锁存功能失效,使IRR寄存器的相应位D7置0,即清除中断请求。然后使当前服务寄存器ISR相应位D7置为1。当8259收到第2个负脉冲时,8259就会从存放中断类型码初始化命令字ICW2的寄存器中得到中断类型码的高5位,根据响应的中断源IR7,得到中断类型码的低三位,也就是111。然后8259控制器将得到的中断类型码0fh,放到数据总线上。那么CPU在连续的发出两个负脉冲后,就会从数据总线上读取中断类型码0fh,然后CPU根据获取的中断类型码0fh在内存的中断向量表中,确定存放该中断向量的起始地址。取出前两个单元的数据到IP寄存器,取出后两个单元的数据到CS寄存器。这样CPU根据CS和IP的值,转到标号为int_proc的中断服务子程序中。
int_proc: ;中断服务程序
mov dx,288h ;自8255A口输入一数据 CPU执行标号为int_proc的中断服务子程序时,将立即数0288h(也就是A口的端口地址)传送给DX寄存器。为什么0288h是A口的端口地址?
in al,dx;CPU执行IO的读指令,根据dx寄存器提供的A口的端口地址0288h ,读取A口输入寄存器中的数据(也就是开关状态的值)到al寄存器中
mov dl,al ;CPU执行数据传送指令,将al寄存器的数据传送给dl寄存器。
mov ah,02h ;显示ASCII码为DL的字符CPU执行数据传送指令,将立即数02h传送给ah寄存器。
int 21h;接着CPU执行中断指令,根据中断类型号21h,转到DOS功能调用的中断服务子程序中,CPU在执行DOS功能调用的中断服务子程序时,根据入口参数ah提供的功能号2,CPU再转到显示一个字符的子模块,CPU在执行显示一个字符的子模块时,根据入口参数dl寄存器所提供的数据(也就是开关状态的值),显示其ASCII值对应的符号。
mov dl,0dh ;回车CPU执行数据传送指令,将立即数0dh传送给dl寄存器。
int 21h;CPU执行中断指令,同样,CPU根据功能号为2转到显示一个字符的子模块,显示的是回车符号
mov dl,0ah ;换行CPU执行数据传送指令,将立即数0ah传送给dl寄存器。
int 21h;CPU执行中断指令,同样,CPU根据功能号为2转到显示一个字符的子模块,显示的是换行符号
mov dx,20h ;发出EOI结束命令CPU执行数据传送指令,将立即数20h传送给dx寄存器。
mov al,20h;CPU执行数据传送指令,将立即数20h传送给al寄存器。
out dx,al; CPU执行IO的写指令,根据dx寄存器提供的8259的偶地址端口的端口地址20h,将al寄存器的数据,写到操作命令字OCW2中。这是由于D4D3为00,决定了访问的是OCW2。根据OCW2的格式,由于D5为1,8259产生EOI中断结束命令,使当前服务寄存器ISR对应的D7这一位清零。
dec bl ;CPU执行减1指令,将bl寄存器的数据减1,该指令影响标志位ZF,第一次减1,结果不为0 ,ZF标志位为0
jnz next ;不为0则返回主程序CPU执行jnc条件转移指令。由于ZF为零,条件满足,转到标号为next处,执行中断返回指令,返回到死循环。当再次按下单脉冲按钮CPU又响应中断服务子程序,通过A口再次获取开关状态的值,显示其ASCII值对应的符号
然后bl寄存器中的数据减1,CPU执行jnz条件转移指令,条件满足,转到标号为next处,执行中断返回指令,又返回到死循环。但连续按下单脉冲按钮第8次时,CPU执行中断服务子程序中的减1指令时,结果为0,ZF标志位为1。CPU执行jnc条件转移指令时,由于ZF为1,条件不满足
in al,21h;CPU顺序执行IO的读指令,根据提供的8259奇地址端口的端口地址21h,读取8259屏蔽寄存器IMR的屏蔽字OCW1到al寄存器中。
or al,80h ;CPU执行或运算指令,将al寄存器中的数据最高位D7强制置为1,也就是强制关闭IR7号中断。
out 21h,al ;关IRQ7中断CPU执行IO的写指令,根据提供的8259奇地址端口的端口地址21h,将经过处理后的屏蔽字,写到屏蔽寄存器IMR中,这样就关闭了IR7号中断。
sti ;开中断CPU执行置中断标志位指令sti,使IF标志位为1,CPU开始响应中断。
mov ah,4ch ;然后CPU执行数据传送指令,将立即数4ch传送给ah寄存器。
int 21h;接着CPU执行中断指令,根据中断类型号21h,转到DOS功能调用的中断服务子程序中,CPU在执行DOS功能调用的中断服务子程序时,根据入口参数ah提供的功能号4ch,CPU再转到返回DOS的子模块,结果返回操作系统。
next: iret
code ends
end start
四、实验结论、实验体会