STC8H开发(十二): I2C驱动AT24C08,AT24C32系列EEPROM存储

目录

AT24C系列

AT24C系列是常见的EEPROM存储芯片, 常用于保存参数及掉电记忆的数据

  • 容量: 型号代表了其容量, 从AT24C01到AT24C1024, 存储容量为1K BIT ~ 1024K BIT, 注意单位是Bit, 如果转换为字节就是128字节 ~ 128K字节
  • 电压: 整个系列有2.7V (2.7V至5.5V)和1.8V (1.8V至5.5V)两个版本, 都兼容3.3V和5V
  • 封装: 8-lead PDIP, 8-lead JEDEC SOIC, 8-lead MAP, 5-lead SOT23, 8-lead TSSOP 和 8-ball dBGA2

与其他存储器件相比

  • 容量小
  • 皮实, 几近无限的擦写次数: 10万次以上, 典型值为百万
  • 超长的数据保持: 40年以上
  • 工作温度范围: 工业级[-55℃,125℃]
  • I2C总线, 只需要SCL和SDA两个接口, 并且可以和其他I2C设备复用
  • 支持写保护

因为这些特点, AT24C常用于一些容量小但是稳定性要求高, 并且需要反复擦写的场景.

AT24C的设备地址和存储地址

设备地址

AT24C的设备地址都是一个字节, 以二进制1010开头, 通过A0,A1,A2这三个pin进行调整. 根据容量不同, 设备地址和寻址范围有区别

AT24C01 - AT24C16

这个系列的存储地址只有一个字节, 所以内存寻址只有256字节(2048 bit), 对于AT24C01, AT24C02可以直接寻址, 对于更大容量的型号, 需要结合设备地址对内存地址分page访问

  • AT24C01, AT24C02: 设备地址 0xA0 - 0xAE, 第8位是R/W, 同一个I2C总线上可以并存8个同类设备
  • AT24C04: 0xA0 - 0xAC, 第7位是page选择, 第8位是R/W, 同一个I2C总线上可以并存4个同类设备
  • AT24C08: 0XA0 - 0xA8, 第6,7位是page选择, 第8位是R/W, 同一个I2C总线上可以并存2个同类设备
  • AT24C16: 0XA0, 第5, 6,7位是page选择, 第8位是R/W, 同一个I2C总线上只能存在1个同类设备

AT24C32, AT24C64

  • 从这个容量开始, 存储地址变成两个字节
  • 设备地址 0xA0 - 0xAE, 第8位是R/W, 同一个I2C总线上可以并存8个同类设备

AT24C128, AT24C256, AT24C512

  • 设备地址 0xA0 - 0xA6, 第5位固定为0, 第8位是R/W, 同一个I2C总线上可以并存4个同类设备
  • 存储地址两个字节

AT24C1024

  • 设备地址 0xA0 - 0xA4, 第5位固定为0, 第7位是page选择, 第8位是R/W, 同一个I2C总线上可以并存2个同类设备
  • 存储地址两个字节, 所以内存寻址只有64K字节, 128K需要分两个page进行访问

通过STC8H访问AT24C系列存储芯片

注意

访问AT24C时I2C总线的频率不能太高.

  • AT24C系列的I2C总线最高频率是400KHz(2.7V), 在1.8V时频率会降到100KHz
  • 市面上的兼容芯片可能会达不到前面的指标
  • STC8H系列的主频基本上从24MHz起步, 甚至直接运行在36.864MHz上
  • STC8H I2C总线的频率是基于FOSC计算的, 在最初的调试阶段, 务必设置一个较大的预分频, 这样可以确保问题不出在频率过高上

接线

对于DIP8封装, 接线方式都是一样的, 测试使用的是 STC8H3K64S2, 可以直接替换为 STC8H 其它型号, 除了下面的4个pin, 还需要选择将A0, A1, A2 接GND或接VCC

P32   -> SCL
P33   -> SDA
GND   -> GND
3.3V  -> VCC

AT24C08访问示例

这个例子演示了单字节存储地址系列型号的访问方式

#include "fw_hal.h"

