资讯动态

8253+8259A+8255中断实验完整链路搭建与调试避坑指南

发布时间:2026/10/15 4:52:02 来源:尧图企业网站定制
简介一份围绕8253、8259A、8255芯片的中断实验资源面向微机原理、汇编语言与接口技术课程的本科生及实验学习者。实验以8253定时器输出周期信号作为中断请求由8259A中断控制器接收并触发中断再通过8255并行接口控制发光二极管在屏幕上显示THIS IS A 8259 INTERRUPT实现每秒中断一次、共八次后返回DOS的完整流程。文档提供了全套汇编源程序包括数据段、堆栈段、代码段覆盖中断向量表的修改、8253通道0与通道1的初值设置、8259A中断屏蔽寄存器的开启与恢复、8255端口的输出控制以及中断服务程序中计数变量递减和点灯数据右移的关键逻辑有助于理解外部中断从触发到响应的每个环节。压缩包内含1个docx文档大小约14KB便于直接阅读和打印。目前已有1264人学习浏览适合作为课程设计参照、实验报告基础或用于深入掌握8253定时、8259A中断管理和8255并行控制的协同设计。1. 中断实验的真正难点把8253、8259A、8255串成一条能工作的链路很多第一次做中断实验的人会把全部精力放在中断服务程序怎么写结果程序写好了一上电LED死活不闪。问题往往不在ISR而在中断根本就没被正确制造出来。用8253、8259A、8255实现的中断实验看起来要配三个芯片实际上是在训练一条完整的中断链路8253负责按节拍产生请求8259A负责让CPU按优先级响应8255负责把处理结果变成看得见的电平。这篇文章按我自己调试这套实验的顺序把每个芯片的配置、参数换算和最容易翻车的地方拆开讲新手能照着一步步跑通熟手可以直接跳过原理看避坑。2. 先把链路理顺8253产生中断、8259A排队、8255露面2.1 三个芯片为什么缺一不可8253是一个可编程定时器/计数器内部有三个独立的16位计数通道每个通道都有CLK时钟输入、GATE门控输入和OUT输出。它存在的意义是让中断请求变得可控你想让CPU每10毫秒被打断一次就给它一个已知频率的时钟让它数到设定值后从OUT脚输出一个信号。没有它中断就只能靠外部按键手动触发谈不上“定时”。8259A是中断控制器负责管理8级中断请求。CPU只有一根INTR引脚多个设备要抢这一根线时总得有个仲裁者。8259A内部有中断请求寄存器IRR、中断服务寄存器ISR和中断屏蔽寄存器IMRIR0到IR7进来后先排队再按优先级把最该处理的那一个送到CPU。它还会在CPU响应时把中断向量号送上数据总线。没有它你只能把8253的OUT直接接到CPU的INTR上一个中断源倒也能工作但优先级、屏蔽、向量号全部失控。8255是并行接口芯片24根IO线分成A、B、C三组。中断实验里它通常干两件事要么把LED接在PA口让ISR里翻转的电平变成肉眼可见的闪烁要么把按键接在PB口让外部输入能进入CPU。CPU的数据总线是分时复用的直接挂LED会因为电平驱动能力不够而点不亮直接挂按键又会因为没锁存而读不稳8255在这中间做了缓冲和锁存。三个芯片合在一起刚好覆盖了“中断源中断管理结果呈现”三段少一个实验都串不起来。2.2 中断从产生到响应信号到底怎么走把实验箱上的信号链路画一遍很多问题就清楚了一半。8253的CLK脚输入系统提供的固定频率时钟比如实验箱上常见的1MHz计数器不断递减。到达初值后OUT脚输出一个方波或脉冲这个信号直接连到8259A的某一条IR输入线上。8259A收到IR请求后先看IMR里这一位有没有被屏蔽。没被屏蔽的话经过优先级仲裁PIC置高INTR引脚CPU在执行完当前指令且IF标志位为1时向8259A回两个INTA应答脉冲。第一个INTA期间8259A把当前最高优先级的那位写进ISR第二个INTA期间8259A把一个8位中断向量号送上数据总线。CPU拿到向量号后乘4查中断向量表得到ISR入口地址跳进去执行。ISR里做的事情通常是读写8255的端口向PA口写数据让LED变化从PB口读按键状态做判断。ISR结束时CPU必须向8259A发送EOI中断结束命令把ISR里对应的那一位置零否则8259A会以为这个中断还在服务后续同优先级或更低优先级的中断全被拦住。最后IRET返回断点。这里最容易忽略的是最后一步。很多人第一次中断能进第二次再也进不去十有八九是EOI没发。后面避坑章节会专门讲。2.3 最小系统怎么接线端口地址与引脚对应不同实验箱的译码电路不一样端口地址不能照抄但规律是一样的。8253三个计数器各自占一个端口控制字寄存器占一个8259A只占两个端口用A0脚区分奇偶地址8255四个端口分别是PA、PB、PC和控制字寄存器。我调试用的这套实验箱地址分配如下可以作为参考芯片端口地址8253计数器0200H8253计数器1201H8253计数器2202H8253控制字寄存器203H8259A偶地址ICW1/OCW2/OCW3210H8259A奇地址ICW2/ICW4/OCW1211H8255PA口220H8255PB口221H8255PC口222H8255控制字寄存器223H接线时注意8253的GATE0要接高电平否则计数器不工作OUT永远没有输出这是新手最容易漏的一根线。8253的OUT0接8259A的IR08259A的INTR接CPU的INTRINTA接CPU的INTA8255的PA0-PA7接8个LEDPB0-PB3接4个按键。上电之前拿万用表量一遍这些连线比写完代码再查快得多。3. 8253定时器配置先让中断源按你的节拍工作3.1 工作方式怎么选方式3在中断实验里最顺手8253有六种工作方式从方式0到方式5。做中断实验时更常用的是方式3和方式0两者区别很关键。方式0叫“计数结束产生中断”写入初值后输出变低计数到0时输出变高。如果要周期性产生中断软件必须反复重写初值每次中断后都得重来一遍非常啰嗦。方式3叫“方波发生器”写入初值后自动输出连续的方波输出高电平持续一半计数周期低电平持续另一半计数到0时自动重装初值不需要软件干预。对中断实验来说8253的OUT脚接8259A的IR0方波的上升沿或高电平都能触发中断请求而且频率稳定用示波器量OUT脚能看到规则的波形。我一般建议直接选方式3把精力留给后面8259A的初始化。方式2分频器也能用但输出的是窄脉冲接8259A时如果电平配合不好会有偶发漏触发属于给自己找麻烦。方式4和方式5是软件触发和硬件触发的单次计数也不适合做周期中断源。3.2 计数初值计算从时钟频率到中断周期的换算8253的计数初值计算公式很简单初值 CLK输入频率 / 期望中断频率。中断频率和中断周期互为倒数想要每10毫秒中断一次中断频率就是100Hz。如果CLK输入是1MHz初值 1000000 / 100 10000。这里有两个细节。第一初值超过255时必须分两次写入先写低字节再写高字节顺序由控制字里的读写格式字段决定第二8253是16位计数器二进制计数方式下初值范围是1到65535写0会被当作65536。如果你的期望频率算出来初值超过65535说明CLK频率选高了换一个低频时钟源或者把中断周期调长。举例CLK 1MHz想要2ms中断一次频率 500Hz初值 1000000 / 500 2000。想要50ms中断一次频率 20Hz初值 1000000 / 20 50000也没超限。常见参数对比如下中断周期中断频率初值1MHz时钟1ms1000Hz10005ms200Hz500010ms100Hz1000050ms20Hz50000在实验箱上先用10ms这个参数跑通再把周期改小看LED闪烁变快能直观感受8253初值和中断频率的关系。3.3 8253初始化代码控制字字段和写序说明8253的初始化分两步先写控制字再写计数初值。控制字指定了用哪个计数器、怎样读写初值、选什么工作方式。下面这段是把计数器0设成方式3、二进制计数、先写低字节再写高字节的代码。; 8253 初始化计数器0方式3二进制计数 MOV AL, 00110110B ; 控制字00计数器011先低后高011方式30二进制 MOV DX, 203H ; 8253 控制字寄存器端口 OUT DX, AL MOV AX, 10000 ; 初值 1MHz / 100Hz 10000 MOV DX, 200H ; 计数器0端口 OUT DX, AL ; 先写低字节AL 00H 的低8位 MOV AL, AH OUT DX, AL ; 再写高字节AL 00H 的高8位控制字00110110B的每一位都有明确含义bit7-bit6是计数器选择00代表计数器0bit5-bit4是读写格式11代表先写低字节后写高字节bit3-bit2是工作方式选择011代表方式3bit0是计数方式0代表二进制。写初值时注意是先OUT低字节再OUT高字节这个顺序和控制字严格对应。检查8253是否配置成功不用急着看LED直接用示波器或者逻辑分析仪量OUT0引脚。示波器能看到频率约100Hz的方波说明8253已经按预期工作后续再排查8259A时这条链路就是可信的。如果看不到波形先查GATE0有没有接高电平再查CLK0有没有时钟输入最后查初值写序是否正确。4. 8259A初始化加8255联动向量号、EOI和LED一起搞定4.1 ICW1到ICW48259A初始化顺序为什么不能乱8259A的初始化必须按固定顺序写初始化命令字ICW1到ICW4。顺序错了8259A会把后面的数据误解到错误的寄存器里中断行为变得不可预测。ICW1写到偶地址端口210H它的功能是启动初始化序列、声明是否需要ICW4、是单片还是级联、用什么触发方式。ICW2写到奇地址端口211H设置中断向量号的高5位这是8259A后面往数据总线上送向量号的依据。如果ICW1里声明了单片模式ICW3可以跳过如果声明了需要ICW4就必须再往奇地址写一个ICW4用来选择8086模式还是8080模式、是否自动EOI、是否缓冲。一个典型的单片8086模式初始化序列是ICW1 00010011B需要ICW4、单片、边沿触发ICW2 01000000B向量号基址40HICW4 00000001B8086模式、非自动EOI。写完这三个字之后8259A进入工作状态之后向奇地址写入的不再是ICW而是OCW。初始化完成后还要写一个OCW1到奇地址端口设置中断屏蔽字。IMR的每一位对应IR0到IR7某位为1表示屏蔽对应的中断。实验里只用IR0屏蔽字就写11111110B 0FEH只放行IR0其他全部屏蔽可以避免实验箱上其他中断源捣乱。4.2 向量号换算与中断向量表写入8259A在第二个INTA周期送到数据总线上的向量号由ICW2的高5位和触发的中断号IR级别决定。ICW2 40H时IR0对应的向量号是40HIR1是41HIR2是42H依此类推到IR7是47H。换算公式是向量号 ICW2的高5位 IR编号。ICW2的bit7-bit3作为基址高5位bit2-bit0由8259A根据IR编号自动填充。IR编号向量号中断向量表地址IR040H40H * 4 100HIR141H41H * 4 104HIR242H42H * 4 108H在8086实模式下中断向量表位于内存起始地址0000H处每个向量占4个字节低两字节是ISR入口偏移地址高两字节是段地址。要把ISR挂到向量号40H上需要把ISR的偏移地址写到0000:0100H处段地址写到0000:0102H处。这一步最容易出错新手经常把向量号当地址直接用或者忘记偏移地址要乘以4。4.3 8255方式0配置把PA口设成输出接LED8255工作方式0是基本输入输出方式不需要握手信号适合实验里直接驱动LED和读按键。控制字格式是bit7必须为1表示这是方式字bit6-bit5选A组方式00为方式0bit4选PA口方向0为输出bit3选PC高四位方向bit2选B组方式bit1选PB口方向1为输入bit0选PC低四位方向。把PA口设成输出驱动LED、PB口设成输入接按键控制字取10000110B 86H。写完控制字后往PA口写数据就能控制LED亮灭从PB口读数据就能拿到按键状态。; 8255 初始化方式0PA输出PB输入 MOV AL, 10000110B ; 控制字方式0PA输出PB输入 MOV DX, 223H ; 8255 控制字寄存器端口 OUT DX, AL这里有个常见的理解偏差8255和8253的控制字寄存器都在基地址加3的位置但它们是两个芯片由不同的片选信号CS区分地址不同就不会冲突。先写对地址再谈控制字。4.4 一个完整的最小ISR与主程序骨架把ISR和主程序拼起来看。ISR里做三件事让LED状态翻转、处理按键逻辑、发送EOI。主程序里做的事按顺序是初始化8255、写中断向量表、初始化8259A、开中断、进入死循环等待。; 中断服务程序IR0入口 ISR_IR0 PROC PUSH AX PUSH DX ; 翻转LED读当前值取反后写回8255 PA口 MOV DX, 220H ; 8255 PA口 IN AL, DX ; 读当前LED状态 XOR AL, 0FFH ; 取反 OUT DX, AL ; 写回 ; 读按键并做简单判断可扩展成调速逻辑 MOV DX, 221H ; 8255 PB口 IN AL, DX ; 发送EOI往8259A偶地址写20H MOV AL, 20H ; 非指定EOI命令 MOV DX, 210H ; 8259A偶地址端口 OUT DX, AL POP DX POP AX IRET ISR_IR0 ENDP ; 主程序 START: CLI ; 初始化阶段先关中断 ; 初始化8255 MOV AL, 10000110B MOV DX, 223H OUT DX, AL ; 写中断向量表向量号40H MOV AX, 0 MOV ES, AX MOV DI, 40H * 4 ; 向量号换算成表内偏移地址 MOV AX, OFFSET ISR_IR0 MOV ES:[DI], AX ; 写偏移地址 MOV AX, SEG ISR_IR0 MOV ES:[DI2], AX ; 写段地址 ; 初始化8259A MOV AL, 00010011B ; ICW1需要ICW4单片边沿触发 MOV DX, 210H OUT DX, AL MOV AL, 01000000B ; ICW2向量号基址40H MOV DX, 211H OUT DX, AL MOV AL, 00000001B ; ICW48086模式非自动EOI OUT DX, AL MOV AL, 11111110B ; OCW1只放行IR0 OUT DX, AL STI ; 开中断 MAIN_LOOP: NOP ; 主程序做其他事或空转 JMP MAIN_LOOP这段代码里有两个细节值得强调。第一写中断向量表必须在CLI状态下进行否则写偏移和写段之间中断一旦发生CPU会拿到一个只写了一半的向量直接跑飞。第二EOI命令是往8259A的偶地址端口写20H不是往奇地址这个区和ICW1共用一个地址靠命令内容区分。主程序里STI之后的中断响应ISR执行完后会回到MAIN_LOOP继续空转。如果实验箱上有LED你会看到PA口接的8个LED在IR0中断驱动下周期性翻转这就说明整条链路已经通了。5. 避坑初始化死机、频率不对、EOI漏发一次说清5.1 现象一执行STI就死机程序跑飞原因中断向量表没挂好。常见两种情况一种是把STI放在了写向量表之前中断一开CPU查表查到一个空地址另一种是ICW2的向量号选在了系统已经占用的区域比如和8259A默认的时钟中断或键盘中断重叠设备的中断服务被引导到错误的地方。解决初始化顺序严格按照“写向量表→初始化8259A→STI”执行向量号避开08H到0FH这些系统区域用40H以后的数值。写完向量表后可以用调试器查看DS:[100H]处的值是否等于ISR的偏移地址确认表真的写进去了。5.2 现象LED闪烁频率和算出来的对不上差了一倍或乱跳原因一个是8253初值高低字节写序错了控制字声明先写低字节代码却先写了高字节另一个是用了方式0做周期中断每次计数结束后不重装初值中断就乱套。解决回到8253的OUT脚用示波器量实际波形。如果频率是预期的一半检查初值是不是写成了两倍如果波形不完整把工作方式改成方式3。改完代码后先盯着OUT脚确认波形再回来看LED不要越过信号链最前端去猜。5.3 现象第一次中断正常第二次之后再也进不来原因8259A工作在实际中断结束模式下ISR里没发EOI。8259A把IR0当成还在服务ISR寄存器里这一位始终为1后续同优先级的请求全部被压住。解决ISR返回前必须往偶地址端口写20H这是非指定EOI命令把当前服务位清零。养成习惯ISR里任何分支出口都别忘了EOI可以用栈保存现场后先发EOI再处理业务这样即使业务代码出错8259A也不会卡死。5.4 现象8255的LED怎么点都不亮代码看起来没问题原因8255控制字把PA口设成了输入或者压根没选中这个芯片。很多初学者把8255的基地址想当然地当成200H和8253共用一份地址结果操作到了错误的芯片上。解决用万用表量PA0引脚电压写0FFH应该接近高电平写00H应该接近低电平。如果没变化先查CS片选有没有被译码电路选中再查控制字里的方向位。你可以先写一个最简单的程序只往PA口写0AAH用万用表逐脚确认跑通后再接中断逻辑。5.5 现象中断没触发寄存器里怎么查都正常原因这种问题玄学成分最多实际上多数是物理连线断了。8253的GATE没接高电平计数器不工作或者OUT0到IR0的跳线松了或者8259A的INTR没接到CPU引脚上。解决用示波器从信号链前端往后逐级量。先量8253的CLK有没有脉冲再量OUT0有没有方波然后量8259A的INTR引脚有没有拉高。信号在哪一段断了问题就在哪一段不要盯着寄存器猜。这一步能把排查时间从半小时压到五分钟是调中断实验性价比最高的习惯。6. 进阶把固定中断改成按键可调的节奏器跑通基础实验后值得做的一个扩展是固定周期中断升级成可通过8255按键调速的节奏器。做法是把两个按键接在8255的PB0和PB1上主循环里轮询按键修改全局变量ISR里根据这个变量重新计算8253的初值并写入。8253有一个方便的特性运行中直接重新写入初值不会破坏当前计数状态新的初值会在下一个周期生效。所以ISR里可以先读PB口判断按键再根据按键方向调整全局变量最后把新初值拆成高低字节写入计数器0。这样按一次加速键LED闪烁频率提高一档按一次减速键闪烁频率降一档。调试时建议在ISR里加一个计数器变量做分频比如每10次中断才翻转一次LED这样即使中断频率很高肉眼也能观察变化趋势。验证方法很简单用示波器夹在LED引脚上按加速键看波形频率上升按减速键看波形频率下降。如果想更严谨用频率计或者示波器的频率测量功能直接读数把理论值和实测值对比偏差应该在1%以内超过这个范围就去查CLK时钟是否稳定。我第一次调这个扩展时翻车在GATE0忘了接高电平计数器压根没启动示波器屏幕上一条直线查了半小时才发现是根跳线松了。后来所有实验都先量波形再碰代码再没犯过同样的错。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