/*
- File : 24clxx.c
- This file is part of eeprom driver for 24clxx,such as at24c02/at24c16.
- COPYRIGHT © 2014 - 2016,
- Change Logs:
- Date Author Notes
- Depend on:
- i2c_bitops.c
- Note:
- 24c04 24c08 24c16 地址为8位,超过0xff地址后,注意页的选择读写
- 24c32 及以上地址为16位
- EEPROM 页读写需要作应答查询或作短暂延时以等待数据写入完成;FM24CLXX则不需要
*/
#define USE_24CLXX_EN 1
#define USE_24CLXX_DEBUG 0
#if USE_24CLXX_EN
#include “main.h”
//eeprom/fram 参数
#define EEPROM_TYPE 0 //0->EEPROM 1->FRAM
#define EEPROM_MODEL 16 //EEPROM 类型 24c16
#define EE24CLXX_SLAVE_ADDR 0x50 //注意读写位,实际地址为0x50
#define EE24CLXX_PageSize 16 //AT24C16每页有16个字节 24C02->8 24c64->32
static void I2C_24CLXXWaitStandby(u8 slave_addr);
//页写延时,FRAM不用
static void I2C_24CLXXWaitStandby(u8 slave_addr)
{
#if EEPROM_TYPE
#else
u16 i;
i = 0xFFFF;
while (i–);
#endif
}
//写多字节,需确保当前写地址+写入数据长度不能超过EEPROM的一页
static void i2c_24clxx_write( u16 WriteAddr, char* pBuffer,u16 NumByteToWrite)
{
struct st_i2c_msg ee24_msg[2];
u8 buf[2];
u8 slave_addr;
//if(WriteAddr+NumByteToWrite > EE24CLXX_PageSize)
// return;
if(EEPROM_MODEL > 16)
{//大于2k字节时,地址为16位
slave_addr = EE24CLXX_SLAVE_ADDR;
buf[0] = (WriteAddr >>8)& 0xff;
buf[1] = WriteAddr & 0xff;
ee24_msg[0].size = 2;
}
else
{
slave_addr = EE24CLXX_SLAVE_ADDR | (WriteAddr>>8);
buf[0] = WriteAddr & 0xff;
ee24_msg[0].size = 1;
}
ee24_msg[0].addr = slave_addr;
ee24_msg[0].flags = ST_I2C_WR;
ee24_msg[0].buff = buf;
ee24_msg[1].addr = slave_addr;
ee24_msg[1].flags = ST_I2C_WR | ST_I2C_NO_START;
ee24_msg[1].buff = (u8*)pBuffer;
ee24_msg[1].size = NumByteToWrite;
i2c_bitops_bus_xfer(&i2c1_dev,ee24_msg,2);
}
/*******************************************************
**
** 外部函数
**
*******************************************************/
//写一字节
char ee_24clxx_writebyte(u16 addr,u8 data)
{
struct st_i2c_msg ee24_msg[2];
u8 buf[3];
u8 slave_addr;
if(EEPROM_MODEL > 16)
{//大于2k字节时,地址为16位
slave_addr = EE24CLXX_SLAVE_ADDR;
buf[0] = (addr >>8)& 0xff; //高位地址在前
buf[1] = addr & 0xff;
buf[2] = data;
ee24_msg[0].size = 3;
}
else
{
slave_addr = EE24CLXX_SLAVE_ADDR | (addr>>8);
buf[0] = addr & 0xff;
buf[1] = data;
ee24_msg[0].size = 2;
}
ee24_msg[0].addr = slave_addr;
ee24_msg[0].flags = ST_I2C_WR;
ee24_msg[0].buff = buf;
i2c_bitops_bus_xfer(&i2c1_dev,ee24_msg,1);
return 0;
}
//写多字节
//新的页写
char ee_24clxx_writebytes(u16 write_addr, char* pwrite_buff, u16 writebytes)
{
u8 write_len,page_offset;
u16 write_remain,write_current_addr;
char error = 0,*pbuff;
pbuff = pwrite_buff; //不要直接使用形参计算,特别是指针操作
write_remain = writebytes;
write_current_addr = write_addr;
while(write_remain > 0)
{
page_offset = write_current_addr & 0x0f; //write_current_addr%EE24CLXX_PageSize
write_len = write_remain > (EE24CLXX_PageSize - page_offset) ? (EE24CLXX_PageSize - page_offset) : write_remain;
i2c_24clxx_write(write_current_addr,pbuff, write_len);
write_remain = write_remain - write_len;
if(write_remain > 0)
{
pbuff = pbuff + EE24CLXX_PageSize - page_offset;
write_current_addr = write_current_addr + EE24CLXX_PageSize - page_offset;
I2C_24CLXXWaitStandby(0);
}
}
I2C_24CLXXWaitStandby(0);
{//校验数据
int i;
char checkdata;
for(i = 0;i < writebytes;i++)
{
ee_24clxx_readbytes(write_addr+i,&checkdata,1);
if(checkdata != pwrite_buff[i])
{
error = 1;
break;
}
}
}
return error;
}
//读多字节,连续读
void ee_24clxx_readbytes(u16 ReadAddr, char* pBuffer, u16 NumByteToRead)
{
struct st_i2c_msg ee24_msg[2];
u8 buf[2];
u8 slave_addr;
if(EEPROM_MODEL > 16)
{//大于2k字节时,地址为16位
slave_addr = EE24CLXX_SLAVE_ADDR;
buf[0] = (ReadAddr >>8)& 0xff;
buf[1] = ReadAddr & 0xff;
ee24_msg[0].size = 2;
}
else
{
slave_addr = EE24CLXX_SLAVE_ADDR | (ReadAddr>>8);
buf[0] = ReadAddr & 0xff;
ee24_msg[0].size = 1;
}
ee24_msg[0].buff = buf;
ee24_msg[0].addr = slave_addr;
ee24_msg[0].flags = ST_I2C_WR;
ee24_msg[1].addr = slave_addr;
ee24_msg[1].flags = ST_I2C_RD;
ee24_msg[1].buff = (u8*)pBuffer;
ee24_msg[1].size = NumByteToRead;
i2c_bitops_bus_xfer(&i2c1_dev,ee24_msg,2);
}
//擦除EEPROM
char ee_24clxx_erasebytes(u16 WriteAddr, char Erasedata, u16 NumByteToErase)
{
char error = 0;
u16 i;
//char *buff;
char buff[2048]; //测试用,实际使用需动态分配内存
//buff = (char*)malloc(2048);
for(i = 0;i < NumByteToErase;i++)
{
buff[i] = Erasedata;
}
error = ee_24clxx_writebytes(WriteAddr,buff,NumByteToErase);
//free(buff);
return error;
}
//eeprom test
#if USE_24CLXX_DEBUG
#define WRSIZE 2048
#define EEP_Firstpage 0
char I2c_Buf_Write[WRSIZE];
char I2c_Buf_Read[WRSIZE];
void EE24CLXX_Test(void)
{
u16 i,error = 0;
for ( i=0; i<WRSIZE; i++ ) //填充缓冲
{
I2c_Buf_Write[i] = i;
}
ee_24clxx_readbytes(EEP_Firstpage, I2c_Buf_Read, WRSIZE);
ee_24clxx_readbytes(EEP_Firstpage, I2c_Buf_Read, WRSIZE);
error = ee_24clxx_writebytes(EEP_Firstpage, I2c_Buf_Write, WRSIZE);
Delayms(5);
ee_24clxx_readbytes(EEP_Firstpage, I2c_Buf_Read, WRSIZE);
for ( i=0; i<WRSIZE; i++ ) //填充缓冲
I2c_Buf_Write[i] = 0;
error = ee_24clxx_writebytes(EEP_Firstpage, I2c_Buf_Write, WRSIZE);
Delayms(5);
ee_24clxx_readbytes(EEP_Firstpage, I2c_Buf_Read,WRSIZE);
//while(error);
}
#endif
#endif