ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

8051实验指导书实战:六个实验从接线到调试全解析

8051实验指导书实战:六个实验从接线到调试全解析

简介:这份实验指导书面向电子信息、自动化等专业学习嵌入式系统的学生,由襄樊学院物理与电子信息工程学院编写,用于支撑单片机与嵌入式课程实验教学。全包共1个doc文档,约965KB,内容完整覆盖6个实验,从实验目的、设备、原理环境到内容、步骤及报告格式均有规范说明。首个实验围绕Keil C51(汇编语言)与ZY15MCU12BD综合单片机实验箱展开,讲解工程建立、源文件加入、编译连接、软件模拟与硬件仿真,并实现P1.0输出1Hz方波、P1.0与P1.1输出反相方波等任务;后续实验延伸至十六进制与十进制转换等顺序结构编程训练。文档还明确预习报告、程序清单与实验总结的撰写要求,可作为课程配套上机手册与实验报告模板使用。已有338人学习下载,适合需要按步骤完成实验、理解开发流程与汇编编程的读者参考。

1. 六个实验拆开看:这份 8051 实验指导书到底能跑通什么

手上这份《嵌入式系统实验指导书(6个实验)》不是那种只给目录和思考题的“空壳文档”,它把每个实验的目的、设备、原理、接线、流程图、参考程序清单和实验报告格式都写全了。核心平台是 8051 内核单片机加一片 8255 扩展口,工具链是 Keil C51 汇编环境,六个实验从点灯、进制转换、数码管动态扫描、矩阵键盘一直做到 ADC0809 采样显示。适合谁?一类是课程设计要交报告、要现场调试的学生,另一类是刚接手 8051 老平台、需要一份能照着接线的工程人员。它解决的不是“学嵌入式要读什么”的问题,而是“实验箱摆在那,线怎么接、程序怎么编、结果不对看哪里”的落地问题。下面按资源结构、关键实验复现、避坑排查、进阶验证四段推进,能抄的代码和参数我尽量给全。

2. 实验平台与工具链:先把 Keil 工程和 8255 地址空间立住

2.1 硬件资源映射与地址分配

这份指导书的实验全部围绕同一套硬件展开,先把资源映射搞清楚,后面写程序才不会乱。核心是一台综合单片机实验箱,CPU 选 Atmel 89C51,晶振 12MHz,通过 RS232 串口与 PC 连接做硬件仿真。片外扩展了一片 8255,A、B、C、控制口分别映射到片外 RAM 的 4000H、4001H、4002H、4003H。这个地址不是随便定的,是实验箱译码电路决定的,写程序时用MOVX @DPTR,A访问,DPTR 装 4000H 就是往 A 口写。

8255 在六个实验里承担了不同角色:实验 3 里 B 口驱动 8 段 LED 的段码,A 口驱动位选;实验 4 里 C 口低 4 位做行输入、高 4 位做列驱动;实验 5 里 ADC0809 的启动和读取映射到 8004H。把这张表贴在显示器边上,比翻文档快得多:

外设端口/地址方向用途
8255 A 口4000H输出LED 位选(低有效)
8255 B 口4001H输出LED 段码(低有效)
8255 C 口4002H高4出/低4入矩阵键盘列驱动/行读入
8255 控制口4003H写方式字 10000001B
ADC08098004H读写启动转换/读结果
EOC 反相P1.0输入查询转换结束

8255 初始化方式字10000001B的含义要拆开看:D7=1 标志位,D6D5=00 选 A 口方式 0,D4=0 A 口输出,D3=0 C 口高 4 位输出,D2=0 B 口方式 0,D1=0 B 口输出,D0=1 C 口低 4 位输入。这个字在实验 4 的参考程序里直接给了,但实验 3 只写“A 口、B 口方式 0 输出,C 口任意”,实际写10000000B也能跑,因为实验 3 不读 C 口。我一般统一用10000001B,省得两个实验之间来回改。

2.2 Keil 工程建立与汇编源文件组织

指导书给的建工程流程是:Project→New Project→选 Atmel 89C51→Target 选项里把晶振改成 12MHz→Output 页勾选生成 HEX→新建 .asm 文件→Add Files to Group。这套操作在 Keil C51 各版本里基本一致,但有两个细节文档没强调:一是工程路径不要带中文和空格,E:\TEST 这种纯英文短路径最稳;二是汇编文件保存时编码选 ANSI,带中文注释的源文件如果存成 UTF-8,老版本 Keil 打开会乱码,编译报错位置还会偏移。

下面这段是实验 1 的参考程序,我补了注释和延时参数说明:

