I2C EEPROM示例
源码路径:example/rt_device/i2c/eeprom
支持的平台
例程可以运行在以下开发板.
- em-lb525 
- em-lb587 
概述
- 在RT-Thread操作系统下,通过对EEPROM芯片AT24CO8SC模块的读写操作,演示I2C的使用方法 
例程的使用
硬件连接
AT24CO8SC的VCC,GND分别连接5v和GND供电
AT24CO8SC的SDA,SCK分别按照下表,根据开发板型号进行连接
| 开发板 | SDA管脚 | SDA管脚名称 | SCL管脚 | SCL管脚名称 | 
|---|---|---|---|---|
| em-lb525 | 3 | PA42 | 5 | PA41 | 
| em-lb587 | 3 | PB29 | PB28 | 
- 更详细的引脚定义请参考 
 - [em-lb525]()
 - [em-lb587]()
- AT24C08SC  
编译和烧录
- 此例程中用到了I2C2,在采用RT-Thread操作系统时,I2C2外设会虚拟成了一个rt_device来进行读写操作,此时需要确认工程所在路径下 - rtconfig.h文件中是否包含了下面3个宏:
#define RT_USING_I2C 1
#define BSP_USING_I2C 1
#define BSP_USING_I2C2 1
只有包含了上面三个宏,在rt_hw_i2c_init2函数中才会通过rt_i2c_bus_device_register函数注册"i2c2"这个rt_device,后面该设备才能rt_device_find和rt_device_open成功。
如果缺失上面三个宏,就需要通过menuconfig如下命令进行打开
menuconfig --board=em-lb525
如下图,选择I2C2,保存并退出menuconfig,查看rtconfig.h宏是否生成

SF525工程代码编译
切换到例程project目录,运行scons命令执行编译:
scons --board=em-lb525 -j8
运行build_em-lb525_hcpu\uart_download.bat,按提示选择端口即可进行下载:
build_em-lb525_hcpu\uart_download.bat
Uart Download
please input the serial port num:5
SF587工程代码编译
切换到例程project目录,运行scons命令执行编译:
scons --board=em-lb587 -j8
切换到例程project/build_xx目录,运行download.bat,程序通过JLink自动下载:
build_em-lb587_hcpu\download.bat
例程输出结果展示:
- log输出: 
   SFBL
   Serial:c2,Chip:4,Package:3,Rev:3  Reason:00000000
   \ | /
  - SiFli Corporation
   / | \     build on Dec  6 2024, 2.1.7 build 779fe6ee
   2020 - 2022 Copyright by SiFli team
   mount /dev sucess
   [32m][2009] I/drv.rtc: PSCLR=0x80000100 DivAI=128 DivAF=0 B=256
   [0m][32m][2036] I/drv.rtc: RTC use LXT RTC_CR=00000001
   [0m][32m][2058] I/drv.rtc: Init RTC, wake = 0
   [0m][32m][2220] I/drv.audprc: init 00 ADC_PATH_CFG0 0x606
   [0m][32m][2242] I/drv.audprc: HAL_AUDPRC_Init res 0
   [0m][32m][2264] I/drv.audcodec: HAL_AUDCODEC_Init res 0
   [0m][32m][2286] I/TOUCH: Regist touch screen driver, probe=1203b8b1 
   [0m]call par CFG1(3313)
   fc 9, xtal 2000, pll 2123
   call par CFG1(3313)
   fc 7, xtal 2000, pll 1698
   main!!
   [2448] D/eeprom_i2c: Start i2c eeprom rtt demo!
   i2c_bus:0x20007f50
   Find i2c bus device I2C2
   [2492] D/eeprom_i2c: i2c write reg:0x1,data:0x11,ret:1
   [2681] D/eeprom_i2c: i2c write reg:0x2,data:0x22,ret:1
   [2869] D/eeprom_i2c: i2c write reg:0x3,data:0x33,ret:1
   [3058] D/eeprom_i2c: i2c write reg:0x4,data:0x44,ret:1
   [3248] D/eeprom_i2c: i2c read reg:0x1,pdata:0x11,ret:1
   [3273] D/eeprom_i2c: i2c read reg:0x2,pdata:0x22,ret:1
   [3298] D/eeprom_i2c: i2c read reg:0x3,pdata:0x33,ret:1
   [3323] D/eeprom_i2c: i2c read reg:0x4,pdata:0x44,ret:1
   [3345] D/eeprom_i2c: i2c end!
   msh />
AT24C08SC芯片手册上要求的i2c读写波形
- i2c写的波形 
  
- i2c读的波形 
  
