
简介并行接口技术是微机原理课程设计的核心考点其本质是CPU通过地址译码与外部设备交换数据。以8255A可编程并行接口芯片为例工程师需掌握控制字配置、端口方向设定及读写时序等基础操作才能构建稳定可靠的输入输出链路。在抢答器这类典型应用中8255A负责按键采集与数码管驱动配合8086汇编程序实现软件防抖与优先锁存而8253定时器则提供倒计时功能形成完整的实时控制方案。该技术体系广泛应用于工业控制器、竞赛计分设备及嵌入式教学实验。本文围绕四路抢答器设计剖析硬件接线、控制字推导及汇编编程细节为课程设计与工程实践提供可直接复用的参考。1. 四路抢答器不是按键判断那么简单抢答器这类题目在每个学期的微机原理课程设计里都少不了表面看是四个按键加一个数码管真正的门槛却在于“谁先按下谁有效”这一条——从按键电平变化到接口读取再到 CPU 锁存选手号任何一个环节的时延差异都会造成判错次序。用 8086/8088 最小系统配 8255A 可编程并行接口芯片来完成它能把地址译码、控制字设置、键盘防抖、显示驱动和程序状态设计全部串起来这也是这道题在微机原理与接口技术课程里长盛不衰的原因。这篇文章按“硬件接线 → 8255 编程 → 8253 倒计时扩展 → 调试验收”的顺序展开从端口地址分配和控制字推导讲起给出可编译的 8086 汇编主程序和可直接抄的 DEBUG 验证命令。适合正在做课程设计的学生也适合需要快速回忆 8255/8253 编程细节的工程师——抢答器本身不复杂但把它调稳定的过程才是这个设计真正的价值。2. 四路抢答器的硬件链路按键、并行接口与数码管的连接设计2.1 为什么选 8086 最小系统加 8255A 而不是单片机课程设计里最常见的坑是做之前先把方案想复杂。有人用 8051 单片机有人用 CPLD 画状态机这些都能实现抢答但和“微机原理”这门课的考察点已经偏离了。这门课的核心是并行接口与接口技术所以要选能体现“CPU 通过地址译码访问外设”这一过程的结构。标准做法是一套 8086 最小系统8086 CPU、74LS373 锁存地址、74LS245 数据缓冲、74LS138 地址译码器再接 8255A 作为并行接口。8255A 提供 3 个 8 位并行口A 口读按键、B 口驱动数码管、C 口分管状态灯和复位键刚好覆盖本题所有输入输出需求。相比单片机方案这套结构多了地址译码和读/写时序的配合学生需要自己画出 74LS138 的译码逻辑来确定端口地址这正是课程设计想考察的。系统时钟一般取 5MHz 或 8MHzI/O 读写周期由 8086 的 M/IO 信号配合 RD、WR 产生。实现时74LS138 的输入接地址线的高位部分输出 Y0~Y7 分别作为 8255A、8253、RAM 等芯片的片选这样每个外设就获得了一段连续的地址空间。记住这个原则8255A 内部有 A0、A1 两根端口选择线所以它至少占用 4 个连续地址地址映射时必须把这几位留出来。2.2 四路按键接口低电平有效、上拉电阻和防抖电路按键部分推荐“按下为低电平”的接法四个微动开关一端分别接 8255A 的 PA0~PA3另一端统一接 GND。PA0~PA3 各自通过一只 10kΩ 电阻上拉到 5V这样松开时读回高电平 1按下时读回低电平 0。选择低电平有效的原因很简单——TTL 接口灌电流能力比拉电流强按键直接对地导通比向外推高电平更可靠。机械按键在按下和松开的瞬间会产生 5~20ms 的不稳定抖动这期间电平会反复跳变。硬件上最经济的办法是在按键两端并一只 0.1μF 瓷片电容再串联一个 100Ω 电阻组成简单的 RC 低通滤波把高频抖动削掉。软件上还要再补一次延时确认读到按键变化后延时 10ms 再读一次两次结果一致才判定为有效按下。两者配合起来基本可以杜绝一次按键被识别成多次触发的问题。显示部分根据题目要求有两种做法。要求低的做法是 4 只 LED 加一个一位数码管LED 接 PC0~PC3 显示哪路先抢到数码管接 PB 口显示选手号。要求高一点的会用两位数码管做倒计时这时候 PB 口输出段码PC0、PC1 分时选中十位和个位利用视觉暂留做动态扫描。无论哪种数码管如果用共阴型段码表必须和硬件一致这是整个系统里最容易出“乱码”的地方。2.3 接口资源分配与端口地址表假设 74LS138 的 Y0 接 8255A 的片选地址线 A9~A3 参与译码A2、A1 悬空或接高电平A0、A1 直接接 8255A 的 A0、A1则可以形成如下地址映射端口方向连接的器件端口地址示例PA0~PA3输入抢答按键 S1~S4按下为低电平2F8HPB0~PB7输出数码管段码a~g、dp2F9HPC0~PC3输出四路状态 LED点亮表示该路抢到2FAHPC4输入裁判复位键按下为低电平2FAH控制字寄存器输出写入 8255A 方式控制字2FBH地址 2F8H~2FBH 不是唯一选择换成 60H~63H 也一样能用关键是 74LS138 的译码逻辑要和程序里的地址对应起来。电路图里还要注意 8255A 的 RESET 端要和系统复位信号连在一起上电时 8255A 所有端口自动进入输入方式避免出现不可控的输出电平。提示PCB 布线时四路按键到 8255A 的信号线尽量等长长度差会带来微小的读取时间差极端情况下会造成两路同时按下时电平到达先后不一致。虽然 CPU 轮询足够快但比赛类设备对时序公平性有要求时不能忽略这一点。3. 8255 控制字与 8086 汇编轮询程序按键检测、去抖与锁存3.1 8255 控制字的推导9AH 是怎么算出来的8255A 有方式 0、方式 1、方式 2 三种工作方式抢答器用方式 0 基本输入输出即可。方式 0 下 A 口、B 口、C 口高低四位都独立定义为输入或输出不做握手不产生中断逻辑最简单也最容易排查问题。控制字格式固定为 D71 表示“方式控制字有效”D6、D5 选 A 口工作方式D4 选 A 口方向D3 选 C 口高四位方向D2 选 B 口方式D1 选 B 口方向D0 选 C 口低四位方向。按 1 表示输入、0 表示输出来配置本题的接口资源得到二进制 1001 1010B即 16 进制 9AH控制字位值含义D71方式控制字有效D6~D500A 口工作于方式 0D41A 口输入接四路按键D31C 口高四位输入接复位键D10B 口输出接数码管段码D00C 口低四位输出接状态 LED有了这个表以后换任何接口分配都能自己推出控制字不需要背现成的数。写初始化代码时注意先送控制字再访问数据端口因为 8255A 上电复位后所有端口默认是输入状态不初始化就把数据往 PB 口写是无效的。3.2 轮询主程序锁存逻辑怎么避免“后按覆盖先按”写完初始化核心问题就变成了如何保证只有第一个按键有效。做法是用一个内存变量 PLAYER 当作软件锁存器初始为 0 表示无人抢答检测到有效按键后把对应选手号写入 PLAYER之后主循环每次检测到按键变化都先检查 PLAYER 是否非 0非 0 就跳过解析不再更新显示。裁判按下复位键把 PLAYER 清 0系统才重新开放抢答。这个方案相比硬件锁存器比如 74LS74 触发器的优点是省一片芯片程序里也更容易扩展——比如增加犯规检测时只需要在锁存条件里加一个“倒计时是否为 0”的判断。缺点是 CPU 必须一直运行扫描循环不能用 HLT 指令进入停机等待功耗稍高但课程设计完全不在乎这点差异。下面是可直接参考的 8086 汇编主程序端口地址按 2.3 节的约定MASM 语法代码里的关键路径都有注释; ; 四路抢答器 - 8255 轮询软件锁存 ; 8255 基址 2F8H: ; PA2F8H 接按键, 按下为0 ; PB2F9H 接共阴数码管段码 ; PC2FAH 低4位接状态LED, PC4接复位键 ; 控制字寄存器2FBH ; STACKSG SEGMENT PARA STACK STACK DW 64 DUP(?) STACKSG ENDS DATASG SEGMENT PARA DATA SEGTAB DB 3FH,06H,5BH,4FH,66H,6DH DB 7DH,07H,7FH,6FH,77H,7CH DB 39H,5EH,79H,71H ; 共阴数码管段码 0~F PLAYER DB 0 ; 0空闲, 1~4已锁定选手号 DATASG ENDS CODESG SEGMENT PARA CODE ASSUME CS:CODESG, DS:DATASG, SS:STACKSG MAIN PROC FAR MOV AX, DATASG MOV DS, AX ; 8255 初始化: A口输入, B口输出, C高4位输入, C低4位输出 MOV DX, 2FBH MOV AL, 9AH OUT DX, AL ; 清显示和状态灯 MOV DX, 2F9H MOV AL, 00H OUT DX, AL MOV DX, 2FAH MOV AL, 0FH OUT DX, AL RESTART: MOV BYTE PTR PLAYER, 0 ; 清软件锁存标志 SCAN: MOV DX, 2F8H IN AL, DX ; 读四路按键 AND AL, 0FH ; 只保留低4位 CMP AL, 0FH ; 全为1表示无人按下 JZ SCAN ; 无人按下则继续轮询 CALL DELAY10MS ; 软件防抖: 延时后再次确认 MOV DX, 2F8H IN AL, DX AND AL, 0FH CMP AL, 0FH JZ SCAN ; 第二次读到全1, 判定为抖动 ; 锁存判断: 已有人抢到就不再响应 CMP BYTE PTR PLAYER, 0 JNZ SCAN ; 解析哪一路按下: 最低位的0对应最早按下的键 MOV BL, 0 ; 记录移位次数 MOV CX, 4 NEXT_BIT: SHR AL, 1 ; 从PA0开始向右移出 JNC FOUND_PLAYER ; CF0 说明该位是0, 键被按下 INC BL LOOP NEXT_BIT FOUND_PLAYER: INC BL ; BL1~4, 对应 S1~S4 MOV PLAYER, BL ; 写入锁存变量 ; 显示选手号 MOV BX, OFFSET SEGTAB MOV AL, PLAYER XLAT ; ALSEGTAB[PLAYER] MOV DX, 2F9H OUT DX, AL ; 点亮对应状态LED MOV AL, PLAYER MOV DX, 2FAH OUT DX, AL WAIT_RESET: MOV DX, 2FAH IN AL, DX ; 读C口, 含PC4复位键 TEST AL, 10H ; PC40 表示复位键按下 JNZ WAIT_RESET CALL DELAY10MS MOV DX, 2FAH IN AL, DX TEST AL, 10H JNZ WAIT_RESET JMP RESTART ; 复位完成, 重新开放抢答 MAIN ENDP DELAY10MS PROC NEAR PUSH CX MOV CX, 0FFFFH DL1: LOOP DL1 POP CX RET DELAY10MS ENDP CODESG ENDS END MAIN代码的逻辑顺序是初始化 8255 → 清空锁存标志 → 循环读 PA 口 → 检测到低电平后延时去抖 → 确认有效 → 检查锁存变量 → 解析选手号 → 显示并点亮 LED → 进入复位等待。其中 SHR 指令和 LOOP 配合从最低位开始逐位检查哪个按键是 0避免了写四段重复的 CMP 分支数据通路更清晰。DELAY10MS 里的 CX 初值 0FFFFH 是按 5MHz CPU 主频估的延时量换成 8MHz 或 10MHz 晶振时要把循环次数适当加大否则去抖时间不足。调试时如果发现按键偶尔连跳两次优先增大这个循环次数而不是改硬件。3.3 轮询方式的两个边界问题轮询方案里有一个容易被忽略的边界如果两个按键在 CPU 两次读取之间同时按下程序读到的电平可能是“都按下”这时候 SHR 解析只会识别最低位造成高编号选手永远输给低编号选手。绝大多数课程设计不要求处理这种物理级同时性但如果题目里写了“两路同时按下时由裁判判定”就得在硬件上加一套优先编码器比如 74LS148把四位按键编码成 3 位二进制码再送给 PA 口。这属于硬件扩展题程序侧的变化是解析部分从查位改为直接读取编码值。另一个边界是倒计时到 0 之后的按键响应。实现上只要在 SCAN 循环里增加判断倒计时变量为 0 时跳过按键解析直接等待复位键。这个逻辑放到第 4 章配合 8253 一起讲原因是要先有计时来源才能谈超时判定。4. 用 8253 定时器为四路抢答器增加倒计时与超时判定4.1 8253 的接线方式两个计数器串联产生 1Hz 秒脉冲很多课设做到这里就停了显示选手号、状态灯亮、复位——功能完整但缺少“时间”维度。加倒计时是让设计上档次的最短路径而 8253/8254 可编程定时器就是干这个的。8253 内部有三个独立的 16 位计数器每个都有 CLK 时钟输入、GATE 门控输入和 OUT 输出。把 OUT0 接到下一个计数器的 CLK1把两个计数器串联起来总的分频系数就是两个初值的乘积。这样做的直接原因是单计数器最大初值只有 65535而系统时钟通常是 1.19318MHz 或 2MHz要让输出频率达到 1Hz单级分频根本装不下。以 1.19318MHz 的 PC 标准时钟为例要得到 1Hz 方波总分频系数是 1193180。拆成两级计数器 0 先除以 1193输出约 1000Hz计数器 1 再除以 1000输出约 1Hz。两个初值都在 16 位范围内刚好成立。GATE 端都接 5V 保持常开。OUT1 输出端接到 8259A 中断控制器的 IR0或者接到 8255A 的 PC5 上让程序轮询读取两种方式对应中断和查询两种计时实现。课程设计推荐用查询方式减少中断嵌套的复杂度但要展示接口技术能力的话走 8259 中断更完整。4.2 8253 控制字、初值装载和中断服务程序两个计数器都工作在方式 2分频器模式输出一个周期内大部分时间为高电平、末尾输出一个窄低脉冲适合作为周期信号源。控制字计算如下计数器控制字控制字值功能说明计数器 00011 0100B34H方式 2二进制计数先写低字节后写高字节计数器 10111 0100B74H方式 2二进制计数先写低字节后写高字节8253 的地址分配延续前文风格端口地址取 2F0H~2F3H2F0H 是计数器 0 通道2F1H 是计数器 1 通道2F3H 是控制字寄存器。初始化代码和初值装载如下; ; 8253 初始化: 计数器0 分频得 1000Hz, ; 计数器1 再分频得 1Hz, OUT1 送 8259 的 IR0 ; 8253 端口: C02F0H, C12F1H, 控制2F3H ; MOV DX, 2F3H MOV AL, 34H ; C0: 方式2, 二进制, 读写两字节 OUT DX, AL MOV AL, 74H ; C1: 方式2, 二进制, 读写两字节 OUT DX, AL MOV DX, 2F0H ; 装载计数器0初值 1193 MOV AX, 1193 OUT DX, AL ; 先写低字节 MOV AL, AH OUT DX, AL ; 再写高字节 MOV DX, 2F1H ; 装载计数器1初值 1000 MOV AX, 1000 OUT DX, AL MOV AL, AH OUT DX, AL初值装载顺序必须和初始化时设定的读写格式一致。设了“先低后高”就必须先 OUT 低字节再 OUT 高字节反过来写进去的计数值就完全错乱。计数器在写入初值后自动开始从该值向下计数计到 0 时 OUT 端输出一个脉冲并自动重装初值不需要 CPU 干预这保证了秒脉冲的连续性。有了 1Hz 中断信号倒计时变量就能在中断服务程序里递减。中断服务程序要做四件事保护现场、向 8259 发送中断结束命令 EOI、修改倒计时变量、恢复现场并返回。示例如下; TIMESEC 定义在数据段, 初始值为 30 ; CNT1S DB 0 ; 秒标志, 主循环查询用 TIMER_ISR PROC NEAR PUSH AX PUSH DS MOV AX, DATASG MOV DS, AX ; 发送 EOI, 结束 8259 中断 MOV AL, 20H OUT 20H, AL DEC WORD PTR TIMESEC ; 倒计时减1 JNS TIMER_EXIT ; 结果不为负则结束 MOV WORD PTR TIMESEC, 0 ; 到0后保持一致, 不再继续减 TIMER_EXIT: POP DS POP AX IRET TIMER_ISR ENDPEOI 命令必须放在中断服务程序的靠前位置否则 8259 会一直认为中断正在处理中后续中断无法响应。JNS 判断用于防止倒计时减成负值显示倒计时的时候不会出现“负 1 秒”。主循环里要做的只是在显示函数前检查 TIMESEC 是否为 0为 0 就跳过 SCAN 中的按键解析逻辑直接进入复位等待。这样“超时后按键无效”就自动成立了。反馈到题目要求上等于给抢答器增加了最常用的一条比赛规则30 秒内无人抢答本题作废。4.3 显示倒计时时端口复用的问题有了倒计时数码管就不止显示选手号了。常见的处理办法是把 2FBH 控制字里的 C 口低四位继续用作 LED 显示再增加 PB 口配合两个数码管做动态扫描。主循环每 5ms 刷新一次十位和个位数码管轮流导通由于人眼视觉暂留效应看到的始终是完整的两位数。刷新频率太低会闪烁太高会增加 CPU 负担5ms 对应 200Hz 刷新率是比较稳妥的选择。真正要留意的是显示缓冲区的统一。建议在数据段里定义 DISPBUF 数组主循环把 TIMESEC 或 PLAYER 的值换算成段码写入 DISPBUF显示函数只负责扫描 DISPBUF这样抢答显示和倒计时显示就可以共用一套刷新逻辑不会出现切换状态时数码管闪一下的错误。5. 调试四路抢答器的常用方法和课程设计验收要点5.1 用 DEBUG 直接验证 8255 端口状态程序写好后不要急着全功能联调先用 DEBUG 这类调试工具验证 8255 的端口地址和控制字是否真的生效。在 PC 兼容机的 DEBUG 环境下直接执行 I/O 命令向端口写入数据-o 2fb 9a ; 向8255控制字寄存器写入9AH -o 2f9 3f ; PB口输出“0”的段码0x3F, 数码管应显示0 -o 2fa 01 ; PC0置1, 第一路状态LED应点亮 -i 2f8 ; 读取PA口: 无键按下应返回0F, 按下S1返回0E-w 前面先验证输出通道再验证输入通道。如果 PB 口输出段码后数码管不亮优先检查共阴共阳是否选错如果 LED 不亮检查 PC 口是不是被控制字设成了输入方向此时高电平写不进去。输入通道用短路线把 PA0 对地短接再执行 -i 2f8返回值应该从 0F 变成 0E否则要量 8255A 的 RD 引脚在命令执行期间有没有拉低。5.2 常见故障现象与排查对照表故障现象排查顺序按下按键无任何反应量 PA0~PA3 静态电平是否 5V按下是否到 0V再量 8255 的 CS 是否有效数码管显示乱码检查段码表与共阴/共阳是否匹配检查 PB 口数据线是否短路第二路按键也能修改显示检查 PLAYER 锁存变量是否被复位检查去抖延时是否过短导致重复触发倒计时不走用示波器量 8253 OUT1 是否有 1Hz 脉冲量 GATE1 是否在高电平复位键无效确认 PC4 在控制字中是不是设成了输入方向检查复位键是否也做了防抖这里特别强调一点程序里最容易出问题的不是按键解析而是复位后状态没有完全清干净。PLAYER 清 0 了但 LED 和数码管还保留着上一轮的显示CPU 速度快时看不出毛病一旦现场演示裁判会明确指出“复位后还显示着 3 号”。所以 RESTART 入口处要同时做三件事清 PLAYER、熄灭全部 LED、清空显示缓冲区。5.3 答辩前的三个功能验证场景验收时评委一般会随机考验三个场景。第一个是顺序抢答依次按 S1、S3、S2最终显示应该是 1之后按 S4 不应该改变显示。第二个是两键同时按下用一根导线同时短接 S1 和 S2因为程序从最低位开始解析结果会锁定为 1 号评委如果追问就解释这是软件优先级策略硬件上可以加 74LS148 改成随机处理。第三个是倒计时超时把 TIMESEC 初值临时改成 3 秒等待倒计时归 0 后再按任意键显示不应变化。这三个场景分别对应优先级锁存、并发处理和超时机制把任何一条做扎实了都能在答辩时主动展示而不是等老师提问。文档的流程框图也建议按这三个路径画主程序循环、按键中断/查询分支、定时器中断分支保持和代码逻辑一一对应。本文还有配套的精品资源点击获取