// 设置地址 0xA0, 对应A0,A1,A2三个pin都接地, 测试中根据自己的接线修改
#define AT24C_ADDR  0xA0

__CODE int8_t dat[20] = {0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB};

// I2C初始化
void I2C_Init(void)
{
    // 主设备模式
    I2C_SetWorkMode(I2C_WorkMode_Master);
    /**
     * I2C 总线频率 = FOSC / 2 / (__prescaler__ * 2 + 4) 这里设成最大值0x3F
    */
    I2C_SetClockPrescaler(0x3F);
    // 选择I2C端口
    I2C_SetPort(I2C_AlterPort_P32_P33);
    // 启用 I2C
    I2C_SetEnabled(HAL_State_ON);
}

// GPIO初始化
void GPIO_Init(void)
{
    // SDA
    GPIO_P3_SetMode(GPIO_Pin_3, GPIO_Mode_InOut_QBD);
    // SCL
    GPIO_P3_SetMode(GPIO_Pin_2, GPIO_Mode_Output_PP);
}


int main(void)
{
    uint8_t offset, i, buf[20];

    SYS_SetClock();
    // 开启 UART1, baud 115200 with Timer2, 1T mode, no interrupt
    UART1_Config8bitUart(UART1_BaudSource_Timer2, HAL_State_ON, 115200);

    GPIO_Init();
    I2C_Init();
    // 对地址0x00连续写入12个字节
    I2C_Write(AT24C_ADDR, 0x00, dat, 12);

    while(1)
    {
    	// 分4次, 起始地址递增, 每次连续读出6个字节并通过串口输出
        for (offset = 0; offset < 4; offset++)
        {
            I2C_Read(AT24C_ADDR, offset, buf, 6);
            for (i = 0; i < 6; i++)
            {
                UART1_TxHex(buf[i]);
                UART1_TxChar(':');
            }
            UART1_TxString("  ");
            SYS_Delay(10);
        }
        UART1_TxString("\r\n");
        // 间隔1秒
        SYS_Delay(1000);
    }
}

代码地址

AT24C32访问示例

这个例子演示了双字节存储地址系列型号的访问方式

#include "fw_hal.h"

// AT24C device address, change according to the voltage level of A0/A1/A2
#define AT24C_ADDR  0xA0
// Test data
__CODE int8_t dat[20] = {0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB};

void I2C_Init(void)
{
    // Master mode
    I2C_SetWorkMode(I2C_WorkMode_Master);
    /**
     * I2C clock = FOSC / 2 / (__prescaler__ * 2 + 4)
    */
    I2C_SetClockPrescaler(0x3F);
    // Switch alternative port
    I2C_SetPort(I2C_AlterPort_P32_P33);
    // Start I2C
    I2C_SetEnabled(HAL_State_ON);
}

void GPIO_Init(void)
{
    // SDA
    GPIO_P3_SetMode(GPIO_Pin_3, GPIO_Mode_InOut_QBD);
    // SCL
    GPIO_P3_SetMode(GPIO_Pin_2, GPIO_Mode_Output_PP);
}

int main(void)
{
    uint8_t offset, i, buf[20];

    SYS_SetClock();
    // UART1 configuration: baud 115200 with Timer2, 1T mode, no interrupt
    UART1_Config8bitUart(UART1_BaudSource_Timer2, HAL_State_ON, 115200);

    GPIO_Init();
    I2C_Init();
    // 与AT24C08示例的区别在于使用了16bit地址
    I2C_Write16BitAddr(AT24C_ADDR, 0x0000, dat, 12);

    while(1)
    {
        for (offset = 0; offset < 4; offset++)
        {
        	// 与AT24C08示例的区别在于使用了16bit地址
            I2C_Read16BitAddr(AT24C_ADDR, 0x0000|offset, buf, 6);
            for (i = 0; i < 6; i++)
            {
                UART1_TxHex(buf[i]);
                UART1_TxChar(':');
            }
            UART1_TxString("  ");
            SYS_Delay(10);
        }
        UART1_TxString("\r\n");
        SYS_Delay(1000);
    }
}

代码地址

posted on 2022-07-04 05:55  Milton  阅读(1925)  评论(0编辑  收藏  举报

导航