ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

番外篇:地址、寄存器与译码器——“我写的地址“是怎么变成“选中一个存储单元“

番外篇:地址、寄存器与译码器——“我写的地址“是怎么变成“选中一个存储单元“ 上一篇《从 FreeRTOS 栈高水位一路问到 SRAM 底层》讲完了存储器的大框架但很多读者反馈地址这一块最绕——为什么我写了 0x0001电路里就有一根线变高了十六进制要不要转二进制寄存器到底几位和译码器什么关系这篇把这些问题一个个拆开讲透。〇、先给结论地址的完整旅程你写代码(0x20000005) → 编译成机器码 → 运行时 CPU 把值装进寄存器 → 寄存器每个1位驱动对应地址线为高 → 地址线(电压组合)送进译码器 → 译码器只把对应那一行选通 → (字节编址)读写 1 字节下面把每一站的为什么都讲清楚。一、地址不是一个数字是一组电压CPU 说访问地址 10时硬件里没有10这个数字——只有几根线上的电压4 位地址 4 根线A3 A2 A1 A0 地址 10二进制 1010→ 线高 低 高 低并行是关键n 位地址就是 n 根线同时给出电压高1、低0不存在把数字传过去再解码的过程——电压组合本身就是地址。二、十六进制只是记法硬件里没有转换器很多人问“十六进制地址进来是不是要先转二进制”——不需要因为十六进制只是二进制的缩写写法0xA 1010 1 个十六进制位 4 个二进制位 0x000A 0xA 10 ← 前导 0 不改变值也不占硬件转换发生在你写代码、编译器生成机器码的那一刻是人和编译器做的记法转换电路里从头到尾只有二进制电压。十六进制是给人类看的硬件不认识也不需要认识。三、寄存器 一排存 0/1 的小格子寄存器不是神秘的整体它是一排触发器每个触发器存 1 位。STM32 的寄存器 32 个格子格子号31 30 … 2 1 0 存的值0 0 … 1 0 1 ← 寄存器存了一个数就是这个意思 输出线低 低 … 高 低 高 ← 存 1 的格子输出线天然是高关键直觉“存了 1这个物理状态就是让那根输出线保持高电平像开关拨到开”灯自然亮——不是谁去拉高它。所以寄存器给译码器地址准确说是值里为 1 的位它们各自的输出线是高电平其余是低。寄存器是几位由 CPU 架构决定STM32 32 位跟你写了几个十六进制位、地址是多少无关。写 0x0000 就是往 32 位寄存器里存 032 根线全低同一个寄存器永远 32 位。四、一个格子的核心两个反相器首尾相连存 1 位的格子内部核心是两个反相器交叉耦合形成的双稳态┌──►[反相器A]──►──────┐ │ ▼ │ [反相器B] └────────◄────────────┘反馈让它自己锁自己Q1 → /Q0 → Q 保持 1正反馈只有两个稳定状态Q1//Q0 或 Q0//Q1所以叫双稳态想写 1用强信号掰一下锁存器松手后自己维持这个电路 SRAM 6 管单元的核心 寄存器每一位的核心——整个存储世界的地基是同一个东西。寄存器的一位D 触发器只是在这个核心外面加了一层时钟门只在时钟边沿允许改写其它时间死死锁住。五、译码器与门接哪两条线就是给谁编址译码器把 n 位地址翻译成 2^n 条选择线同一时刻只有一条有效。做法每个输出对应一个与门与门的输入从正相轨 / 反相轨里各取一条与门输入1 接输入2 接响应的地址门 0/A1 轨/A0 轨00门 1/A1 轨A0 轨01门 2A1 轨/A0 轨10门 3A1 轨A0 轨11接正相 这一位要求是 1接反相 要求是 0。所以接线就是编址——每个地址组合恰好只有一个与门全票通过输出 1。地址 10 来时只有门 2 两个输入都是 1。六、n 位 → 2n同一个2n出现三次位置为什么是 2^nn 位寄存器能表示 2^n 种不同值但某时刻只处于其中一种译码器要区分 2^n 种组合 → 2^n 个与门存储阵列所以有 2^n 个可寻址位置寄存器宽度、地址线根数、译码器规模、存储位置数量——四者永远是同一套宽度。换算2¹⁰≈1K2¹⁶64K2²⁰1M2³²4G。16 位地址 65536 个位置 经典的64KB 寻址空间51 单片机。七、一个地址 一个字节 8 个 1-bit 单元最容易混的点基本存储单元6T SRAM存 1 bit但地址在字节编址里对应 1 字节。字节编址x8 组织下译码器选中一个地址 选中一排 8 个并排的 bit 单元同时读写 8 位地址 0x0005 → 这一排同时工作 ┌────┬────┬────┬────┬────┬────┬────┬────┐ │bit7│bit6│bit5│bit4│bit3│bit2│bit1│bit0│ 1 字节 └────┴────┴────┴────┴────┴────┴────┴────┘所以 64KB 的存储器 65536 个地址 × 8 位 512Kbit。64K × 8手册写法里的两个数字就是这么来的。数据宽度x8/x16只决定每行并几个单元不改变译码器——64K×8 和 64K×16 的译码器一模一样。八、译码器不管数据译码器 纯定位器只做地址 → 选通对应那一行这一件事。部件负责什么译码器选哪个地址行被激活位线/列选择/数据总线一次搬几位、往哪搬读出放大器把微弱压差放大成标准电平存储单元存内容数据是什么谁都不管酒店类比译码器是前台报房号只负责开那间门房间里装多大行李、装什么前台一概不管。九、全流程串一遍从 C 代码到写入*(uint32_t*)0x200000040x12345678;编译器把这条语句变成机器指令地址作为立即数编码进指令运行时 CPU 执行地址值进入内部路径32 根地址线按值的二进制给出电压地址线 → 总线 → 存储控制器区域/片选→ SRAM 的低位地址线译码器选中 0x20000004 那一个字节位置 8 个 bit 单元数据 0x12345678 分 4 次每地址 1 字节写入 0x20000004 ~ 0x20000007小端下字节顺序040x78、050x56、060x34、070x12。写 4 字节占 [04, 07] 四个地址08 是下一个变量的起点不是 08 结尾。十、常见误区清单都是真实踩过的坑地址是电压组合不是报一个数字十六进制只是记法没有十六进制转二进制的芯片“寄存器拉高” 存 1 的位输出天然高不是被谁拉寄存器位数由 CPU 决定STM3232 位与写法/值无关前导 0 不占硬件0x000A 就是 0xA都是 4 位二进制装得下的值4 位地址 4 根线 一个 4 位值不是 4 个寄存器一个地址 1 字节 8 个 1-bit 单元6T 单元本身只存 1 bit写 4 字节占用起始3 个地址4 是下一个的起点别差一uint16_t 指针一次读 2 字节不是 1 字节译码器只管定位数据宽度和内容不归它管十一、一句话总结地址是 n 根线上的电压组合1 的位线高、0 的位线低→ 这组电压进译码器 → 译码器按与门接线编址只拉高对应那一行 → 字节编址下选中 8 个并排的 1-bit 单元1 字节→ 数据写入。寄存器宽度、地址线、译码器、存储位置始终是同一套n 位 → 2^n。如果这篇解决了你的困惑推荐继续往下挖CPU 怎么知道数据回来了读时序/等待周期、区域译码与片选的分工、Cache 与内存一致性问题。
返回列表