
计算机组成与体系结构Ⅰ的实验做到第 4 个存储器原理实验基本是很多人第一次真正用手理解三组总线的地方。前面几个实验多半是组合逻辑、时序逻辑的复现芯片给好、连线画好照着接就行到了存储器原理这一关画风就变了——给你一片 SRAM、一片 EEPROM地址译码要自己搭片选和读写脉冲要自己发最后还得让某个地址单元里稳稳地存住一个字节断电再上电读回来还是它。这门课里讲了一学期的地址总线、数据总线、控制总线到这一刻才算落地。这个实验的受众其实挺明确刚学完存储器章节、需要交实验报告的学生准备做存储器扩展或者接口设计的人以及想真正搞明白 EEPROM 存储器存储原理到底怎么实现、为什么断电还能留住数据的人。它解决的问题不复杂但很关键——把你脑子里存进去、读出来这句轻飘飘的话拆成地址建立、片选有效、写脉冲宽度、数据保持时间这一串实打实的信号一旦有哪一步时序对不上读出来的就是 0xFF、0x00 或者随机跳变的垃圾值。下面我就按自己做这个实验的顺序把设计思路、原理细节、接线实操和踩过的坑全部拆开讲一遍参数以常见型号的数据手册为准你手上具体是哪个型号最后一定要拿手册再核一遍。1. 实验整体设计与思路拆解1.1 为什么先看存储元再看存储芯片很多人一上手就直奔接线结果接完能读能写就交报告知其然不知其所以然。我的建议是反过来先把存储单元级别的原理理一遍再往上看芯片。原因是SRAM、DRAM、EEPROM 三种东西在芯片接口这一层长得几乎一样——都有地址线、数据线、片选、读/写控制你在实验箱上看到的引脚功能表也大同小异真正的差别全部藏在存储元里面。静态存储元是六个 MOS 管构成的雙稳态触发器两对反相器首尾相连A 点为 1 则 B 点必为 0只要不断电这个状态就一直锁在那儿所以叫静态。DRAM 就抠门多了一个电容加一个管子信息以电荷形式储存在电容上电容会漏电必须每隔几毫秒刷新一遍这就是动态的由来。EEPROM 又是另一条路靠浮栅晶体管里困住的电荷改变阈值电压电荷被二氧化硅包围没有外部高压几乎跑不掉所以断电也不丢。三种存储元对应三种使用姿势SRAM 快、贵、容量小做缓存DRAM 便宜、密度高、要刷新做主存EEPROM 慢、可改写、非易失做配置参数存储。实验里同时给你 SRAM 和 EEPROM就是让你亲手体会这个分界线。从实验设计者的角度想也合理如果只做 SRAM掉电就丢你很难直观感受到非易失这个词的分量如果只做 EEPROM写入慢、时序复杂会掩盖掉地址译码、片选逻辑这些更基础的知识点。两种一起上对比感立刻就出来了。所以第一节实验课我一般会留二十分钟只做一件事——把三种存储元的等效电路画在草稿纸上标注电荷或者电流的流向画完再接线下手后面排查问题时会省下大量时间。1.2 器件选型为什么是 6116 和 AT28C64实验箱和课程设计里最常见的组合是 SRAM 6116 配 EEPROM AT28C64或者再宽一点加一片 62256。选它们不是因为性能好而是因为够典型、够好接、不容易烧。6116 是 2K×8 的静态 RAM11 根地址线、8 根数据线控制信号只有三个CE片选、OE输出使能、WE写使能。控制逻辑非常干净——读的时候 CE 和 OE 有效、WE 无效写的时候 CE 和 WE 有效、OE 无效两者同时有效时绝大多数型号以写优先但你要在实验报告里明确写清楚你的芯片是哪一种行为别想当然。AT28C64 是 8K×8 的并行 EEPROM13 根地址线8 根数据线控制脚同样是 CE、OE、WE接口几乎和 SRAM 一样。这正是它适合教学的原因接口相似但写入行为完全不同会逼着你去查数据手册里的写周期、轮询标志、页写大小。它的单字节写入典型在 1ms 量级最大可能到 10ms写入期间芯片是忙的不给它时间就发下一条数据就废了。为什么不直接选 62256其实 62256 是 32K×8容量大一倍多引脚也兼容到 28 脚做存储器扩展实验更合适。但在基础实验阶段2K 的 6116 有个隐藏优势地址线少用 74LS138 加两个门就能搭出干净的译码不会一上来就被十几根地址线绕晕。选型这件事的逻辑其实是先用最小的复杂度把核心概念讲透再往上加容量你理解了 2K 怎么译码128K 也只是多几级译码而已。注意不同厂家、不同后缀的 6116 在访问时间和控制优先级上可能有差异74LS 系列属于较老的工艺扇出和驱动能力有限实验箱上如果用了总线驱动芯片别绕开它直接接单片机 IO。1.3 顶层数据通路与三个必须想清楚的问题动手前我会先在纸上画一张顶层图只画方块和箭头CPU或者单片机、FPGA引出三组总线地址总线进译码器译码器输出去各个芯片的 CE数据总线并联到所有存储器的数据脚读写控制线并联到所有芯片的 OE 和 WE。这张图很简单但它逼着你回答三个问题。第一个问题地址怎么分配哪片芯片占哪段地址空间谁跟谁重叠。第二个问题数据线能不能并联同一时刻只能有一个芯片驱动数据总线不然两个芯片一个输出 0 一个输出 1就成了电源对地短路芯片发热甚至烧掉这就是为什么片选信号必须互斥。第三个问题谁产生读写脉冲如果是单片机读写脉冲由总线控制器自动产生你只需要接对脚如果是 FPGA读写脉冲得自己在状态机里数时钟周期发出来这时候必须把存储器的时序参数变成时钟周期数。这三个问题想清楚接线就是体力活想不清楚后面一定会在示波器前面耗掉一整晚。我个人习惯是把这三个问题的答案写在实验记录本的第一页排查问题时随时回头对照比反复翻接线图高效得多。2. 存储器核心原理从存储单元到读写时序2.1 静态存储单元的双稳态与地址译码存储矩阵的本质是一个二维阵列。行选和列选交叉交点就是一个存储元行列都有效时那个单元才与数据线连通。假设 2K×8 的片子内部是 128×128 的阵列每个交点 8 位——也就是一个字横向排在 8 个存储元上。地址线一半去行译码一半去列译码这就是为什么大规模存储器内部不做一维译码2048 个单元如果一维译码译码器要 2048 个输出面积和功耗都受不了拆成 64×64 的二维译码只需要两个 6-64 的译码器。在芯片外部你看到的就是一维的 11 根地址线内部怎么切是芯片自己的事。但你至少要理解一件事地址译码的扇出和延迟直接影响到访问时间这就是为什么容量越大、访问越慢也是为什么同样工艺下 SRAM 比 DRAM 快——SRAM 不需要把电荷送出到外部再放大一个双稳态触发器被选中后立刻就能驱动数据线。另一个容易被忽略的点是片内三态总线。所有存储元的输出都挂到内部数据总线上只有被选中的那一个才打开三态门其余的处于高阻。三态门的开关时间也是访问时间的一部分所以在读时序里从地址有效到数据稳定这段延迟 tAA很大一部分消耗在译码器加三态门的链路上。理解这一层你在看时序图时就不会觉得那些参数是凭空冒出来的。2.2 SRAM 读写时序与关键时间参数计算做实验前一定要把时序图上标注的参数翻译成你能验证的量。以常见的 6116 这类 SRAM 为例读周期里几个关键参数是tRC读周期时间最低约 100ns 到 150ns 量级、tAA地址有效到数据有效、tCO片选有效到数据有效、tOE输出使能到数据有效、tHZ片选或输出使能撤销后数据变为高阻的延迟。写周期里则是 tWC写周期时间、tAW/tAS地址建立时间、tWP写脉冲宽度、tDW数据建立时间、tDH数据保持时间。参数怎么变成设计依据举个例子。如果 CPU 侧总线周期是 1μs而 SRAM 的 tAA 是 100ns那时序上是绰绰有余的不需要插等待周期。但如果换成 100MHz 的 FPGA 直接驱动一个时钟周期只有 10nstAA 需要 10 个周期那就必须做多周期访问。这就是慢速存储器配快速控制器的经典矛盾解决办法有两个加等待周期或者用状态机把访问拉长到固定的若干个时钟周期。我用得最多的做法是状态机固定节拍。假设时钟 50MHz周期 20ns那么地址在第一个周期的下降沿有效片选在第二个周期拉低写脉冲保持 2 个周期也就是 40ns——如果手册要求 tWP 不小于 30ns这 40ns 就是可接受的余量。地址、片选、写脉冲的相对顺序也不能乱地址必须在片选和写脉冲之前稳定撤的时候反过来写脉冲先撤、片选后撤最后地址撤。只要顺序错了就可能在一个错误的地址上写进一个垃圾数据。下面这段 Verilog 是我常用的最小写控制器骨架把片选和写脉冲的先后关系固定死module mem_ctrl( input wire clk, // 50MHz input wire rst_n, input wire wr_req, output reg ram_ce_n, output reg ram_oe_n, output reg ram_we_n ); localparam S_IDLE 2d0, S_SETUP 2d1, // 地址/数据建立片选拉低 S_PULSE 2d2, // 写脉冲 S_HOLD 2d3; // 收尾撤销顺序与建立相反 reg [1:0] state; reg [3:0] cnt; always (posedge clk or negedge rst_n) begin if (!rst_n) begin state S_IDLE; cnt 4d0; {ram_ce_n, ram_oe_n, ram_we_n} 3b111; end else begin case (state) S_IDLE: begin {ram_ce_n, ram_oe_n, ram_we_n} 3b111; cnt 4d0; if (wr_req) state S_SETUP; end S_SETUP: begin ram_ce_n 1b0; // 片选先有效 ram_oe_n 1b1; // 写操作OE 保持无效 state S_PULSE; end S_PULSE: begin cnt cnt 1b1; if (cnt 4d0) ram_we_n 1b0; // 写脉冲下拉 else if (cnt 4d3) begin // 保持 80ns ram_we_n 1b1; // 写脉冲先撤销 state S_HOLD; end end S_HOLD: begin ram_ce_n 1b1; // 片选后撤销 state S_IDLE; end endcase end end endmodule这段代码里每个节拍都在做一件事注释写清楚了你才好在示波器上对拍。实测下来把 cnt 的阈值调成 3 对应 80ns 写脉冲宽度绝大多数老型号都稳如果你的芯片手册写 tWP 最小 50ns可以减到 2。记住一个原则写脉冲宁可宽一点不要窄。宽了只是慢几十纳秒窄了就是偶发写入失败这种故障最折磨人因为它十次里可能九次成功。2.3 EEPROM 存储原理浮栅、隧穿与阈值窗口EEPROM 存储器存储原理是这几年被问得最多的一块因为它和 SRAM 的思路完全不一样——它不是锁住一个状态而是往一个绝缘的岛里搬电荷。核心器件叫浮栅 MOSFET在普通 MOS 的控制栅和沟道之间多插了一层多晶硅浮栅四周被二氧化硅包着。这层氧化物是绝缘体正常情况下电荷进去了就出不来这就是非易失的物理基础。写入的时候在控制栅和衬底之间加一个较高的电压典型在十几伏的量级氧化物层里形成很强的电场电子靠隧穿效应穿过氧化层进入浮栅。擦除则反过来把电子从浮栅里抽走。浮栅上有没有电子直接改变管子的开启阈值电压有电子的那一侧阈值高读的时候管子不容易导通读出来是 0没电子的那一侧阈值低读出来是 1。读操作只需要加一个远低于写入电压的读电压靠管子通断判断所以读的速度远快于写。这里有两个非常重要的工程含义。第一写入必须要有足够高的电压笔记本、单片机常用的 5V 供电是写不进去的芯片内部自带电荷泵升压这个升压过程就是写周期慢的原因——1ms 量级的等待时间很大一部分花在泵电压上。第二氧化层反复承受高电场会被逐渐损伤这就是有限擦写次数的来源典型标称 10 万次以上、数据保持 10 年量级。这个指标听着很多但你别在循环里高频写假设每秒写 10 次一天就是 86 万次一天就能把寿命耗尽。Flash 是 EEPROM 的远亲结构上更偏向按块擦除写入前必须先擦掉一整块。而并行 EEPROM 支持按字节擦写用起来更像 RAM这也是教学实验里选它的原因。很多同学第一次用 AT28C64 会问为什么我写一个字节要等 1ms读却只要 100ns答案就在上面——写的慢是电荷泵和隧穿的代价读的快是简单比较的代价。2.4 三类存储器横向对比把关键差异整理成一张表比背定义有用得多对比项SRAMDRAMEEPROM / Flash存储元双稳态触发器1 管 1 电容浮栅晶体管是否易失掉电丢失掉电丢失掉电保持是否需要刷新不需要需要周期性刷新不需要读速度快纳秒级较快需考虑刷新开销快纳秒到百纳秒级写速度与读同级与读同级慢毫秒级需等待完成擦写寿命无限次无限次有限十万次量级单位成本高低中典型用途缓存、小容量高速缓冲主存配置参数、校准数据、固件这张表里最容易踩坑的是最后两行的组合因为 EEPROM 慢很多人用写进去、马上读回来验证的方式判断成功结果读回来的是旧值或者半途值误以为是接线错了。正确做法是等忙标志或者固定延时后再读。SRAM 和 DRAM 那一行的差异在实验中体现得不明显但你做课程设计时如果用了动态存储器接口刷新逻辑不做数据就会自己慢慢烂掉。3. 实操全过程从接线到读写验证3.1 器件清单与上电前检查一次完整的存储器原理实验硬件清单大致如下SRAM 6116 一片并行 EEPROM AT28C64 一片74LS138 译码器一片74LS32 或者 74LS00 做片选组合单片机或者 FPGA 最小系统板一块面包板或者实验箱一块杜邦线若干万用表一块示波器一台。别嫌列得啰嗦我见过太多次因为少一片门电路硬用两根地址线凑片选结果地址镜像导致调试思路完全跑偏的。上电前的检查我固定做三件事。第一用万用表蜂鸣档挨个测电源脚和地脚确认没有短路特别是杜邦线插孔里卡住的细铜丝肉眼看不见但真的会短路。第二检查每片芯片的电源脚旁边有没有 0.1μF 的陶瓷去耦电容没有就补上这个电容能吸收掉开关瞬间的电源尖峰缺了它你会看到随机跳变的读取结果然后在软件里查半天冤枉路。第三确认所有芯片的未用输入脚都有确定电平CMOS 输入悬空会有漏电和振荡尤其是 OE、WE 这种控制脚实验箱上通常有上拉电阻自己搭板子就要手动加上拉。注意接插件和面包板都是有接触电阻的几欧姆到几十欧姆都可能地址线数据线如果不小心走了很长的跳线加上没有去耦边沿会出现振铃。这类问题的现象是大部分时候正常、偶尔读错一个位很难查所以走线尽量短、并行靠近。3.2 地址分配与译码电路实现先算地址范围。2K 就是 2048 个单元2048 等于 2 的 11 次方所以 SRAM 需要 A0 到 A10 共 11 根地址线8K 等于 2 的 13 次方EEPROM 需要 A0 到 A12。地址范围的算法很直白起始地址加上容量再减一如果 SRAM 从 0000H 开始那就是 0000H 到 07FFH。接着做译码。用 74LS138 是个省事的办法把高位地址 A13 接 A 输入、A14 接 B、A15 接 C三个使能脚该接的接好那么 Y0 对应 0000H 到 1FFFH 这一段 8K 空间Y1 对应 2000H 到 3FFFH。EEPROM 有 8K直接把 Y1 接到它的 CE地址范围就是 2000H 到 3FFFH干净利落。SRAM 只有 2K如果直接把 Y0 接到 CE那 0000H、0800H、1000H、1800H 四个地址都会选中同一片芯片这就是地址镜像也就是同一块存储单元在四个地址上都能访问。它不会立刻报错但会让你在读数据时产生从 0800H 读出来的值怎么和 0000H 一样的困惑。解决办法是把 A11 和 A12 拉进译码用 74LS32 把 Y0、A11、A12 相或得到的信号只在三个地址位全为 0 时有效这样就只剩 0000H 到 07FFH 这 2K 空间。芯片容量占用地址线片选来源地址范围SRAM 61162K×8A0–A10Y0 与 A11、A12 组合0000H–07FFHEEPROM AT28C648K×8A0–A1274LS138 的 Y12000H–3FFFH这张表建议打印出来贴在实验台边上后面地址对不上时一眼就能看出是不是译码算错了。3.3 手动单步读写先用开关和 LED 打通链路我强烈建议不要一上来就用单片机跑程序先用拨码开关加 LED 做手动单步。原因是自动跑的时候一旦出错你不知道是硬件接错了还是程序逻辑错了两个变量同时存在排查难度翻倍。手动模式只有硬件一个变量出问题一定是线的问题。具体操作是地址开关拨到一个值比如 0055H数据开关拨一个值比如 0x5A按一下写按钮写脉冲可以由按键加一个单稳态电路产生或者直接用实验箱上的脉冲键然后切到读模式把 OE 拉低、WE 拉高观察 LED 显示的数据是不是 0x5A。读对了说明地址译码、片选、读写控制和数据通路整条链路都是通的。这一步有个细节特别值得说写脉冲用按键直接产生是有风险的普通按键抖动会产生几十毫秒的多次脉冲如果按键没有消抖你可能会在同一个地址上写入多次甚至写进抖动产生的错误数据。所以要么用硬件消抖要么用实验箱上专门的单脉冲输出。我早期吃过这个亏写一次读出来是乱的查了两小时才发现是按键抖动后来在报告里专门画了一张带消抖的脉冲电路图。手动模式还要做一件事验证地址空间的边界。在 0000H 和 07FFH 各写一次在 0800H 再读一次如果 0800H 读出的值和 0000H 一样说明你的译码没有把 A11 拉进来地址镜像还在。这个小测试只花你两分钟但能提前暴露译码层次的错误。3.4 MCU/FPGA 批量读写与自动比对手动打通之后再上自动。用经典 51 单片机的话最省事的办法是用xdata指针直接读写外部存储器地址空间由译码硬件自然划分。下面这段代码做的是全片写入加回读比对图案用的是 0x55 和 0xAA 交替的棋盘格而不是全 0 或全 1#include reg51.h #define SRAM_BASE 0x0000 #define EEPROM_BASE 0x2000 /* 用 xdata 指针访问外部存储空间地址由硬件译码决定 */ #define SRAM(addr) (*(unsigned char xdata *)(SRAM_BASE (addr))) #define EEP(addr) (*(unsigned char xdata *)(EEPROM_BASE (addr))) /* 棋盘格图案比全 0/全 1 更容易暴露相邻位之间的串扰 */ unsigned char pattern(unsigned int i) { return (i 1) ? 0xAA : 0x55; } void sram_test(void) { unsigned int i; for (i 0; i 0x800; i) { SRAM(i) pattern(i); } for (i 0; i 0x800; i) { if (SRAM(i) ! pattern(i)) { P1 0x01; /* 出错点亮指示灯或置错误码 */ while (1); } } P1 0x00; } /* AT28C64 单字节写入带忙轮询和超时保护 */ unsigned char eep_write(unsigned int addr, unsigned char dat) { unsigned int timeout 20000; /* 粗略的超时计数1ms 量级 */ EEP(addr) dat; /* I/O7 在写入期间输出的是被写数据的反相写完变为真实值 */ while ((EEP(addr) 0x80) ! (dat 0x80)) { if (--timeout 0) { return 1; /* 超时失败 */ } } return 0; /* 写入成功 */ } void main(void) { unsigned int i; sram_test(); for (i 0; i 0x40; i) { if (eep_write(i, (unsigned char)(0x30 i)) ! 0) { P1 0x02; /* EEPROM 写失败 */ while (1); } } while (1); }这里有两个点必须解释清楚。第一棋盘格比全 0 全 1 敏感得多全 0 的时候即使某根数据线断了、被下拉到地读出来还是 0测试会通过棋盘格让相邻位电平相反一旦有位间短路或者串扰立刻就能看出来。第二忙轮询必须带超时。理论上每次写入都应该在几毫秒内完成但如果你遇到的是写保护脚接错、电压不够、WE 脉冲太窄这类问题轮询会永远卡住程序看起来像死机实际上是在等一个永远不会来的标志。加超时是给自己留一条排查出路。做 EEPROM 全片写入时算一下时间你就会理解页写的价值8K 字节按单字节 1ms 计算总共要 8 秒多而 AT28C64 支持 64 字节的页写128 页每页 8ms 左右总时间降到 1 秒上下。所以我一般先用单字节写验证正确性确认无误后再改用页写提升效率顺便在报告里对比两种方式的耗时。3.5 示波器看时序与数据保持测试数据能读对只是及格线真正能说明你掌握了存储器原理的是能把时序画出来。我的做法是双通道示波器通道一探 CE 或 WE通道二探数据线或者地址线的最高位触发设在写脉冲的下降沿。观察三件事写脉冲宽度是否满足手册最小值地址和数据在写脉冲有效期间是否已经稳定写脉冲撤销后片选是否还保持了必要的保持时间。如果时间允许再测一次读周期的 tAA方法是把触发放在地址变化的那一瞬间观察数据从地址有效到稳定的延迟。你测出来的值通常比手册给出的最大值小因为手册给的是最坏条件这是正常的但你要在报告里说明测试条件室温、标称电压、没有负载电容。这一步做扎实了实验报告的分量完全不一样。数据保持测试更容易做也最有说服力往 EEPROM 里写入一组有规律的图案拔掉电源等半小时再上电读比对结果如果实验安排允许隔夜再读一次。同时可以对比做一次 SRAM 的掉电测试断电三秒再上电读出来的一定是随机值。这一组对比直接回答了为什么需要非易失存储器这个问题比背结论强一百倍。4. 常见问题排查实录4.1 读不出正确数据的四类根因存储器实验的故障现象翻来覆去就那么几种我按出现频率排序。第一类是读出恒定的 0xFF 或 0x00。0xFF 通常意味着数据总线处于高阻状态被上拉电阻拉到了高电平也就是说根本没有芯片在驱动总线——要么片选没拉低要么 OE 没接对要么芯片根本没供电。0x00 则相反可能某根控制线被持续拉低导致芯片一直处于写模式或者数据线对地短路。判断方法很简单用万用表量片选脚的电平在选中状态下应该是低电平。第二类是读出值只有部分位不对而且是固定的那几位。这种几乎可以断定是那几根数据线的问题虚焊、插错孔位、杜邦线内部断了。用万用表的通断档从芯片脚一直量到控制器脚一段一段量。并联的数据线中有一根不通读出来那一位就会一直是 0 或者一直跟随其他信号。第三类是数据跳变、时好时坏。这是最烦的一类根因通常是电源噪声。检查去耦电容有没有装、地线是不是形成了环路、控制线和地址线是不是并排走了很长一段。另外还有一种可能是地址线的建立时间不够控制器太快、存储器太慢读懂时序图必要时插入等待周期。第四类是地址错位。往 0010H 写数据读 0011H 读到同样的值或者读出来的值整体像是从另一个地址搬过来的。这就是地址线接错或者译码逻辑算错逐位核对地址线从 A0 开始一位一位对别跳着查。4.2 写入假成功与 EEPROM 特有问题SRAM 的写入基本不会失败只要时序对。真正容易出问题的是 EEPROM。第一种假成功是写完立刻读读出来的是新值你以为成功了其实芯片还在忙等到下一次访问时就出错了。必须等忙标志或者老老实实延时足够的写周期时间。第二种是写保护。不少 EEPROM 有个写保护脚电平接错了就整个芯片拒绝写入但读操作完全正常你会在读回来还是旧值的时候怀疑人生。查手册确认这个脚的有效电平通常需要拉到无效状态。第三种是页写越界。页写有个隐藏规则一次页写的数据不能跨页边界64 字节的页如果你从页内第 60 个字节开始写 10 个字节它会翻回本页开头覆盖掉前面的内容而不是顺序写到下一页。这个坑非常隐蔽写进去的值看着都在但位置全部错了。我在报告里专门记过这一条做参数存储的时候地址要对齐到页边界或者干脆退化成单字节写。第四种是寿命焦虑的误判。有人测了几次写入以后发现某个字节读出来不对就以为芯片坏了。其实更可能是那颗字节前面的写入没有真正完成后续写入打断了它。EEPROM 的写入不能被中断也不能在忙的时候去读别的地方——虽然很多型号允许读其他位置但为了稳妥我习惯写完等完成再干别的。4.3 常见问题速查表与排查顺序现象最可能的原因快速验证方法处理办法读出恒为 0xFF片选未有效或数据线高阻量 CE 脚电平是否为低检查译码输出、OE 接线读出恒为 0x00芯片被持续选中写模式或数据线对地短路量 WE 电平是否常低检查控制线极性、排查短路固定几位读错对应数据线虚接或断路通断档逐位测量重新插线或补焊数据随机跳变缺少去耦、地环路、边沿振铃示波器看电源纹波补 0.1μF 电容、缩短走线地址读串地址线接错或译码漏项写边界地址并回读核对 A0 起逐位、补全译码同一数据出现在多个地址高位地址未参与译码检查片选逻辑表达式把未用高位拉入译码EEPROM 写完读回旧值写周期未完成检查是否加了忙等待增加轮询或延时EEPROM 完全不写写保护脚电平错误查手册确认保护脚极性改为无效电平页写后数据位置错乱写入跨越页边界检查起始地址是否对齐对齐页边界或改单字节写上电后数据丢失写的是 SRAM 或用错地址段对比两种芯片的地址范围确认写到了非易失器件上排查顺序我建议固定成一条线电源和地、片选、控制信号极性、地址线、数据线、时序。按这个顺序走不要跳大部分问题在前三步就能定位。跳着查最容易出现查到一半突然发现是自己接错了一根线的情况前面的时间全浪费了。5. 存储器扩展与经验收尾5.1 位扩展、字扩展与译码余量基础实验做完往上走一步就是存储器扩展。位扩展指的是用多片同容量芯片拼出更宽的字长两片 2K×8 的 6116 可以拼成 2K×16做法是两片共享全部地址线和片选、读写控制线但数据线不能并联——第一片接低 8 位第二片接高 8 位。这里的关键点是所有控制信号必须并联否则两片的数据不会同时有效你拼出来的 16 位里总有一半是悬空的。字扩展则是拼容量。四片 32K×8 的 62256 可以拼成 128K×8做法是数据线和控制线全部并联地址线的低位也并联只有片选用不同的译码输出区分。比如 A16、A15 经过二级译码产生四个片选分别对应四段 32K 空间。这里很容易犯的错误是地址范围计算错位四片各占 32K第一片 00000H 到 07FFFH第二片 08000H 到 0FFFFH以此类推别凭感觉写。还有一个容易被忽略的工程细节译码器要留余量。如果你用的是 74LS138八个输出只用了两个剩下六个也别浪费将来加个显示缓冲区、加个串口缓存都能用得上。同时注意译码器的输入不能悬空让高位地址完整参与译码从根上杜绝地址镜像。我做过一次 256K 的扩展就是因为漏掉了最高的两根地址线导致高 64K 空间反复映射到低 64K程序里跑得好好的一访问高位地址就莫名其妙地改了别处的数据查了大半天才定位到译码漏项。5.2 几条踩过坑才知道的细节第一个细节是去耦电容不是可选项。我做过一次对比实验同一块板子拆掉所有去耦电容读写一千次里大约会错三到五次而且错的位随机装回去以后一千次全过。这个实验成本很低但说服力极强建议你也做一遍写进报告。第二个细节是上电顺序和复位。上电瞬间控制线的电平是不确定的如果这时候片选和写脉冲同时有效芯片可能会被写入随机数据。我的做法是在控制线上加上拉电阻让默认状态是不选中、不写同时控制器上电后先做一段初始化延时等电源稳定了再开始访问。EEPROM 尤其要注意它会把上电瞬间的错误当成一次真实写入。第三个细节是别用写一次读一次来验证 EEPROM 的可靠性。正确的做法是写入一整片图案断电再上电整片回读比对。单点验证的偶然性太大一次成功不代表时序留了余量只有全片比对才能把边缘情况暴露出来。第四个细节是关于热词的很多人搜 EEPROM 存储器存储原理出来的都是浮栅结构图看完还是不知道实验里为什么要等 1ms。我的理解是这 1ms 的本质是内部电荷泵升压加上隧穿注入需要的时间这两件事都无法通过提高外部时钟频率来加速。你把这个因果关系理解了就再也不会纠结为什么我把时钟调到 100MHz 写入还是慢了。最后说一个报告写作上的体会数据表格比结论更有价值。写入次数、耗时、错误位数、不同图案下的通过率这些实测数据能体现你真的动过手。我在报告里放过一张不同图案的对比表全 0 全 1 通过率 100%棋盘格通过率 99.5%Walker 图案每次移位一位通过率 97%那张表直接指出了我板子上某一根数据线的接触不良也成了整份报告里最有说服力的一页。做实验这件事动手之前先想清楚要测什么比测完之后再想怎么解释效率高得多。