资讯动态

两引脚自供电串行EEPROM:一根数据线同时搞定供电、时钟与通信

发布时间:2026/8/27 23:06:18 来源:尧图企业网站定制
去年做一个小型环境监测节点主控选了颗很便宜的 8 位 MCUIO 口排到最后一个不剩偏偏还得存一组校准系数和节点 ID。板子上已经塞不下多余电源轨也不想为一片存储芯片再拉两根走线。当时翻出一颗样品两引脚自供电串行 EEPROM一根数据线同时干三件事传时钟、传数据、供电。实测完我只有一个感觉这种为 IoT 场景做的小器件真的是把“省”字做到了极致。这篇博文不打算念数据手册就围绕这种两引脚自供电串行 EEPROM讲清楚它的原理是什么、和常见的 I2C/SPI EEPROM 怎么选、软件怎么驱动以及我在真实项目里踩过的坑。适合正在做低功耗、小体积或 IO 紧张的嵌入式产品的朋友参考。1. 为什么 IoT 设备需要一个“两引脚”串行 EEPROM1.1 存储需求的背后设备身份、校准数据与运行状态IoT 终端看着简单其实每个节点身上至少有两类数据不能丢。第一类是出厂后就固定的身份信息比如节点 ID、MAC 地址、传感器校准系数、产品序列号第二类是在运行中需要频繁更新、断电还要保留的运行参数比如累计运行时长、报警阈值、网络配置、固件升级标记。这些数据如果堆在 MCU 的 Flash 里要处理磨损均衡、扇区擦除、掉电保护而且代码和配置混在同一颗芯片里调试和生产都很别扭。外部串行 EEPROM 的价值就是把“数据”从“代码”里独立出来。结构简单驱动成熟寿命长还方便生产预烧录。我在项目里的习惯是程序代码放 MCU Flash关键参数放外部 EEPROM。这样固件升级不会冲掉参数坏板子拆下 EEPROM 还能读数据排查问题。1.2 内部 EEPROM/Flash 并不总是够用说到 EEPROM很多人第一时间想到的是 MCU 内部自带的那一小块。网上搜“stm32 eeprom”“stc32g eeprom”能刷出大量帖子说明这是很多人的入门方案。内部 EEPROM 确实方便不用额外芯片也不用操心总线布线但有几个现实问题。一是容量普遍不大通常只有几 K 字节装个 Bootloader 参数、放两张校准表就紧张了。二是寿命和磨损需要自己管理。内部 EEPROM 标称擦写寿命一般在十万次到百万次级别如果某个地址被频繁写入比如每秒记录一次计数器很快就到上限得自己做磨损均衡代码量一下就上去了。三是有些 MCU 根本没有独立 EEPROM只能用 Flash 模拟。Flash 扇区擦除一次要几十毫秒过程中断电就可能丢数据处理起来很麻烦。在这些场景下外部串行 EEPROM 是个稳定省心的方案选一个合适型号在软件里把它当成一个“掉电不丢的变量区”来用。而在所有外部 EEPROM 里两引脚自供电这种形态是把外部存储的成本压缩到极致的选择。1.3 两引脚方案的存在价值常规 I2C EEPROM 至少需要 SDA、SCL、VCC、GND 四根线SPI EEPROM 更夸张CS、SCK、MOSI、MISO 加上电源和地最少五根线。两引脚自供电串行 EEPROM 整个器件只有数据线SCIO和地VSS两个功能引脚数据线上同时承载时钟、数据和供电。好处非常直接MCU 只占一个 IO 口PCB 上少一组电源走线封装能做得很小。对现在越来越紧凑的传感器模块、穿戴设备、灯控模块来说省一个引脚可能就决定了一块板子要不要换更大封装的 MCU或者能不能把板子整体缩小一圈。对 IoT 行业来说单颗芯片成本差不了几分钱但面积、引脚数量这些系统性成本影响很大。当然它也不是万能的。通信速率不高基本只支持单从设备对数据线的驱动能力和布线长度也有要求。这些限制我会在后面的原理和使用注意事项里详细展开。2. 自供电与单线通信原理一根线如何同时传电和传数据2.1 曼彻斯特编码每个 bit 都是一次心跳要理解“自供电”核心是理解曼彻斯特编码。曼彻斯特编码是一种把时钟和数据合并在一起的编码方式每个 bit 的位周期中间必然发生一次电平跳变。跳变方向代表逻辑 1 还是逻辑 0由协议具体约定但关键是“中间必有跳变”。为什么必须是这个编码因为器件没有 VCC 引脚它的内部电源完全依赖数据线上的电压变化。每来一个脉冲器件内部的充电电路就把能量抽到一颗微小的储能电容里这颗电容再给内部逻辑和存储阵列供电。如果数据线停在某个固定电平不动器件就没有能量来源电容里的电很快就会耗尽芯片直接掉电复位。打个比方这就像心脏给人供血每个 bit 的跳变就是一次心跳。心跳不能停停一小会儿整个“身体”就要关机。曼彻斯特编码保证了不管数据是 0 还是 1每个 bit 都会发生一次跳变所以只要主机在持续发 bit器件就有持续的能量供应。2.2 时序流程充电、起始、数据、停止在 UNI/O 这类单线协议里总线的空闲状态是低电平。主机要开始通信时先把总线拉高保持一段时间让器件内部电容尽可能充电然后拉低再进入正式的曼彻斯特数据位。这个“拉高-拉低”的起始序列既是通信的起始信号也是在给器件做一次“能量预充”。数据位按曼彻斯特编码逐个发送。读操作时主机继续提供时钟脉冲器件在相应的时间窗口里驱动数据线输出主机在窗口中间采样。通信结束时主机让总线回到低电平器件进入低功耗待机。为什么空闲时必须拉低因为拉低既是协议规定的空闲态也能让储能电容在下一个高脉冲到来前处于“准备充电”的低电位状态。如果空闲时保持高电平器件既拿不到能量也无法区分总线上有没有人在说话。所以任何一段通信结束一定要记得把总线拉回低电平。这一点在写软件驱动的时候特别容易忽略。2.3 供电约束与功耗指标两引脚自供电 EEPROM 的读取电流通常在亚毫安到 1 毫安级别写操作因为要驱动存储阵列电流比读操作更高一些。这些电流全部要从数据线上“挤”出来所以它有几个天然限制。一是通信速率不会很高一般标称最高支持 100kHz 左右不适合做高速大数据传输但存配置、存节点 ID 这种低速场景绰绰有余。二是数据线的驱动能力直接决定供电质量。主机 IO 口驱动能力太弱、线径太长、板级寄生电容太大都会让器件拿不到足够能量出现偶发读写失败。三是器件对连续通信的要求比较苛刻。比如写完一个字节后处于内部写周期时主机不能把总线长期停在某个固定电平否则器件内部的电容可能撑不到写周期结束。我自己的经验是数据线布线尽量短器件引脚和连接器之间的走线最好不要超过 3 到 5 厘米。如果非要跨接插件线束就把通信速率降到几十 kHz再实测验证。否则很容易出现“原理图看着没问题板子批量生产后偶尔读写错乱”这种典型问题。3. 选型对比和主流 SPI/I2C EEPROM 放在一起看3.1 三种串行 EEPROM 总线协议横向对比对比维度两引脚自供电UNI/O 类I2C EEPROMSPI EEPROM功能引脚数2SCIO GND4SDA SCL VCC GND5CS SCK MOSI MISO GNDVCC 另算典型速率100kHz 级400kHz / 1MHz20MHz 以上供电方式数据线寄生供电独立 VCC独立 VCC多设备挂接一般 1 对 1支持多设备总线片选扩展驱动复杂度需要自己实现单线时序标准外设/HAL 库标准 SPI 外设适用场景引脚紧张、超小模块通用配置存储高速大批量数据I2C 是嵌入式里最常见的 EEPROM 接口网上搜“i2c读写eeprom代码 verilog”能找到大量教程甚至有不少软核实现。如果 MCU 自带 I2C 外设驱动写起来确实简单。SPI 则胜在速度快适合存启动配置或者需要频繁读写的数据。两引脚方案的优势场景非常聚焦引脚极度紧张、布局空间极小、低功耗低速存储。3.2 从 I2C 转过来要改变哪些习惯如果你已经熟悉 I2C EEPROM比如 AT24C 系列转到两引脚方案后有几点会很不习惯。一是没有硬件外设可用。几乎所有 MCU 都没有 UNI/O 这种外设你得用 GPIO 定时器软件模拟时序或者自己封装一个和硬件平台无关的驱动层。二是没有 ACK 机制。I2C 的从机应答能帮我们快速确认设备在线而单线方案对时序的约定更严格调试时更依赖逻辑分析仪。三是必须重视供电问题。I2C 器件只要 VCC 稳定就能工作两引脚器件则要求通信过程本身提供能量软件时序和硬件驱动能力会直接影响电源稳定性。不过底层的存储抽象是一样的都有写使能都按地址写字节、读字节容量大的型号还支持页写。如果你维护过 I2C 或 SPI 的 EEPROM 驱动迁移过来并不会太难主要工作就是重新实现底层的字节收发。3.3 选型时需要重点看的参数实际选型时我会按这个顺序去核对参数容量先估算要存多少数据再留 20% 余量。两引脚 EEPROM 常见容量在 1Kbit 到 16Kbit 之间存身份信息、校准参数足够想存日志或固件就没戏。工作电压范围要保证和 MCU 的 IO 电平匹配这直接决定能否稳定寄生供电。最大时钟频率评估你的主控能不能满足最小时序RTOS 环境下还要算上关中断的时间。写周期时间典型值一般在 5ms 上下。如果写操作频率低问题不大如果频繁写要评估等待时间是否影响系统响应。工作电流与待机电流电池供电的产品待机电流直接决定休眠功耗这个千万不能漏。温度范围工业级和商用级的差别很大户外节点至少选工业级。特殊功能比如带预烧录 EUI-48 的型号适合做网络设备身份管理后面我会专门展开。4. 软件驱动用 MCU 模拟 UNI/O 协议读写 EEPROM4.1 最小硬件连接与注意事项两引脚方案硬件连接非常简单MCU 一个 GPIO 接 SCIO器件 VSS 和系统共地。GPIO 我建议配置为推挽输出读的时候切换成输入也可以用开漏加外部上拉。通信频率不高的情况下优先用推挽驱动强度有保障速度也更可控。这里有一个常见误区不要在这个引脚上额外挂大电容。很多人习惯在电源引脚旁边加 0.1uF 退耦电容但两引脚器件的数据线本身就是电源输入挂大电容会把数据线上的脉冲滤掉器件反而取不到能量。老老实实按数据手册的建议做别擅自加滤波。另外上电后不要立刻发命令。器件没有 VCC第一次通信前需要主机主动给一串“热身脉冲”让内部储能电容先把电充起来。我在初始化函数里会先让总线保持低电平几十毫秒再连续发几个高/低脉冲然后才开始正常通信流程。4.2 底层发送与接收 bit 的实现下面是一段演示用的 C 代码框架。重点是展示“软件模拟曼彻斯特单线时序”的思路真实的位极性、命令格式、字节序必须对照你手上型号的数据手册调整否则会出现“看起来在跑、数据全是错的”这种坑。// 硬件抽象宏根据你的平台替换 #define UNIO_PIN_HIGH() GPIO_WriteBit(GPIOB, GPIO_Pin_1, 1) #define UNIO_PIN_LOW() GPIO_WriteBit(GPIOB, GPIO_Pin_1, 0) #define UNIO_PIN_SET_IN() // 配置为输入模式 #define UNIO_PIN_SET_OUT() // 配置为推挽输出 #define UNIO_PIN_READ() GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) // 时序参数来自目标器件数据手册先做占位 #define UNIO_TSTH_US 100 // 起始高电平时间 #define UNIO_TSTL_US 10 // 起始低电平时间 #define UNIO_TBIT_US 20 // 单个 bit 位周期 static void delay_us(uint32_t us) { // 使用定时器或空循环实现具体看平台 } static void unio_start(void) { UNIO_PIN_SET_OUT(); UNIO_PIN_HIGH(); delay_us(UNIO_TSTH_US); UNIO_PIN_LOW(); delay_us(UNIO_TSTL_US); } static void unio_send_bit(uint8_t bit) { if (bit) { // 示例逻辑 1 前半高后半低 UNIO_PIN_HIGH(); delay_us(UNIO_TBIT_US / 2); UNIO_PIN_LOW(); delay_us(UNIO_TBIT_US / 2); } else { // 逻辑 0 前半低后半高 UNIO_PIN_LOW(); delay_us(UNIO_TBIT_US / 2); UNIO_PIN_HIGH(); delay_us(UNIO_TBIT_US / 2); } } static void unio_send_byte(uint8_t byte) { for (int i 7; i 0; i--) { unio_s

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价