ORG 0000H ; 复位入口,必须从 0000H 开始 AGAIN: CPL P1.0 ; P1.0 取反,产生方波翻转 MOV R0,#10 ; 外层循环 10 次 LOOP1: MOV R1,#100 LOOP2: MOV R2,#250 DJNZ R2,$ ; 内层空转 250 次 DJNZ R1,LOOP2 DJNZ R0,LOOP1 SJMP AGAIN ; 无限循环 END

延时怎么算:12MHz 晶振下机器周期 1μs,DJNZ R2,$本身 2 个机器周期,加上循环开销约 2.5μs 一次,250 次约 0.6ms;乘 100 约 60ms;乘 10 约 0.6s。所以实际输出接近 0.8Hz 而不是精确 1Hz,文档写“1Hz”是近似值。要更准就把 R0 改成 8 或微调 R1,但实验箱上肉眼看不出来,不必死磕。实验 1 的第二个要求是在 P1.0 和 P1.1 输出反相方波,改法很简单:CPL P1.0后面加一句CPL P1.1不行,那样两个口同相;正确做法是初始化时SETB P1.1,循环里只CPL P1.0,P1.1 保持高电平反相关系,或者用MOV C,P1.0再取反送 P1.1。我一般直接写:

AGAIN: CPL P1.0 CPL P1.1 ; 两次取反间隔一个指令周期,严格说不是同时反相 ; 延时... SJMP AGAIN

这样两个口电平始终相反,频率一致,只是翻转有 1μs 偏差,实验要求“电平状态相反”完全满足。

2.3 软件仿真与硬件仿真的切换条件

指导书明确区分了两种运行方式:程序不驱动硬件时用软件仿真(Debug→Start/Stop Debug Session),有硬件动作时必须连实验箱、拨 K10 到 B 端、按 SS10 复位后再进硬件仿真。这个切换点很多人翻车:在软件仿真里跑得好好的程序,一接硬件就没反应,八成是 Debug 页没选“Use”硬件仿真器,或者串口被其他软件占用。另外文档反复强调“修改程序后必须退出连接、重新编译、再重新连接”,这是因为 Keil 的硬件仿真会话不会自动加载新 HEX,不退出重连跑的还是旧程序。

3. 三个核心实验复现:数码管动态扫描、矩阵键盘、ADC 采样

3.1 8 段 LED 动态显示:字形表与 0.5ms 刷新节奏

实验 3 是整个指导书里信息密度最高的一节。6 位 8 段 LED 采用动态驱动,段码走 8255 B 口低电平有效,位选走 A 口低电平有效,刷新频率不低于 50Hz 才能看起来不闪。文档给了完整字形表,从 0 到 F、带小数点、横杠、全灭共 34 个码,按顺序排成表,待显示数 00H~1FH 直接做表索引。这个设计很省事:20H~25H 六个单元存 00H~1FH 的索引,显示子程序逐个取出查表送段口,位码从 FEH 开始左移。

显示子程序的关键参数是每位停留 0.5ms,六位一轮 3ms,刷新率约 333Hz,远高于 50Hz,不会闪。但 0.5ms 延时如果用三层循环写,实际会偏长,导致亮度下降。我一般用 R1 做单层计数:

DISP: MOV R0,#20H ; 显示缓冲区首址 MOV R2,#0FEH ; 位码,左起第一位低有效 MOV DPTR,#SEGTAB ; 字形表首址 DISP1: MOV A,@R0 ; 取待显示索引 MOVC A,@A+DPTR ; 查字形码 MOV DPTR,#4001H MOVX @DPTR,A ; 段码送 B 口 MOV A,R2 MOV DPTR,#4000H MOVX @DPTR,A ; 位码送 A 口 LCALL DELAY05 ; 延时 0.5ms MOV A,#0FFH MOVX @DPTR,A ; 关所有位,防重影 MOV A,R2 RL A ; 位码左移 MOV R2,A INC R0 CJNE R0,#26H,DISP1 RET

这里有个容易忽略的点:关显示要在位码移位之前做,否则换位瞬间上一位的段码还留在 B 口,下一位会短暂显示错误内容,看起来就是“拖影”。文档流程图里画了“关闭所有显示位”这一步,但参考程序清单没给完整实现,很多人抄漏了。字形表按文档顺序从 0 开始排,SEGTAB: DB 0C0H,0F9H,0A4H...,注意 0.~F. 那一段和 0~F 是分开的,索引 10H 对应 0.,别把表排错位。