逻辑分析仪抓取部分波形
- i2c写的波形  
- i2c读的波形  
I2C参数修改
- 见EEPROM_init函数内注释 
unsigned char EEPROM_init(void)
{
    uint8_t slaveAddr = EEPROM_I2C_ADDRESS; // 7bit address of device
    HAL_StatusTypeDef ret;
    //1. pin mux
#ifdef SF32LB52X 
    HAL_PIN_Set(PAD_PA41, I2C2_SCL, PIN_PULLUP, 1); // i2c io select
    HAL_PIN_Set(PAD_PA42, I2C2_SDA, PIN_PULLUP, 1);
#elif defined(SF32LB58X)
    HAL_PIN_Set(PAD_PB28, I2C6_SCL, PIN_PULLUP, 1); // i2c io select
    HAL_PIN_Set(PAD_PB29, I2C6_SDA, PIN_PULLUP, 1);
#endif
    // 2. i2c init
    // find i2c2
#ifdef SF32LB52X 
    i2c_bus = rt_i2c_bus_device_find("i2c2");
#elif defined(SF32LB58X)
    i2c_bus = rt_i2c_bus_device_find("i2c6");
#endif
    rt_kprintf("i2c_bus:0x%x\n", i2c_bus);
    if (i2c_bus)
    {
        #ifdef SF32LB52X 
        rt_kprintf("Find i2c bus device I2C2\n");
        #elif defined(SF32LB58X)
        rt_kprintf("Find i2c bus device I2C6\n");
        #endif
        // open rt_device i2c2
        rt_device_open((rt_device_t)i2c_bus, RT_DEVICE_FLAG_RDWR);
        //rt_i2c_open(i2c_bus, RT_DEVICE_FLAG_RDWR);
        struct rt_i2c_configuration configuration =
        {
            .mode = 0,
            .addr = 0,
            .timeout = 500, //Waiting for timeout period (ms)
            .max_hz = 400000, //I2C rate (hz)
        };
        // config I2C parameter
        rt_i2c_configure(i2c_bus, &configuration);
    }
    else
    {
        #ifdef SF32LB52X 
        LOG_E("Can not found i2c bus I2C2, init fail\n");
        #elif defined(SF32LB58X)
        LOG_E("Can not found i2c bus I2C6, init fail\n");
        #endif
        return -1;
    }
    return 0;
}
- 在打开rt_device设备时,如果采用rt_i2c_open函数,功能上没有发现问题,但是 - list_device时- i2c2不会显示open状态,
rt_i2c_open(i2c_bus, RT_DEVICE_FLAG_RDWR);
    msh />
 TX:list_device
    list_device
    device           type         ref count
    -------- -------------------- ----------
    audcodec Sound Device         0       
    audprc   Sound Device         0       
    rtc      RTC                  0       
    pwm3     Miscellaneous Device 0       
    touch    Graphic Device       0       
    lcdlight Character Device     0       
    lcd      Graphic Device       0       
    i2c4     I2C Bus              0       
    i2c2     I2C Bus              0       
    i2c1     I2C Bus              0       
    lptim1   Timer Device         0       
    btim1    Timer Device         0       
    uart1    Character Device     2       
    pin      Miscellaneous Device 0       
    msh />
采用rt_device_open时
rt_device_open((rt_device_t)i2c_bus, RT_DEVICE_FLAG_RDWR);
    msh />
 TX:list_device
    list_device
    device           type         ref count
    -------- -------------------- ----------
    audcodec Sound Device         0       
    audprc   Sound Device         0       
    rtc      RTC                  0       
    pwm3     Miscellaneous Device 0       
    touch    Graphic Device       0       
    lcdlight Character Device     0       
    lcd      Graphic Device       0       
    i2c4     I2C Bus              0       
    i2c2     I2C Bus              1       
    i2c1     I2C Bus              0       
    lptim1   Timer Device         0       
    btim1    Timer Device         0       
    uart1    Character Device     2       
    pin      Miscellaneous Device 0  
- 这里只是演示了I2C的一种用法,在I2C外设要求的波形跟示例不一致时,可以参考rt_i2c_transfer函数的用法。 
注意:
- 除SF32LB55x芯片外,所有PA口都支持HCPU I2C的SDA、SCL功能,所有PB口都支持LCPU I2C的SDA、SCL功能 
- HCPU的PA口不能配置为LCPU的I2C实例使用,LCPU的PB口也不能配置为HCPU的I2C使用, 比如I2C5是LCPU的I2C实例,他的SCL和SDA管脚不能映射到PA口 
- HAL_PIN_Set 最后一个参数为hcpu/lcpu选择, 1:选择hcpu,0:选择lcpu 
异常诊断
- I2C无波形输出 
- pin status 39命令查看对应PA39,PA40的IO状态FUNC对不对,VAL电平应该是1
    msh />
 TX:pin status 39
    pin status 39
    [32m][215653658] I/TEST.GPIO: PIN 39, FUNC=4, VAL=1, DIG_IO_PU, GPIO_MODE_INPUT, irqhdr=/, arg=/
    [0m]
    msh />
    msh />
 TX:pin status 40
    pin status 40
    [32m][215753678] I/TEST.GPIO: PIN 40, FUNC=4, VAL=1, DIG_IO_PU, GPIO_MODE_INPUT, irqhdr=/, arg=/
    [0m]
    msh />
    msh />
- ‘list_device’命令查看’i2c2’设备是不是存在并且打开了 
- 检查IO配置和连接是否正确 
- 连写失败,I2C波形正常,无应答信号 
- AT24C08SC写输入时需要至多5ms Write Cycle Time等待数据烧录 
void EEPROM_test(void)
{
    unsigned char i = 0;
    for ( i = 0; i < 4; i++)
    {
        EEPROM_write_data(TEST_ADDR[i], TEST_DATA[i]);
        delayms(5); //5ms delay for AT240C8SC write time cycle
    }
    for ( i = 0; i < 4; i++)
    {
        EEPROM_read_data(TEST_ADDR[i], &RECEIVED);
    }
}
参考文档
更新记录
| 版本 | 日期 | 发布说明 | 
|---|---|---|
| 0.0.1 | 10/2024 | 初始版本 | 
