
简介这份实验指导书面向高校电子信息、自动化等专业学生及嵌入式初学者系统梳理嵌入式系统课程实验的完整流程与规范要求帮助读者在缺乏教师逐条讲解时也能独立完成实验并规范撰写报告。压缩包内共1个doc文档约965KB内容按实验逐项编排涵盖实验目的、设备、原理与环境、内容、步骤及报告格式等模块并给出预习、实验过程与实验后总结三阶段的具体要求。指导书以Keil C51使用汇编语言为起点涉及工程建立、源文件加入、编译连接、软件模拟与硬件仿真调试以及十六进制与十进制转换等顺序结构编程训练还包含方波输出等典型实验任务可帮助读者掌握单片机实验箱操作、汇编程序编写与调试排错思路。目前已有338人学习下载适合作为课程配套实验与自学练习的参考材料。1. 六个实验拆开看这份 8051 实验指导书到底能跑通什么手上这份《嵌入式系统实验指导书6 个实验》不是那种只给目录不给细节的课程大纲它把每个实验的目的、设备、原理、内容、步骤、报告格式全写死了连 Keil C51 里点哪个菜单、存储器窗口敲d:30H还是i:30H都标了出来。整套东西围绕一块 8051 实验箱展开六个实验从汇编入门一路推到 A/D 转换加数码管显示覆盖了 Keil C51 工程建立、十六进制转十进制、8 段 LED 动态扫描、4×4 矩阵键盘、ADC0809 采样这几块嵌入式入门最常被考到的硬骨头。适合谁正在带单片机实验课、需要一份能直接照着搭环境的助教或者自学 8051 想找一条从点灯到键盘加显示的完整链路的人。它最大的价值不是理论多深而是把“实验箱型号、8255 地址、字形码表、键值表”这些容易卡住新手的硬参数全摊开了照着敲就能出结果。2. 把 Keil C51 工程跑起来从建工程到 P1.0 出方波2.1 工程参数为什么必须锁死 12MHz 和 89C51第一个实验看着简单就是 P1.0 输出 1Hz 方波但它把后面五个实验的地基全打了。建工程时选 Atmel 的 89C51晶振频率填 12MHzOutput 页勾上生成 HEX这三步一个都不能错。晶振频率不是随便填的它直接决定 Keil 软件仿真时的时间基准也决定你后面写软件延时循环时每条指令折算多少微秒。12MHz 下 8051 的机器周期是 1μs标准 12T 模式一条 DJNZ 是 2 个机器周期即 2μs实验里那段MOV R2,#250 / DJNZ R2,$内层循环就是 250×2500μs三层嵌套凑出 0.5 秒这个账必须自己会算否则换个晶振程序时序全乱。工程建好后新建源文件存成test.asm注意扩展名是 asm 不是 a51虽然 Keil 都认但指导书统一用 asm后面 Add Files to Group 时按这个找。源文件里第一行必须是ORG 0000H这是复位入口六个实验全一样漏了这条链接能过但跑起来行为不可预期属于典型的“编译绿灯、上板翻车”。2.2 方波程序逐行拆解与编译产物ORG 0000H AGAIN: CPL P1.0 ; 取反 P1.0方波高低电平各半周期 MOV R0,#10 ; 外层计数 10 次 LOOP1: MOV R1,#100 ; 中层 100 次 LOOP2: MOV R2,#250 ; 内层 250 次 DJNZ R2,$ ; 内层自减到 0约 500us DJNZ R1,LOOP2 ; 中层循环约 50ms DJNZ R0,LOOP1 ; 外层循环约 0.5s SJMP AGAIN ; 回到取反形成 1Hz 方波 END这段的核心是三层延时嵌套。DJNZ R2,$里的$表示当前指令地址等价于原地跳转R2 从 250 减到 0 共 250 次每次 2μs得 500μsR1 循环 100 次得 50msR0 循环 10 次得 0.5s。CPL 取反一次耗时 1μs 可忽略所以高低电平各 0.5s整周期 1Hz。参数想改频率就动 R0/R1/R2 三个初值但注意 8051 的 R 寄存器只有 8 位最大 255想要更长延时只能再加一层或者换 16 位计数。编译走 Project→Build target产物里 OBJ 是目标文件、LST 是带地址的列表文件、HEX 是烧录或仿真用的十六进制文件。LST 文件值得养成看的习惯它把每条指令的机器码和地址列出来程序跑飞时对着 LST 查 PC 落在哪条指令上比盲猜快得多。编译报错会打在 Output 窗口双击错误行能跳到源码对应位置改完存盘重新 Build 即可。2.3 软件仿真和硬件仿真的切换点Debug→Start/Stop Debug Session 进的是软件仿真不接实验箱也能跑适合验证纯逻辑。但第一个实验的方波要观察 P1.0 电平变化软件仿真里得开 Peripherals→I/O Ports→Port 1 窗口看位状态或者用 Logic Analyzer 加 P1.0 信号。真正上板要切到硬件仿真Project→Options for Target→Debug 页选实验箱对应的驱动串口线接好、通电、拨位开关 K10 打到 B 端再把 P1.0 接 L00、P1.1 接 L01这样端口电平才能驱动 LED 看到闪烁。这里有个反复被强调的细节进硬件连接前先按一次单片机复位键 SS10退出时也按一次。原因是实验箱的仿真串口和单片机复位状态有耦合不复位直接连偶尔会出现端口初始态不对、程序像没跑一样。血泪经验是凡是“下载成功但灯不亮”先按 SS10 再连一遍八成能好。3. 十六进制转十进制与 8 段 LED 动态扫描两个实验的衔接3.1 除以权值法的寄存器分配第二个实验把片内 RAM 30H 里的两位十六进制数转成三位十进制按高位到低位放进 31H33H存成非压缩 BCD。原理是除以权值先除 100 得百位商余数再除 10 得十位商最后的余数就是个位。8051 没有除法指令直接给余数得用 DIV ABA 放被除数、B 放除数执行后 A 是商、B 是余数正好一次拿到两个值。MOV A,30H ; 取待转换的十六进制数 MOV B,#100 ; 除权值 100 DIV AB ; A百位商, B余数 MOV 31H,A ; 存百位 MOV A,B ; 余数转去继续除 MOV B,#10 ; 除权值 10 DIV AB ; A十位商, B个位余数 MOV 32H,A ; 存十位 MOV 33H,B ; 存个位 SJMP $ ; 原地停住方便观察这段要在单步模式下跑View→Memory Window 调出存储器窗口地址栏敲d:30H看片内 RAM 低 128 字节敲i:30H看间接寻址区敲x:xxxxH看片外 RAM。改 30H 的值用右键 Modify Memory at连续多个单元用逗号隔开。断点用 Debug→Insert/Remove BreakpointStep 是纯单步会进子程序Step Over 把子程序调用当一条指令过调显示子程序时用 Step Over 更省事。3.2 8255 三个口的分工与字形码表第三个实验是重头6 位 8 段 LED 动态显示。硬件上 8255 的 A 口做位驱动、B 口做段驱动A/B/C/控制口地址分别是片外 RAM 的 4000H/4001H/4002H/4003H。段码低电平点亮位码也是低电平选中这个极性搞反了就是全亮或全灭。字形码表按 0F、0.F.、-、灭的顺序排比如 0 是 C0H、1 是 F9H、灭是 FFH这张表必须原样抄进程序自己推容易在带小数点的字形上翻车。动态扫描的本质是“骗眼睛”每次只点亮一位延时 0.5ms 后关掉再换下一位六位轮一遍 3ms刷新率 333Hz远高于人眼 50Hz 的闪烁阈值看起来就是六位同时亮。显示子程序入口约定待显示数放 20H25H对应左起第 1第 6 位出口是每位亮 0.5ms 后返回占用 R0、R1、R2、A、PSW、DPTR。DISP: MOV R0,#20H ; 显示数缓冲区首址 MOV R2,#0FEH ; 位码初值左起第一位低电平 MOV DPTR,#SEGTAB; 字形码表首址 DLOOP: MOV A,R0 ; 取当前位待显示数 MOVC A,ADPTR ; 查字形码 MOV DPTR,#4001H ; B 口段驱动 MOVX DPTR,A ; 送段码 MOV A,R2 ; 取位码 MOV DPTR,#4000H ; A 口位驱动 MOVX DPTR,A ; 送位码选中当前位 LCALL DELAY05 ; 延时 0.5ms MOV A,#0FFH ; 关全部位防拖影 MOVX DPTR,A MOV A,R2 RL A ; 位码左移换下一位 MOV R2,A INC R0 ; 缓冲区指针加一 CJNE R0,#26H,DLOOP ; 六位没扫完继续 RET关键在MOVX而不是MOV8255 挂在片外总线必须用外部数据传送指令。位码初值 FEH 是 11111110最低位为 0 选中第一位每轮 RL 左移让 0 往高位走。延时 0.5ms 用 R1 做计数器注意这个 R1 不能和主程序里的循环计数冲突指导书专门提醒“使用的计数单元与显示子程序中用到的不能冲突”这是新手最常见的隐形 bug显示正常但主程序节奏全乱查半天发现寄存器被覆盖。3.3 主程序初始化与流水显示子程序自己跑不起来得配主程序。主程序先对 8255 初始化控制字写 4003HA 口 B 口方式 0 输出、C 口任意控制字 80H 就够C 口不参与显示时。然后设堆栈 SP 到 6FH往 20H25H 填 00H0FH 调显示应看到 0F填 10H1FH 看到 0.F.填 20H、21H 看到“-、灭”。流水显示那段是每约 1 秒把 20H25H 整体左移一位、25H 加一后与 0FH 相与形成 0F 循环左移的动画调用显示子程序 330 次凑 1 秒用双重循环实现且计数单元避开显示子程序占用的 R0/R1/R2。上板前记得把 P0.0P0.7 与 JD0JD7 用排线连起来开关 KC 打到上方这两步漏了显示器就是全灭很多人以为是程序错其实是线没接。4. 矩阵键盘扫描与 ADC0809 采样中断式查询和键值映射4.1 4×4 键盘的行列扫描与消抖第四个实验的键盘接在 8255 的 PC0PC34 行和 PC4PC74 列所以 8255 控制字要改成 C 口高 4 位输出、低 4 位输入即 10000001B 也就是 81H。扫描逻辑是逐列输出低电平、其余列高读行输入某行变低说明该列该行交叉点的键被按下。键值表按图 4-1 排第一行 00H03H、第二行 04H07H 依此类推。消抖是必须的读到行状态有低电平后延时 20ms 再读一次两次一致才认否则机械抖动会让一次按键被识别成多次。松手检测是反复读行状态直到低 4 位全为 1注意高 4 位是无用且不定的必须用ANL A,#0FH滤掉不然永远等不到“全 1”。KEY: MOV R2,#0FEH ; 列驱动码第一列低 KSCAN: MOV DPTR,#4002H ; C 口 MOV A,R2 MOVX DPTR,A ; 输出列驱动码 MOVX A,DPTR ; 读回行状态 ANL A,#0F0H ; 只看高 4 位行输入 CJNE A,#0F0H,KFOUND ; 有行变低则找到按键 MOV A,R2 RL A ; 换下一列 MOV R2,A CJNE A,#0EFH,KSCAN ; 四列没扫完继续0EFH 为第四列 MOV A,#0FFH ; 无键返回 FFH RET KFOUND: LCALL DELAY20 ; 延时 20ms 消抖 MOVX A,DPTR ANL A,#0F0H CJNE A,#0F0H,KCONFIRM SJMP KEY ; 二次不一致重扫 KCONFIRM: ; 此处合并列驱动码与行状态调查键值子程序查键值子程序 KEY20 的入口约定是 A 高 4 位为列驱动码、低 4 位为行状态出口 A 为键值。它先数高 4 位里 0 在第几位算列号再数低 4 位里 0 在第几位算行号列号乘 4 加行号得索引查 KEYTAB 表出键值。KEYTAB 的内容是0FH,0BH,07H,03H / 0EH,0AH,06H,02H / 0DH,09H,05H,01H / 0CH,08H,04H,00H这张表和硬件接线强绑定换实验箱就得重排。主程序把键盘扫描和显示子程序串起来初始化 8255 后循环调 DISP 和 KEYKEY 返回非 FFH 就把 20H24H 依次挪到 21H25H、新键值放 25H效果是每按一键从右端移入一个数字。这里 DISP 用的是实验 3 的子程序所以两个实验的代码要合到一个 asm 文件里寄存器占用得统一规划否则又是覆盖问题。4.2 ADC0809 的启动、查询与显示拼接第五个实验把电位器 W1 分压出的 05V 送 ADC0809 的 IN4启动转换是往 8004H 写任意数取结果是读 8004HEOC 经反相器接到 P1.0所以查询逻辑是等 P1.0 变低表示转换结束反相后极性翻转这点极易搞错直接查 EOC 原极性会死等。MOV DPTR,#8004H MOVX DPTR,A ; 写任意数启动 A/D WAIT: JB P1.0,WAIT ; EOC 反相后接 P1.0变低才结束 MOVX A,DPTR ; 读转换结果8 位数字量 MOV 30H,A ; 转存复用实验 2 的转换程序 LCALL HEX2DEC ; 调十六进制转十进制结果在 31H~33H ; 再把 31H~33H 搬到 23H~25H调 DISP 显示在第四~六位显示位置是第四到第六位对应 20H25H 里的 23H、24H、25H前三位可以填灭FFH 对应字形码或留空。这样整个链路就通了模拟电压→ADC0809→8 位数字量→除以权值转 BCD→动态扫描显示。调试时先用软件仿真确认 HEX2DEC 结果对再上板看显示分两段排查比一锅端快。5. 避坑与排查六个实验里最容易翻车的五处5.1 编译通过但上板无反应现象是 Build 零错误、下载也提示成功LED 或数码管毫无动静。原因多半是没按 SS10 复位就进硬件连接或者拨位开关 K10 没打到 B 端、P0 与 JD 的排线没插。解决顺序固定为断电→按 SS10→检查 K10 和排线→上电→重新进 Debug。这套动作我后来做成 checklist每次上板前过一遍能省掉大半“程序是不是写错了”的自我怀疑。5.2 数码管显示拖影或某位常亮现象是数字边缘发虚、或者某一位始终亮着不灭。原因是动态扫描里关显示那步漏了或者位码左移后没及时把上一位关掉。解决是在每位延时结束后先往 A 口写 FFH 关全部位再移下一位另外检查 0.5ms 延时是否被主程序拉长延时过长会让刷新率掉到 50Hz 以下肉眼就能看到闪烁。5.3 键盘按一下出好几个数现象是一次按键在显示器上移入多个相同数字。原因是消抖没做或 20ms 延时太短也可能是松手检测没滤高 4 位导致提前退出。解决是把二次读行状态比对补上松手循环里加ANL A,#0F0H只判高 4 位确认全 1 才返回。另外检查 20ms 延时用的寄存器有没有和显示子程序撞车。5.4 十六进制转十进制结果错位现象是 30H 放 64H十进制 100却显示成 010 或 001。原因是 DIV AB 后没及时把余数从 B 挪到 A 再除第二次或者存 31H33H 的顺序反了。解决是严格按“商存高位、余数转下轮”的顺序写单步跑一遍看 31H/32H/33H 三个单元的值和手算对一遍再继续。5.5 ADC 查询死等不返回现象是程序卡在JB P1.0,WAIT出不来。原因是 EOC 经反相器后极性变了等错了电平或者启动转换的写地址不是 8004H。解决是先确认硬件上 EOC 到 P1.0 中间有没有反相器有就等低电平没有就等低到高再判启动地址对着原理图核一遍写错地址转换根本没启动EOC 永远不变。6. 把六个实验串成一条验证链从单步到整机联调六个实验单独跑通只是及格线真正有价值的是把它们串成一条链做整机验证。我的习惯是从实验 5 倒着往回验先确认 ADC 采样值随电位器线性变化再把 HEX2DEC 的输出接到 DISP 上看第四到第六位数字跟着变然后加键盘按不同键切换显示内容最后回到实验 1 的方波确认基础时序没被后续代码破坏。这条链上任何一环断问题范围立刻缩小到相邻两个模块之间比六个实验各调各的效率高得多。具体做法是建一个总工程把 DISP、KEY、HEX2DEC、ADC 采样四个子程序放同一个 asm 文件主程序用状态机轮询无键按下时持续采样显示有键按下时把键值作为显示偏移或模式切换。寄存器分配提前画一张表R0R2 归显示、R3R5 归键盘、R6R7 归转换谁都不越界这样就不会再出现“显示正常但键盘失灵”的覆盖问题。延时子程序统一成一个入口、参数走 R7避免每个模块各写一套延时导致时序对不上。验证环节观察点通过标准ADC 采样31H33H 随 W1 变化0V 对应 0005V 对应 255 附近进制转换30H 与 31H33H 对应手算 BCD 一致动态显示六位数码管亮度均匀无闪烁、无拖影键盘扫描每次按键移入一个数无重复、无漏键整机联调按键切换显示模式采样与显示同步更新还有一条容易被忽略的每次改完程序必须先退出硬件连接、重新 Build、再重新连接才生效。指导书在实验 2 和实验 3 的重要提示里都写了这句但新手往往改完直接点运行看到结果没变就以为代码错了其实是旧 HEX 还在跑。从那以后我每次改完代码都强制走一遍“退出连接→Build→复位→重连”的固定动作再没在这上面浪费过时间。希望这套拆法帮到你少走几个我已经踩过的坑。本文还有配套的精品资源点击获取