实验 3 的第三个内容是左移显示 0~F:每 0.5 秒把 20H~25H 的内容整体左移一位,25H 加 1 后与 0FH 相与。这里“调用显示子程序 330 次约 1 秒”是文档给的估算,实际 330×3ms≈1 秒,但如果你把延时改短了,这个次数要跟着调,否则移动速度会变快。我一般把 330 改成 160,配合 0.5ms 延时刚好 0.5 秒左右,视觉上更舒服。

3.2 矩阵键盘扫描:列驱动、行读入与 20ms 消抖

实验 4 的键盘是 4×4 接在 8255 C 口,PC0~PC3 行输入、PC4~PC7 列驱动。扫描逻辑是:依次让某一列输出低、其余列高,读行状态,如果低 4 位不全为 1 说明该列有键按下。文档给了查键值子程序 KEY20,入口 A 高 4 位是列驱动码、低 4 位是行状态,出口 A 是键值 00H~0FH。这个子程序用移位计数算行列号,再查 KEYTAB 表,思路清晰但有个坑:JNB ACC.4,KEY22判断的是列驱动码里第一个 0 的位置,如果列驱动码不是标准单 0 模式(比如消抖时读回的值混进去),列号会算错。

扫描主流程里 20ms 消抖是必须的,文档流程图写了“软件延时 20mS 再读行状态,二次相同才确认”。20ms 用 12MHz 下约 20000 个机器周期,可以写三层循环,也可以复用实验 1 的延时结构把 R0 改成 33 左右。消抖之后还要“读行状态直到键松开”,这一步文档特别提醒要滤掉高 4 位,因为 C 口高 4 位是输出列驱动码,读回来不是稳定的 1。正确做法是ANL A,#0FH再判断是否等于 0FH。

主程序里键盘值和显示缓冲区的移位逻辑是:有新键值时 20H←21H、21H←22H……25H←A,相当于从右端挤入。这个移位顺序和实验 3 的左移显示正好相反,组合起来就是“按键数字从右边进来、整体往左走”。调试时如果发现按一个键显示两个数,多半是消抖没做或者键松开检测漏了;如果显示的数字和按键对不上,先查 KEYTAB 表顺序,文档给的表是 0FH,0BH,07H,03H 开头,对应第一行从右到左,别自己重排。

3.3 ADC0809 采样与十六进制转十进制显示

实验 5 把前面几个实验串起来了:电位器分压送 IN4,写 8004H 启动转换,查询 P1.0(EOC 经反相器)等待结束,读 8004H 得 8 位结果,再把 2 位十六进制转 3 位十进制送 LED 第四~六位显示。转换算法文档在实验 2 里给了:依次除以 100、10,商和余数就是百位、十位、个位。实验 2 是纯软件仿真,30H 放十六进制数,31H~33H 放非压缩 BCD;实验 5 把这段算法嵌进采样流程,输入从 30H 换成 ADC 结果。

除法用 8051 的 DIV AB 指令最直接:A 装被除数,B 装除数 100,执行后 A 是商、B 是余数;余数再除 10,A 是十位、B 是个位。三段结果分别存 33H、32H、31H(注意高低位顺序),然后 20H~25H 里 20H~22H 放灭或前导零处理、23H~25H 放三位数字索引。这里有个显示细节:ADC 结果 00H~FFH 对应 0~255,百位可能是 0,文档没要求消隐前导零,直接显示“0xx”也能接受,但看起来不如消隐舒服。我一般判断百位为 0 时送“灭”码(索引 21H),十位为 0 且百位也为 0 时也送灭,这样小电压时只显示个位。

EOC 查询要加超时,虽然文档没写,但实际调试时如果 ADC 没接好或者启动信号没发出去,JB P1.0,$会死等。加个计数器循环几十次还等不到就跳出错处理,至少不会卡死整个程序:

MOV DPTR,#8004H MOVX @DPTR,A ; 写任意数启动转换 MOV R7,#0FFH WAIT: JNB P1.0,READ ; EOC 反相后低电平表示转换中?按文档接法确认极性 DJNZ R7,WAIT SJMP ERR ; 超时 READ: MOVX A,@DPTR ; 读结果

极性这里要特别注意:文档说 EOC 通过反相器接 P1.0,那么转换结束时 P1.0 应该是低电平还是高电平,取决于反相器接法。指导书写“查询 P1.0 的状态”但没给判断方向,实际以实验箱为准,用单步看一次就清楚了。我遇到过学生把JNB和JB写反,程序要么立刻读要么永远等,这是典型的“文档没写死、现场试出来”的坑。

4. 避坑与排查:六个实验里最容易翻车的五件事

4.1 中文符号混入汇编导致编译报错

