3、AT24Cxx系列芯片选型:AT24C01/02/04/08/16区别,容量计算,页写入与字节写入
好,咱们进入正题。这一节聊的是AT24Cxx系列,这是美容仪里最常用的EEPROM,没有之一。我最早接触它是在做一款射频仪的时候,当时为了存用户的使用次数和能量档位,选了半天,最后还是老老实实用了AT24C02。为什么?便宜、稳定、资料多,你想想看,做产品最怕什么?最怕芯片断供或者踩坑,而AT24C系列几乎不会给你这种“惊喜”。
3.1 型号与容量:别被数字骗了
AT24C01、02、04、08、16,这几个型号看着像升级打怪,其实核心区别就一个——容量。我直接给你个表,一目了然:
| 型号 | 容量(bit) | 容量(Byte) | 页大小(Byte) | 器件地址位数 |
|---|---|---|---|---|
| AT24C01 | 1K | 128 | 8 | 1 |
| AT24C02 | 2K | 256 | 8 | 1 |
| AT24C04 | 4K | 512 | 16 | 2 |
| AT24C08 | 8K | 1024 | 16 | 3 |
| AT24C16 | 16K | 2048 | 16 | 4 |
注意看,型号里的数字是“Kbit”,不是“KByte”。AT24C02是2Kbit,换算成字节就是256字节。我见过有新手直接当256K用,结果存数据存到一半就写不进去了,还以为是芯片坏了。嗯,这里要注意,容量计算一定要除以8。
3.2 器件地址与I2C从机地址
AT24C系列走的是I2C协议,每个芯片都有一个7位从机地址。地址怎么来的?高4位固定是1010,低3位由硬件引脚A0、A1、A2决定。
但有个坑——容量不同,可用的地址引脚数量也不同。
- AT24C01/02:A0、A1、A2全可用,最多挂8个芯片。
- AT24C04:A0、A1可用,A2被内部用作页地址选择。最多挂4个。
- AT24C08:只有A0可用,A1、A2被内部占用。最多挂2个。
- AT24C16:A0、A1、A2全部被内部用作页地址,只能挂1个。
我曾经在一个项目里,为了省IO口,把AT24C16的A0、A1、A2全接地,结果发现怎么都读不到数据。查了半天手册才反应过来——地址引脚被内部占用了,你接地也没用,它内部已经用这些位来区分不同的页了。
3.3 页写入 vs 字节写入
这是面试常考题,也是实际开发中容易出性能瓶颈的地方。
字节写入:一次写1个字节,发完地址和数据后,等芯片内部写完成(tWR,一般5ms左右)。如果你要写100个字节,就得等100次5ms,总共500ms。这在美容仪里是致命的——用户按一下按键,你让人家等半秒?体验太差了。
页写入:一次写一页。AT24C01/02每页8字节,AT24C04/08/16每页16字节。你可以在一次I2C传输中连续写入一页的数据,芯片内部会一次性完成擦写。还是100个字节,用页写入只需要等7次(100/16≈7次),每次5ms,总共35ms。快了十几倍。
我个人的习惯是:只要数据量超过2个字节,一律用页写入。但要注意一个细节——页写入不能跨页。什么意思?比如AT24C02,页0的地址范围是0x00~0x07,页1是0x08~0x0F。如果你从0x07开始写3个字节,写到0x08时,芯片会自动“卷回”到页0的开头,把0x00、0x01给覆盖掉。嗯,这个坑我踩过,当时校准数据莫名其妙丢失,查了两天才发现是跨页写入导致的。
3.4 代码示例:页写入实现
给你一个我常用的页写入函数,基于STM32 HAL库,但逻辑是通用的:
// 向AT24Cxx写入多字节(自动处理页边界)
HAL_StatusTypeDef AT24Cxx_Write_Page(uint16_t addr, uint8_t *data, uint16_t len)
{
uint16_t page_size = 16; // AT24C04/08/16用16,AT24C01/02用8
uint16_t bytes_written = 0;
while (bytes_written < len)
{
// 计算当前页剩余空间
uint16_t page_offset = addr % page_size;
uint16_t bytes_this_page = page_size - page_offset;
if (bytes_this_page > (len - bytes_written))
bytes_this_page = len - bytes_written;
// 启动I2C写入
if (HAL_I2C_Mem_Write(&hi2c1, AT24CXX_ADDR, addr,
I2C_MEMADD_SIZE_8BIT,
data + bytes_written,
bytes_this_page, 100) != HAL_OK)
return HAL_ERROR;
// 等待内部写完成(轮询ACK)
HAL_Delay(5); // 至少等5ms
addr += bytes_this_page;
bytes_written += bytes_this_page;
}
return HAL_OK;
}
你看,核心就是那个page_offset的计算。每次写入前先算一下当前地址离页边界还有多远,然后只写这么多,保证不跨页。剩下的下一轮循环再处理。
3.5 选型建议:美容仪场景下怎么选?
说实话,AT24C02是我用得最多的。256字节,存个设备序列号、校准参数、用户使用次数、最后关机时间,绰绰有余。而且价格便宜,大概几毛钱一片。
但如果你要做多档位、多探头的美容仪,比如每个探头要存独立的校准曲线,那AT24C16会更合适。2K字节,够你存几十组参数了。
我个人不建议在美容仪上用AT24C01,128字节太局促了。你想想看,一个浮点数就占4字节,存几个校准系数就满了,后续想加功能都没空间。
小项目用02,大项目用16。
04和08是过渡,除非库存清不掉。
页写入要牢记,跨页写入是大忌。
好了,这一节就聊到这儿。下一节咱们实战——怎么用逻辑分析仪抓I2C波形,看看EEPROM到底有没有正常工作。到时候我会分享一个我当年排查“写进去读出来全是0xFF”的经典案例,保证让你少走弯路。