说明:介绍 i2c 通讯接口的eeprom at24cxx 读写测、试代码,代码基于 at24cxx 软件包实现。
使用步骤:
* 1:在 RT-Thread Settings 中开启 【软件模拟I2C】
* 2:在 RT-Thread Settings 软件包中搜索 at24cxx 添加软件包,并保存。
* 3:drivers-> board.h 中打开I2C接口的定义 搜索 I2C CONFIG BEGIN,按介绍定义。
* 4:packages 目录中可以找到添加的软件包,at24cxx.h 中定义 eeprom的型号 ,如 #define EE_TYPE AT24C64
* 软件包提示: 注意事项
* 请在at24cxx.h中修改EE_TYPE为自己使用的型号(默认为AT25C512) 。
* 请在at24cxx.h中修改EE_TWR为自己使用EEPROM的Write Cycle Time,具体值请查看芯片datasheet(默认为5ms) 。
* 从设备地址为7位地址 0x50, 而不是 0xA0 。
1:在 RT-Thread Settings 中开启 【软件模拟I2C】
2:在 RT-Thread Settings 软件包中搜索 at24cxx 添加软件包,添加后并保存。
3:drivers-> board.h 中打开I2C接口的定义 搜索 I2C CONFIG BEGIN,按介绍定义。
4:packages 目录中可以找到添加的软件包,at24cxx.h 中定义 eeprom的型号 ,如 #define EE_TYPE AT24C64
4.1.设置 EEPROM芯片型号,写周期,地址
at24cxx.h 头文件中设置芯片型号,修改写周期(根据芯片手册)
4.2.型号设置好后先编译,编译后对应的 c文件中的相应配置就会打开。
4.3. 芯片地址设置(EEPROM地址一般是 0x50 不含读写标志位及3个IO设置的地址, A0 = A1 = A2 =L 接 GND时地址为0x50;A0 = H, A1 = L, A2 = L 地址为0x51)
5. 测试代码
/* * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 说明:本eeprom 读写测试代码基于 at24cxx 软件包 * 使用步骤: * 1:在 RT-Thread Settings 中开启【软件模拟I2C】 * 2:在 RT-Thread Settings 软件包中搜索 at24cxx 添加软件包,并保存。 * 3:drivers-> board.h 中打开I2C接口的定义搜索 I2C CONFIG BEGIN,按介绍定义。 * 4:packages 目录中可以找到添加的软件包,at24cxx.h 中定义 eeprom的型号 ,如 #define EE_TYPE AT24C64 * * 软件包提示: 注意事项 * 请在at24cxx.h中修改EE_TYPE为自己使用的型号(默认为AT25C512) 。 * 请在at24cxx.h中修改EE_TWR为自己使用EEPROM的Write Cycle Time,具体值请查看芯片datasheet(默认为5ms) 。 * 从设备地址为7位地址 0x50, 而不是 0xA0 。 */#include "user_cfg.h"#define EEPROM_I2C"i2c1" /* eeprom 所挂载的i2c总线 */#define EEP_ADDR 0 /* 从设备芯片地址,IC的A2,A1,A0设置的值 */#define CF_START_ADD 0 /* eeprom 校准系数的首地址 *///#define EEPROM_TEST_CODEstatic at24cxx_device_t eeprom_dev;/*at24cxx 设备对象 *//* eeprom 设备初始化 */void eeprom_init(void){eeprom_dev = at24cxx_init(EEPROM_I2C,EEP_ADDR);if(eeprom_dev == RT_NULL){rt_kprintf(">eeprom 注册失败... \n");}}/* 校准系数保存到 eeprom*/void eeprom_cf_save(void){int8_t temp[CH_NUM*2];for (int8_t var = 0; var >8;temp[var*2+1] = Adc_Channel_CF_Data[var];}at24cxx_write(eeprom_dev,CF_START_ADD,(uint8_t *)temp,CH_NUM*2); /*向eeprom 中写入数据*/rt_kprintf(">校准值已保存到 eeprom ... \n");}void eeprom_rw_entry(void *param){ rt_kprintf(">eeprom 线程启动... \n"); eeprom_init(); rt_kprintf(">eeprom 初始化完成... \n");#ifdefEEPROM_TEST_CODE /* 数据读写测试 */ uint8_t eeprom_RBuffer[254]; uint8_t eeprom_WBuffer[254]; for (uint8_t var = 0; var < 254; ++var) { eeprom_WBuffer[var] = var ; } at24cxx_write(eeprom_dev,0,eeprom_WBuffer,254); /*向eeprom 中写入数据*/ rt_kprintf("eeprom 数据写入 完成... \n"); rt_thread_mdelay(100); at24cxx_read(eeprom_dev,0,eeprom_RBuffer,254);/*从eeprom 中读数据*/ rt_kprintf("eeprom 数据读出 完成... \n"); for (uint8_t var = 0; var < 254; ++var) { rt_kprintf("ADD = %d ,Data = %d \n",var,eeprom_RBuffer[var]); } /* 以上 数据读写测试 */#endif uint8_t eeprom_RBuffer[CH_NUM*2]; at24cxx_read(eeprom_dev,CF_START_ADD,eeprom_RBuffer,CH_NUM*2);/*从eeprom 中读数据放入内存*/ for (uint8_t var = 0; var < CH_NUM; ++var)/* eeprom 中的校准数据转换成16bit后给校准值变量,eeprom中存储方式为高位在前,低位在后。*/ { Adc_Channel_CF_Data[var] = eeprom_RBuffer[2*var]; Adc_Channel_CF_Data[var] = (Adc_Channel_CF_Data[var]<<8)|eeprom_RBuffer[2*var+1]; rt_kprintf("校准值:%011s ,Data = %05d \n",Adc_Channel_Name[var],Adc_Channel_CF_Data[var]); } while(1) { rt_thread_mdelay(100); }}void eeprom_test(void){rt_thread_t tid1;//创建线程控制块指针来接收线程创建函数的返回值,目的是通过返回值判断线程是否创建ok/* 创建线程 1,名称是 pt_io_test_entry,入口是 pt_io_test_entry*/tid1 = rt_thread_create("eeprom_rw_entry",eeprom_rw_entry, RT_NULL,1700,//设置内存堆栈大小10, 50);//设置优先级,时间片参数,时间片是在有多个相同优先级线程时,这个线程每次被执行多少个时间片/* 如果获得线程控制块,启动这个线程 */if (tid1 != RT_NULL)rt_thread_startup(tid1);}INIT_APP_EXPORT(eeprom_test);
6. 项目使用中对软件包函数的一些描述
at24cxx.c
/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2019-04-13 XiaojieFan the first version * 2019-12-04 RenMingADD PAGE WRITE and input address can be selected*/#include #include #include #include #include #define DBG_ENABLE#define DBG_SECTION_NAME "at24xx"#define DBG_LEVEL DBG_LOG#define DBG_COLOR#include #include "at24cxx.h"#ifdef PKG_USING_AT24CXX#define AT24CXX_ADDR (0xA0 >> 1)//A0 = A1 = A2 =L, connect GND//#define AT24CXX_ADDR (0x51) //A0 = H, A1 = L, A2 = L#if (EE_TYPE == AT24C01)#define AT24CXX_PAGE_BYTE 8#define AT24CXX_MAX_MEM_ADDRESS 128#elif (EE_TYPE == AT24C02)#define AT24CXX_PAGE_BYTE 8#define AT24CXX_MAX_MEM_ADDRESS 256#elif (EE_TYPE == AT24C04)#define AT24CXX_PAGE_BYTE 16#define AT24CXX_MAX_MEM_ADDRESS 512#elif (EE_TYPE == AT24C08)#define AT24CXX_PAGE_BYTE 16#define AT24CXX_MAX_MEM_ADDRESS 1024#elif (EE_TYPE == AT24C16)#define AT24CXX_PAGE_BYTE 16#define AT24CXX_MAX_MEM_ADDRESS 2048#elif (EE_TYPE == AT24C32)#define AT24CXX_PAGE_BYTE 32#define AT24CXX_MAX_MEM_ADDRESS 4096#elif (EE_TYPE == AT24C64)#define AT24CXX_PAGE_BYTE 32#define AT24CXX_MAX_MEM_ADDRESS 8192#elif (EE_TYPE == AT24C128)#define AT24CXX_PAGE_BYTE 64#define AT24CXX_MAX_MEM_ADDRESS 16384#elif (EE_TYPE == AT24C256)#define AT24CXX_PAGE_BYTE 64#define AT24CXX_MAX_MEM_ADDRESS 32768#elif (EE_TYPE == AT24C512)#define AT24CXX_PAGE_BYTE 128#define AT24CXX_MAX_MEM_ADDRESS 65536#endifstatic rt_err_t read_regs(at24cxx_device_t dev, rt_uint8_t len, rt_uint8_t *buf){struct rt_i2c_msg msgs;msgs.addr = AT24CXX_ADDR | dev->AddrInput;msgs.flags = RT_I2C_RD;msgs.buf = buf;msgs.len = len;if (rt_i2c_transfer(dev->i2c, &msgs, 1) == 1){return RT_EOK;}else{return -RT_ERROR;}}/**读取 eeprom 一个字节函数 (YL已验证测试) * @param dev ,at24cxx 设备对象 * @param readAddr;读取地址 * @return temp;返回读取到的数据 */uint8_t at24cxx_read_one_byte(at24cxx_device_t dev, uint16_t readAddr){rt_uint8_t buf[2];rt_uint8_t temp = 0;#if (EE_TYPE > AT24C16)buf[0] = (uint8_t)(readAddr>>8);buf[1] = (uint8_t)readAddr;if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR, 0, buf, 2) == 0) #elsebuf[0] = readAddr;if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR | dev->AddrInput, 0, buf, 1) == 0)#endif{return RT_ERROR;}read_regs(dev, 1, &temp);return temp;}/**写一个字节eeprom 函数 (YL已验证测试) * @param dev ,at24cxx 设备对象 * @param readAddr;写地址 * @param dataToWrite;待写入数据 * @return 写成功,写失败 */rt_err_t at24cxx_write_one_byte(at24cxx_device_t dev, uint16_t writeAddr, uint8_t dataToWrite){rt_uint8_t buf[3];#if (EE_TYPE > AT24C16)buf[0] = (uint8_t)(writeAddr>>8);buf[1] = (uint8_t)writeAddr;buf[2] = dataToWrite;if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR, 0, buf, 3) == 3)#elsebuf[0] = writeAddr; //cmdbuf[1] = dataToWrite;//buf[2] = data[1];if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR | dev->AddrInput, 0, buf, 2) == 2)#endifreturn RT_EOK;elsereturn -RT_ERROR;}rt_err_t at24cxx_read_page(at24cxx_device_t dev, uint32_t readAddr, uint8_t *pBuffer, uint16_t numToRead){struct rt_i2c_msg msgs[2];uint8_t AddrBuf[2];msgs[0].addr = AT24CXX_ADDR | dev->AddrInput;msgs[0].flags = RT_I2C_WR ; #if (EE_TYPE > AT24C16)AddrBuf[0] = readAddr >> 8;AddrBuf[1] = readAddr;msgs[0].buf = AddrBuf;msgs[0].len = 2; #elseAddrBuf[0] = readAddr;msgs[0].buf = AddrBuf;msgs[0].len = 1;#endifmsgs[1].addr = AT24CXX_ADDR | dev->AddrInput;msgs[1].flags = RT_I2C_RD;msgs[1].buf = pBuffer;msgs[1].len = numToRead;if(rt_i2c_transfer(dev->i2c, msgs, 2) == 0) {return RT_ERROR;}return RT_EOK;}/**写一页eeprom 函数 * @param dev ,at24cxx 设备对象 * @param readAddr;写地址 * @param *pBuffer; * @param numToWrite; * @return 写成功,写失败 */rt_err_t at24cxx_write_page(at24cxx_device_t dev, uint32_t wirteAddr, uint8_t *pBuffer, uint16_t numToWrite){struct rt_i2c_msg msgs[2];uint8_t AddrBuf[2];msgs[0].addr = AT24CXX_ADDR | dev->AddrInput;msgs[0].flags = RT_I2C_WR ;#if (EE_TYPE > AT24C16)AddrBuf[0] = wirteAddr >> 8;AddrBuf[1] = wirteAddr;msgs[0].buf = AddrBuf;msgs[0].len = 2; #elseAddrBuf[0] = wirteAddr;msgs[0].buf = AddrBuf;msgs[0].len = 1;#endifmsgs[1].addr = AT24CXX_ADDR | dev->AddrInput;msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;msgs[1].buf = pBuffer;msgs[1].len = numToWrite;if(rt_i2c_transfer(dev->i2c, msgs, 2) == 0) {return RT_ERROR;}return RT_EOK;}/**查看是否存在eeprom 设备,通过在最后一个字节写入标志位,进行判断 * @param dev ,at24cxx 设备对象 * @return =RT_EOK设备存在, != RT_EOK设备不存在 */rt_err_t at24cxx_check(at24cxx_device_t dev){uint8_t temp;RT_ASSERT(dev);temp = at24cxx_read_one_byte(dev, AT24CXX_MAX_MEM_ADDRESS - 1);if (temp == 0x55) return RT_EOK;else{at24cxx_write_one_byte(dev, AT24CXX_MAX_MEM_ADDRESS - 1, 0x55);rt_thread_mdelay(EE_TWR); // wait 5ms befor next operationtemp = at24cxx_read_one_byte(dev, AT24CXX_MAX_MEM_ADDRESS - 1);if (temp == 0x55) return RT_EOK;}return RT_ERROR;}/**连续读取 * This function read the specific numbers of data to the specific position;读取 eeprom ,在AT24CXX里面的指定地址开始读出指定个数的数据 * * @param bus the name of at24cxx device ; dev:总线at24cxx设备的名称 * @param ReadAddr the start position to read; ReadAddr:读取的起始位置 * @param pBufferthe read data store position; pBuffer:读取数据存储位置 * @param NumToRead; NumToRead:读取数量 * @return RT_EOKwrite ok.!= RT_EOK 读取成功,RT_EOK 读取失败 */rt_err_t at24cxx_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead){rt_err_t result;RT_ASSERT(dev);if(ReadAddr + NumToRead > AT24CXX_MAX_MEM_ADDRESS){return RT_ERROR;}result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);if (result == RT_EOK){while (NumToRead){*pBuffer++ = at24cxx_read_one_byte(dev, ReadAddr++);NumToRead--;}}else{LOG_E("The at24cxx could not respondat this time. Please try again");}rt_mutex_release(dev->lock);return RT_EOK;}/** * This function read the specific numbers of data to the specific position * * @param bus the name of at24cxx device * @param ReadAddr the start position to read * @param pBufferthe read data store position * @param NumToRead* @return RT_EOKwrite ok. */rt_err_t at24cxx_page_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead){rt_err_t result = RT_EOK;uint16_t pageReadSize = AT24CXX_PAGE_BYTE - ReadAddr % AT24CXX_PAGE_BYTE;RT_ASSERT(dev);if(ReadAddr + NumToRead > AT24CXX_MAX_MEM_ADDRESS){return RT_ERROR;}result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);if(result == RT_EOK){while (NumToRead){if(NumToRead > pageReadSize){if(at24cxx_read_page(dev, ReadAddr, pBuffer, pageReadSize)){result = RT_ERROR;}ReadAddr += pageReadSize;pBuffer += pageReadSize;NumToRead -= pageReadSize;pageReadSize = AT24CXX_PAGE_BYTE;}else{if(at24cxx_read_page(dev, ReadAddr, pBuffer, NumToRead)){result = RT_ERROR;}NumToRead = 0;}}}else{LOG_E("The at24cxx could not respondat this time. Please try again");}rt_mutex_release(dev->lock);return result;}/**连续写入 * This function write the specific numbers of data to the specific position;写入,在AT24CXX里面的指定地址开始写入指定个数的数据 * * @param bus the name of at24cxx device;at24cxxdev:设备对象 * @param WriteAddr the start position to write;WriteAddr:写入的首地址 * @param pBufferthe data need to write;*pBuffer:需要写入的数据的首地址 * @param NumToWrite;NumToWrite:写入数量 * @return RT_EOKwrite ok.at24cxx_device_t dev */rt_err_t at24cxx_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite){//rt_err_t ret; /*YL新增*/uint16_t i = 0;rt_err_t result;RT_ASSERT(dev);if(WriteAddr + NumToWrite > AT24CXX_MAX_MEM_ADDRESS){return RT_ERROR;}result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);if (result == RT_EOK){/*以下 原源代码*/while (1) //NumToWrite--{if (at24cxx_write_one_byte(dev, WriteAddr, pBuffer[i]) != RT_EOK){rt_thread_mdelay(EE_TWR);}else{WriteAddr++;i++;}if (i == NumToWrite){break;}}/*以上 原源代码*///while (1) //NumToWrite--//{//ret = at24cxx_write_one_byte(dev, WriteAddr, pBuffer[i]);//if (at24cxx_write_one_byte(dev, WriteAddr, pBuffer[i]) != RT_EOK)//{//rt_thread_mdelay(EE_TWR);//}//else//{//WriteAddr++;//i++;//}//if (i == NumToWrite)//{//break;//}////}}else{LOG_E("The at24cxx could not respondat this time. Please try again");}rt_mutex_release(dev->lock);return RT_EOK;}/**此函数将特定数量的数据写入特定位置 * This function write the specific numbers of data to the specific position * * @param bus the name of at24cxx device; dev:设备对象 * @param WriteAddr the start position to write;WriteAddr:写入的首地址 * @param pBufferthe data need to write*pBuffer:需要写入的数据的首地址 * @param NumToWrite NumToWrite:写入数量 * @return RT_EOKwrite ok.at24cxx_device_t dev */rt_err_t at24cxx_page_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite){rt_err_t result = RT_EOK;uint16_t pageWriteSize = AT24CXX_PAGE_BYTE - WriteAddr % AT24CXX_PAGE_BYTE;RT_ASSERT(dev);if(WriteAddr + NumToWrite > AT24CXX_MAX_MEM_ADDRESS){return RT_ERROR;}result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);if(result == RT_EOK){while (NumToWrite){if(NumToWrite > pageWriteSize){if(at24cxx_write_page(dev, WriteAddr, pBuffer, pageWriteSize)){result = RT_ERROR;}rt_thread_mdelay(EE_TWR);// wait 5ms befor next operationWriteAddr += pageWriteSize;pBuffer += pageWriteSize;NumToWrite -= pageWriteSize;pageWriteSize = AT24CXX_PAGE_BYTE;}else{if(at24cxx_write_page(dev, WriteAddr, pBuffer, NumToWrite)){result = RT_ERROR;}rt_thread_mdelay(EE_TWR); // wait 5ms befor next operationNumToWrite = 0;}}}else{LOG_E("The at24cxx could not respondat this time. Please try again");}rt_mutex_release(dev->lock);return result;}/**设备初始化 * This function initializes at24cxx registered device driver ;根据总线名称,自动初始化对应的 AT24CXX 设备 * * @param dev the name of at24cxx device ;i2c_bus_name,i2c 设备名称 * @param * @return the at24cxx device. */at24cxx_device_t at24cxx_init(const char *i2c_bus_name, uint8_t AddrInput){at24cxx_device_t dev;RT_ASSERT(i2c_bus_name);dev = rt_calloc(1, sizeof(struct at24cxx_device));if (dev == RT_NULL){LOG_E("Can't allocate memory for at24cxx device on '%s' ", i2c_bus_name);return RT_NULL;}dev->i2c = rt_i2c_bus_device_find(i2c_bus_name);if (dev->i2c == RT_NULL){LOG_E("Can't find at24cxx device on '%s' ", i2c_bus_name);rt_free(dev);return RT_NULL;}dev->lock = rt_mutex_create("mutex_at24cxx", RT_IPC_FLAG_FIFO);if (dev->lock == RT_NULL){LOG_E("Can't create mutex for at24cxx device on '%s' ", i2c_bus_name);rt_free(dev);return RT_NULL;}dev->AddrInput = AddrInput;return dev;}/** * This function releases memory and deletes mutex lock * 如果设备不再使用,反初始化将回收 at24cxx 设备的相关资源 * @param dev the pointer of device driver structure */void at24cxx_deinit(at24cxx_device_t dev){RT_ASSERT(dev);rt_mutex_delete(dev->lock);rt_free(dev);}uint8_t TEST_BUFFER[] = "WELCOM TO RTT";#define SIZE sizeof(TEST_BUFFER)void at24cxx(int argc, char *argv[]){static at24cxx_device_t dev = RT_NULL;if (argc > 1){if (!strcmp(argv[1], "probe")){if (argc > 2){/* initialize the sensor when first probe */if (!dev || strcmp(dev->i2c->parent.parent.name, argv[2])){/* deinit the old device */if (dev){at24cxx_deinit(dev);}dev = at24cxx_init(argv[2], atoi(argv[3]));}}else{rt_kprintf("at24cxx probe - probe sensor by given name\n");}}else if (!strcmp(argv[1], "read")){if (dev){uint8_t testbuffer[50];/* read the eeprom data */at24cxx_read(dev, 0, testbuffer, SIZE);rt_kprintf("read at24cxx : %s\n", testbuffer);}else{rt_kprintf("Please using 'at24cxx probe ' first\n");}}else if (!strcmp(argv[1], "write")){at24cxx_write(dev, 0, TEST_BUFFER, SIZE);rt_kprintf("write ok\n");}else if (!strcmp(argv[1], "check")){if (at24cxx_check(dev) == 1){rt_kprintf("check faild \n");}}else{rt_kprintf("Unknown command. Please enter 'at24cxx0' for help\n");}}else{rt_kprintf("Usage:\n");rt_kprintf("at24cxx probe - probe eeprom by given name\n");rt_kprintf("at24cxx check- check eeprom at24cxx \n");rt_kprintf("at24cxx read - read eeprom at24cxx data\n");rt_kprintf("at24cxx write- write eeprom at24cxx data\n");}}MSH_CMD_EXPORT(at24cxx, at24cxx eeprom function);#endif
at24cxx.h
/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2019-04-13 XiaojieFan the first version * 2019-12-04 RenMingUse PAGE WRITE instead of BYTE WRITE and input address can be selected*/#ifndef __AT24CXX_H__#define __AT24CXX_H__#include #include #include #include #define AT24C01 0#define AT24C02 1#define AT24C04 2#define AT24C08 3#define AT24C16 4#define AT24C32 5#define AT24C64 6#define AT24C1287#define AT24C2568#define AT24C5129#define AT24CTYPE 10 // Number of supported types/* *注意事项: *请在at24cxx.h中修改EE_TYPE为自己使用的型号(默认为AT25C512) 。 *请在at24cxx.h中修改EE_TWR为自己使用EEPROM的Write Cycle Time,具体值请查看芯片datasheet(默认为5ms) 。 *从设备地址为7位地址 0x50, 而不是 0xA0 。 */#define EE_TWR5 //Write Cycle Time;写周期时间 ms#ifndef EE_TYPE#define EE_TYPE AT24C64#endifstruct at24cxx_device{struct rt_i2c_bus_device *i2c;rt_mutex_t lock;uint8_t AddrInput;};typedef struct at24cxx_device *at24cxx_device_t;extern uint8_t at24cxx_read_one_byte(at24cxx_device_t dev, uint16_t readAddr);extern rt_err_t at24cxx_write_one_byte(at24cxx_device_t dev, uint16_t writeAddr, uint8_t dataToWrite);extern at24cxx_device_t at24cxx_init(const char *i2c_bus_name, uint8_t AddrInput);extern rt_err_t at24cxx_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead);extern rt_err_t at24cxx_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite);extern rt_err_t at24cxx_page_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead);extern rt_err_t at24cxx_page_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite);#endif