现象:编译输出窗口报错行号指向一条看起来完全正确的指令,错误信息是“undefined symbol”或“syntax error”。原因:指令里的逗号、分号、冒号用了中文全角字符,或者数字 0 和字母 o 混淆。指导书在实验 1 的重要提示第一条就写了这个,但每年还是有人中招。解决:Keil 编辑器里把字体换成等宽字体,中文符号明显更宽;编译前用查找替换把全角逗号、分号批量换成半角;养成注释用中文、代码区只用英文输入法的习惯。

4.2 硬件仿真连不上或跑旧程序

现象:点 Start/Stop Debug Session 后提示连接失败,或者连上了但程序行为跟刚改的代码对不上。原因:串口被占用、K10 没拨到 B 端、没按 SS10 复位,或者改完程序没退出会话重新编译。解决:先关掉其他可能占串口的软件,确认 K10 位置,按一次 SS10 再连;每次修改源文件后执行 Build,然后 Stop→Start 重新进会话。指导书反复写“修改后必须退出连接、编译、再连接”,不是啰嗦,是硬件仿真器只认进入会话那一刻加载的 HEX。

4.3 数码管显示重影或亮度不均

现象:数字边缘有暗影,或者某一位明显比别的位暗。原因:换位前没关显示,上一位段码残留;或者每位延时不一致,某一位查表路径长了几个周期。解决:在送新位码之前先往 A 口写 FFH 关所有位,再送段码、送位码;延时用固定子程序,不要在不同位之间插条件判断。如果某一位特别暗,检查该位的位选驱动三极管或限流电阻,实验箱用久了接插件接触不良也会这样,拔插一下排线往往就好了。

4.4 键盘扫描误触发或键值错位

现象:没按键也偶尔出数,或者按 1 显示 4、按 5 显示 8。原因:消抖时间不够、键松开检测没滤高 4 位、KEYTAB 表顺序和实际接线行列反了。解决:消抖延时加到 20ms 以上,读行状态后ANL A,#0FH;用单步在查表前看 A 的高 4 位列码和低 4 位行码是否符合预期,不符合就查接线;键值错位固定偏移时,直接调 KEYTAB 表顺序比改算法快。

4.5 ADC 读数跳变或始终为 0/FF

现象:采样值在小范围内乱跳,或者一直读 00H、FFH。原因:参考电压不稳、IN4 输入悬空、启动写地址错、EOC 极性判断反。解决:先用万用表量电位器中间抽头电压是否随旋钮变化;确认写的是 8004H 不是 8000H;用单步看启动后 P1.0 是否按预期翻转,翻转方向反了就把 JNB 改 JB;读数跳变在 ±2 以内属正常,8 位 ADC 低位噪声,显示时右移一位或做四次平均都能压下去。

5. 从跑通到写进报告:用单步和存储器窗口做验证

六个实验跑通只是及格线,指导书对实验报告的要求其实透露了验证方法:实验原理及环境、实验内容文字叙述、程序清单、实验步骤、实验总结里要写“调试过程、错误及产生的原因”。这意味着验收时老师看的是你能不能定位问题,而不是灯亮没亮。我常用的验证套路是:每个实验先在软件仿真里用单步跑一遍,打开 View→Memory Window,地址栏输d:20H看片内 RAM 缓冲区,输x:4000H看片外 8255 端口;实验 2 重点看 30H 输入和 31H~33H 输出是否符合除权算法;实验 3 看 20H~25H 移位是否按预期滚动;实验 4 按键时看 C 口读回值和 A 返回值是否对应 KEYTAB;实验 5 看 8004H 读出值和后续 BCD 拆分。

单步有个技巧:Step Over 把LCALL DISP当一条指令过,适合看主流程;Step 进去看显示子程序内部,适合查重影和位码。断点设在MOVX @DPTR,A后面,停下来看外设端口实际写进去的值,比盯着 LED 猜快得多。硬件仿真时如果单步导致外设时序乱掉(比如键盘扫描需要连续跑),就改用“运行到光标处”加断点组合。

最后说一个我自己的习惯:每次改完程序,不管改多小,都先 Build 看 Output 窗口有没有 Warning,再进仿真。汇编的 Warning 经常是“符号未定义但地址默认为 0”,这种程序跑起来可能碰巧对,换个芯片就翻车。从那以后我每次交报告前都把 Build 输出截一张图贴在调试过程里,既证明编译干净,也逼自己把 Warning 清零。希望这份拆解能帮你把六个实验从“照着抄”变成“知道为什么这么写”。

本文还有配套的精品资源,点击获取

返回列表