
简介面向微机接口技术课程学习者的8255A基础实验报告围绕Intel可编程并行接口芯片在方式0下的典型应用展开适合正在做实验、写实验报告或准备课程设计的学生对照参考。文档完整记录三个实验用A口输出学号后两位驱动8个LED静态显示通过B口读取8个逻辑开关状态再由A口回送到LED借助段码与位选控制七段数码管显示另一名同学的学号。每个实验均配有硬件连线图、程序流程图、带详细注释的汇编源代码、实验现象与结论以及问题分析可直接作为报告模板与调试参照。整包仅1个docx文件约141KB轻量易查阅。目前已有809人学习下载。读者可从中理清8255A三个端口的分组与控制字设置思路掌握方式0输入输出的初始化与读写流程并借鉴实验现象的记录写法减少连线与程序调试中的弯路。1. 实验箱上电后那份六页双面打印的报告到底能复现什么实验箱上电八个 LED 全灭你手里那份微机接口 8255A 实验报告只有六页双面打印三个实验的代码加起来不到一百行。可真到自己接线、改端口地址、调延时的时候卡住的地方往往不在代码本身——控制字写错一位现象就是灯全亮或者全灭位选移位方向搞反数码管就从右往左串。这份报告对应的是 8088 系统下 8255A 方式 0 的基础训练A 口驱动 LED、B 口读开关、A/B 口配合做七段数码管动态扫描。它适合正在上微机接口课、需要把实验箱跑通的人也适合隔了几年想快速回忆 280H~283H 地址分配和控制字位定义的人。下面按“原理立住—代码复现—时间账—避坑”的顺序拆接线和代码都能直接照着来。2. 8255A 的地址与控制字先把 280H/283H 和 80H 讲透代码只有几十行但决定能不能跑通的是两件事端口地址对不对、控制字每一位什么意思。这两件事错了现象会非常“玄学”——灯全亮、全灭、或者只有一位乱闪你盯着代码看半天也看不出问题。所以先不贴代码把地址译码和控制字逐位拆开后面三个实验才有落脚点。8255A 内部有 A、B、C 三个 8 位数据端口和一个控制寄存器对外只用 A0、A1 两根地址线做片内选择片选信号来自高位地址译码。实验箱把这片 8255A 映射到 280H 起始的四个连续地址于是才有了代码里反复出现的 280H、281H、283H。2.1 三个端口四个地址280H~283H 是怎么分出来的A0、A1 的组合直接决定选中哪个寄存器这是硬件决定的改不了。把这两根线理解成“寄存器编号”就行A1A0选中对象常见地址读/写用途00A 口数据寄存器280H输出 LED 数据、输出位选01B 口数据寄存器281H读开关、输出段码10C 口数据寄存器282H本组实验未直接用11控制寄存器283H写方式控制字高位地址经译码后产生片选只有片选有效时这四个地址才真正落到 8255A 上。实验箱上通常有地址跳线或固定的 I/O 译码电路报告里默认就是 280H 这一组。你自己接线前先确认实验箱说明书上的基地址如果不是 280H代码里所有 DX 赋值都要跟着换这是最常见的第一道坎。C 口在这三个实验里没有单独接线但它在控制字里仍要参与配置因为 A 组包含 C 口高四位、B 组包含 C 口低四位配置时躲不开。还有一点容易被忽略地址是字节地址端口是字节宽。8088 用OUT DX, AL一次送一个字节正好对应 8 位 LED 或 8 位开关不需要拆字操作。这也是方式 0 最适合入门实验的原因——没有握手、没有中断写进去就输出读进来就是当前电平。2.2 控制字 D7~D0 逐位拆80H、82H 到底在说什么8255A 的方式控制字是一个字节D7 是特征位。D71 表示这是方式设置字D70 表示这是 C 口按位置位/复位字两者不能混。实验里用到的都是 D71 的方式设置字逐位含义如下位名称取值含义D7特征位必须为 1表示方式设置字D6 D5A 组方式00方式 001方式 11x方式 2D4A 口方向1输入0输出D3C 口高四位方向1输入0输出D2B 组方式0方式 01方式 1D1B 口方向1输入0输出D0C 口低四位方向1输入0输出注意 D4 和 D1 的方向定义1 是输入0 是输出很多教材的表格排版容易看反血泪经验是写代码前先默念一遍“1 进 0 出”。按这张表回看报告里的两个值80H 1000 0000BA 组方式 0、A 口输出、C 高输出B 组方式 0、B 口输出、C 低输出。整体全输出对应 LED 静态显示实验。82H 1000 0010BA 组方式 0、A 口输出、C 高输出B 组方式 0、B 口输入、C 低输出。A 出 B 进对应开关量回显实验。报告里写的10000010B就是 82H只是换成了二进制写法本质一样。数码管实验里用的10000000B又是 80H和 LED 静态实验相同因为段码和位选都从 A、B 口往外送全部配置成输出即可。控制字只需要在程序开头写一次循环体里不要再重复写重复写不会报错但会白白占掉指令周期动态扫描时尤其要避免。2.3 方式 0 的读写时序为什么必须先写控制字再碰数据口8255A 复位后所有端口默认是方式 0 输入控制寄存器内容为 0。也就是说上电后你不写控制字A、B、C 三口全是输入这时候往 280H 写数据是写不进去的LED 不会有任何反应。这是初学者最常翻的车代码里地址没错、数据也没错就是灯不亮原因就是漏了那三行初始化。方式 0 是基本输入/输出没有握手信号OUT指令把数据送到数据总线8255A 在写信号有效沿把数据锁进对应端口寄存器引脚上立刻反映出来IN指令则把引脚电平锁进端口寄存器再读到 AL。整个过程中 A0、A1 决定去哪个寄存器片选决定访不访问这片芯片读写信号决定方向。顺序上一定是先往 283H 写控制字定方向再往 280H/281H 读写数据。还有一个细节控制字写完之后到第一次读数据口之间建议留几条指令的间隔。8088 的总线周期和 8255A 的建立时间在实验箱的低速环境里通常够用但如果你把初始化放在循环里反复执行偶发的方向切换毛刺会让输出闪一下。稳妥做法是初始化只做一次主循环只做数据搬运。3. 三个实验的代码复现从 LED 静态到数码管动态扫描原理清楚之后三个实验其实是同一套骨架的三种变体初始化 8255A、往数据口写或从数据口读、需要时加循环。差别只在控制字、数据来源和是否要动态刷新。下面按报告里的顺序逐个复现代码保留原结构注释补全关键参数每段后面说明逻辑和可调的地方。汇编环境按 MASM 的段定义写END START告诉汇编器入口标号。3.1 LED 静态显示把学号后两位变成一个字节写进 A 口DATA SEGMENT ID DB 01H ; 学号后两位对应的二进制值01H 00000001B DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX, DATA MOV DS, AX ; 初始化数据段 MOV AL, 80H ; 控制字A组方式0、A口输出、B组方式0、B口输出 MOV DX, 283H ; 控制寄存器地址 OUT DX, AL ; 写入控制字确定端口方向 MOV AL, ID ; 取学号字节直接寻址取变量内容 MOV DX, 280H ; A口数据地址 OUT DX, AL ; 送 A 口8 个 LED 显示对应位 MOV AH, 4CH INT 21H ; 返回 DOS CODE ENDS END START这段代码的骨架只有“初始化—取数—输出”三步。关键参数是ID报告里写01对应二进制00000001B所以只有最低位为 1。现象描述“前七个不亮、最后一个亮”说明实验箱上 LED7~LED0 与数据位 D7~D0 的对应关系是 D0 对应最右边那个灯输出高电平点亮。你自己做的时候先确认 LED 是共阴还是共阳、高电平亮还是低电平亮如果是低电平亮输出值要取反否则现象正好相反。这里有个容易踩的坑学号后两位是十进制数字比如“01”“27”不能直接当成 BCD 码往端口送。01H在汇编里是十六进制 1对应的二进制是00000001B这才是 LED 要的位模式。如果你写DB 01多数汇编器按十进制处理值还是 1但换成DB 27就是十进制 27二进制00011011B和“学号 27”的 BCD 码0010 0111B不是一回事。正确做法是先把两位十进制学号转成二进制数再送端口报告里的01恰好数值小两种理解碰巧一致别被这个巧合带偏。3.2 开关量回显B 口读、A 口写的轮询骨架DATA SEGMENT DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AL, 82H ; 控制字A口输出、B口输入、均为方式0 MOV DX, 283H OUT DX, AL ; 初始化方向 LP1: MOV DX, 281H ; B口数据地址 IN AL, DX ; 读 8 个开关状态到 AL MOV DX, 280H ; A口数据地址 OUT DX, AL ; 原样送 A 口驱动 LED JMP LP1 ; 无限轮询 CODE ENDS END START控制字82H把 A 口设成输出、B 口设成输入这是整个实验的核心。LP1循环里先IN后OUT没有延时也没有判断开关拨一下下一次循环 LED 就跟着变实时性取决于循环执行速度8088 上这个循环是微秒级肉眼看起来就是即时跟随。参数上要注意两点。第一B 口读进来的值是不是和 LED 位序一致。开关通常一端接地、一端接端口拨到 ON 时读回 0 还是 1取决于接线是下拉还是上拉。如果发现开关拨上和 LED 亮灭相反别急着改代码先看实验箱开关电路的有效电平必要时在IN之后加一条NOT AL取反。第二A 口输出和 B 口输入的地址别写反281H 是 B 口数据口不是控制口报告里那句“写 8255A 控制 B 口地址”的注释是笔误实际访问的是 B 口数据寄存器控制口始终是 283H。这个轮询结构可以直接扩展成“读 C 口某几位、判断后输出到 A 口”的小逻辑比如用两个开关控制 LED 的流水方向。扩展时控制字要相应调整 C 口方向位别只改数据口不改控制字。3.3 七段数码管动态扫描段码表、位选和延时三件套DATA SEGMENT NO DB 0,0,1,5,0,7,0,2 ; 八位数码管要显示的学号从最高位到最低位 LED DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ; 共阴极 0~9 段码 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX, DATA MOV DS, AX MOV AL, 80H ; A、B 口全输出方式0 MOV DX, 283H OUT DX, AL FLAG0: MOV DI, 0 ; DI 指向学号数组当前位 MOV CL, 8 ; 共 8 位数码管 MOV AH, 10000000B ; 位选初值B71 选中最高位数码管 FLAG1: MOV AL, NO[DI] ; 取当前位要显示的数字 0~9 LEA BX, LED ; BX 指向段码表基址 XLAT ; AL [BXAL]查表得到段码 MOV DX, 281H OUT DX, AL ; 段码送 B 口 MOV AL, AH MOV DX, 280H OUT DX, AL ; 位选送 A 口只有一位为 1 MOV AL, CL ; 保存外层循环计数 MOV CX, 0FFH ; 延时初值可调 FLAG2: LOOP FLAG2 ; 软件延时让当前位亮够时间 MOV CL, AL ; 恢复外层计数 ROR AH, 1 ; 位选循环右移换到下一位 INC DI ; 指向学号下一位 LOOP FLAG1 ; 8 位扫完一轮 JMP FLAG0 ; 从头再扫 CODE ENDS END START这段是三个实验里唯一需要“时间管理”的。段码送 B 口、位选送 A 口同一时刻只有一位位选为 1八个数码管轮流点亮靠人眼视觉暂留拼成完整学号。XLAT指令用 AL 作索引、BX 作表基址取出LED表里的段码索引就是NO[DI]里的 0~9。ROR AH,1让位选从10000000B逐次右移到00000001B对应从最高位数码管扫到最低位。延时循环MOV CX,0FFH加LOOP FLAG2是报告里明确提到的关键点。不加延时位选切换太快前一位的段码还没从数码管上消失就切到下一位会出现“后一位从影”看起来像数字叠在一起。加上 255 次空循环后每一位点亮时间拉长到肉眼无法分辨切换显示就稳定了。这个值不是固定的实验箱时钟、数码管余辉、环境亮度都会影响0FFH不够就加到1FFH或2FFH但加太大整屏会闪。另外要提醒一个报告自身的不一致NO数组第四位是5而现象记录写的是“0、0、1、6、0、7、0、2”。按代码走第四位应该显示 5。复现时以代码和段码表为准报告里的现象记录可能是笔误别为了对上文字去改数组那样反而把正确的显示该坏了。4. 动态扫描的时间账延时循环、重影与刷新率估算动态扫描能骗过眼睛靠的是刷新率和占空比两个参数配合。刷新率太低会闪占空比太低会暗位选切换不留死区会串影。这一章把这三个量拆开算一遍你调延时的时候心里就有数而不是靠反复烧程序试。4.1 重影从哪来位选切换与段码保持的时间窗口重影的本质是“该灭的时候没灭干净”。动态扫描的时序是送段码、开位选、延时、关位选、换下一位。如果关位选和送新段码之间没有间隔或者延时太短前一位的段码还留在数据总线上下一位的位选已经打开于是下一位数码管短暂地显示了上一位的段码看起来就是数字叠影。报告里加LOOP延时拉长的是“开位选”的持续时间让每一位亮得更久相对地缩短了切换瞬间的占比影就淡了。更彻底的做法是“先关显示再换数据”在ROR AH,1之前先把 A 口输出 0让所有位选关闭再送新段码、开新位选。这样切换瞬间屏是全黑的人眼察觉不到重影从根上消失。代价是亮度略降因为每位多了一段熄灭时间。实验箱上数码管余辉通常够先加延时、再加关显示两步做完基本就干净了。4.2 LOOP 延时的粗略估算与可调参数8088 上LOOP指令的周期数按经典资料大约 17 个时钟周期取 4.77MHz 主频估算一次LOOP约 3.6 微秒255 次约 0.9 毫秒。八位一轮约 7.3 毫秒刷新率约 137Hz远高于人眼闪烁阈值所以看起来是稳定的。这个估算不精确因为实验箱实际时钟、总线等待周期、指令预取都会影响但量级是对的用来判断“该加还是该减”足够了。调参时记住两个方向延时加大单点亮的时间变长、整屏刷新率下降加到一轮超过 20 毫秒刷新率低于 50Hz就会开始闪延时减小刷新率上升但单点亮变短太短会暗、会串影。工程上常用的是每位 1~2 毫秒、整屏刷新 60Hz 以上。报告里的0FFH落在 0.9 毫秒附近是个合理的起点觉得暗就往上加一档觉得闪就往下减别一次改一个数量级。4.3 共阴极段码表的由来与校验方法段码表3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH对应共阴极接法位定义是 D0a、D1b、D2c、D3d、D4e、D5f、D6g、D7dp某位为 1 则该段亮。以数字 0 为例a、b、c、d、e、f 六段亮、g 和 dp 灭二进制0011 1111B就是 3FH。数字 1 只要 b、c 亮0000 0110B是 06H。数字 6 需要 a、c、d、e、f、g 亮0111 1101B是 7DH和表里一致。校验方法很简单拿万用表二极管档红表笔接公共端共阴接法公共端接地黑表笔依次碰 a~g 引脚哪一段亮就记下对应的位。或者直接写一段只输出单个段码的死循环程序看哪几段亮反推位序。如果你手里的实验箱是共阳极整张表要按位取反3FH变成C0H这一点接线前必须确认接反了要么全亮要么全灭。5. 避坑与排查接线、控制字、延时三类翻车记录这三个实验代码量不大但翻车点很集中。下面五条是照着报告复现时最容易遇到的按“现象→原因→解决”写每条都对应一个具体的检查动作。先看现象定位到哪一类再动手改比盲目重写代码快得多。5.1 五条现象到根因的排查记录第一条八个 LED 全不亮代码检查不出错。现象是上电后无论怎么改数据灯一点反应没有。原因多半是控制字没写或者写错地址端口还停在复位默认的输入状态OUT写不进去。解决用调试器在OUT DX,AL控制字那一条后设断点读 283H 确认写入值同时确认DX是 283H 而不是 280H。地址写错一位控制字就跑到 A 口去了方向自然没配。第二条开关拨动LED 亮灭和开关状态相反。现象是开关拨到 ON对应 LED 灭拨到 OFFLED 亮。原因是开关电路的有效电平和 LED 驱动极性没对齐IN读回来的 0/1 与预期反了。解决先查实验箱开关是接地有效还是接高有效再看 LED 是高电平亮还是低电平亮两者相反时在IN后加NOT AL或者改接线不要靠猜。第三条数码管显示重影数字叠在一起。现象是相邻两位的数字有残影尤其亮段多的数字明显。原因是位选切换太快、延时不够或者切换时没有先关显示。解决先把MOV CX,0FFH加到1FFH看是否改善改善了就说明是延时问题如果还有影在ROR AH,1前把 A 口输出 0 关掉所有位选再送下一位。第四条数码管只亮一位或者八位显示同一个数字。现象是位选没走起来或者段码没跟着索引变。原因通常是ROR AH,1的方向或初值错了或者XLAT前 AL 不是 0~9 的索引比如把段码当索引用。解决单步看 AH 每次移位后的值确认从10000000B逐次右移到00000001B再确认NO[DI]取出来的是数字而不是段码XLAT的索引必须在 0~9 范围内。第五条程序烧进去跑飞或者端口完全没有输出。现象是实验箱无反应调试器也停不下来。原因可能是段寄存器没初始化、END后面的入口标号写错、或者实验箱的地址跳线没接到 280H 这一组。解决先确认MOV AX,DATA/MOV DS,AX两行在END START的标号和代码段入口一致再用调试器读 280H如果读出来是 FFH 且写不进去回头查硬件片选和跳线。5.2 上电自检顺序先灯后开关再数码管接线之前先跑一遍自检能省掉一半的来回。第一步只接 LED 和 A 口跑 3.1 的静态显示确认灯能按位点亮说明地址、控制字、数据通路都通。第二步接开关和 B 口跑 3.2 的回显确认IN能读到变化说明输入方向配置正确。第三步再上数码管先只接一位、固定显示一个数字确认段码和位选都对再扩到八位做扫描。这个顺序的好处是每一阶段只引入一个新变量出问题时排查范围小。自检时把控制字的值写在纸上贴在实验箱旁边80H对应全输出、82H对应 A 出 B 进每次改代码先对一眼比事后猜省事。5.3 用调试器单步看端口比反复改代码快现象不对时第一反应不应该是改代码重烧而是单步看端口。在控制字写入后停住读 283H 确认值在数据口OUT后停住用调试器的端口查看功能读 280H/281H看写进去的值和读回来的值是否一致。如果写 280H 读回来不变说明片选或地址有问题如果写进去变了但灯不亮问题在接线或 LED 极性。单步还能看到ROR AH,1每一步 AH 的实际值位选错位一眼就能发现。这套方法比“改一个参数烧一次”快得多尤其是动态扫描这种时序相关的现象静态观察比反复试错可靠。6. 从实验报告到可复用骨架子程序化与上机验收清单三个实验跑通之后代码还是散的初始化一段、输出一段、扫描一段换个实验就要复制粘贴改地址。把它们收成子程序下次做 8255A 相关的课设或小项目直接调用就行。下面给一个最小骨架初始化、字节输出、数码管扫描各一个入口参数用寄存器传地址用常量集中定义改基地址只改一处。6.1 收成三个子程序; 常量集中定义换实验箱只改这里 P8255_A EQU 280H P8255_B EQU 281H P8255_CTL EQU 283H ; 初始化A口输出、B口输入、方式0 INIT_8255 PROC MOV DX, P8255_CTL MOV AL, 82H OUT DX, AL RET INIT_8255 ENDP ; A口输出一个字节入口 AL数据 OUT_A PROC MOV DX, P8255_A OUT DX, AL RET OUT_A ENDP ; B口读一个字节出口 AL数据 IN_B PROC MOV DX, P8255_B IN AL, DX RET IN_B ENDP骨架的价值在于把“地址”和“方向”从业务代码里剥离出来。INIT_8255只在程序开头调一次后面所有输出都走OUT_A或直接写数据口读开关走IN_B。数码管扫描可以在此基础上加一个SCAN_ONCE子程序把 3.3 里FLAG1那一段包进去主程序只负责循环调用和更新显示缓冲区。这样改学号、改显示内容只动数据段不动时序逻辑。6.2 上机验收清单检查项预期现象判据控制字写入283H 读回 80H 或 82H读回值等于写入值A 口输出写 01H 后最右 LED 亮位序与接线一致B 口输入拨动任一开关读回值对应位翻转无抖动、无粘连段码表固定显示 8七段全亮无缺段、无多段位选移位单步看 AH 从 80H 到 01H八位依次选中刷新效果八位学号稳定不闪、无重影距离 30cm 目视无叠影验收时按表逐项打勾任何一项不过就回到对应章节查不要跳步。尤其是位选移位那一项单步看 AH 的值比看屏幕可靠屏幕会骗人寄存器不会。从那以后我每次上实验箱都先把 283H 的控制字写一遍、用调试器读回确认再动手接数据线这个习惯帮我省掉了至少一半的“灯不亮”排查时间。动态扫描的延时值我也习惯先按 0FFH 起步、单步看一轮时间再调而不是一次改到 2FFH 然后对着闪烁的屏发愣。希望帮到你。本文还有配套的精品资源点击获取