AT24C1024是基于IIC的EEPROM,容量为1024/8=128k bytes。它的引脚如下:
其中A1,A2为硬件地址引脚
WP为写保护引脚,一般我们需要读写,需要接低电平GND,接高的话则仅允许读
SDA和SCL则为IIC通信引脚
芯片通信采用IIC,有关IIC的通信原理可参考:
读数据:
- 启动总线
- 发送设备地址+写...等待应答
- 发送数据存储地址...等待应答
- 发送数据
- 结束总线
写数据:
- 启动总线
- 发送设备地址+写...等待应答
- 发送数据存储地址...等待应答
- 发送设备地址+读...等待应答
- 读数据
- 结束总线
本次采用模拟IIC的方式,便于移植,具体的代码如下
void eeprom_start(void)
{
IIC_SDA_ON;
IIC_SCL_OFF;
DELAY_US (10);
IIC_SCL_ON;
DELAY_US(1);
IIC_SDA_OFF;
DELAY_US(1);
IIC_SCL_OFF;
DELAY_US(2);
IIC_SCL_OFF;
IIC_SDA_ON;
DELAY_US(10);
}
void eeprom_stop(void)
{
IIC_SDA_OFF;
IIC_SCL_OFF;
DELAY_US(1);
IIC_SCL_ON;
DELAY_US(1);
IIC_SDA_ON;
DELAY_US(2);
IIC_SCL_OFF;
DELAY_US(2);
IIC_SCL_OFF;
IIC_SDA_ON;
DELAY_US(10);
}
void eeprom_ack(void)
{
IIC_SDA_ON;
IIC_SCL_OFF;
DELAY_US (10);
IIC_SDA_OFF;
DELAY_US(1);
IIC_SCL_ON;
DELAY_US(1);
IIC_SCL_OFF;
DELAY_US(2);
IIC_SCL_OFF;
IIC_SDA_ON;
DELAY_US(10);
}
void eeprom_noack(void)
{
IIC_SDA_ON;
IIC_SCL_OFF;
DELAY_US (10);
IIC_SCL_ON;
DELAY_US(1);
IIC_SCL_OFF;
DELAY_US(2);
IIC_SCL_OFF;
IIC_SDA_ON;
DELAY_US(10);
}
void eeprom_checkack(void)
{
IIC_SCL_ON;
DELAY_US(10);
IIC_SCL_OFF;
}
void eeprom_write_byte(unsigned char ucChar)
{
unsigned char i;
IIC_SDA_ON;
IIC_SCL_OFF;
DELAY_US (10);
for(i=0; i<8; i++)
{
if(!(ucChar & BIT(7-i)) == 0) IIC_SDA_ON;
else IIC_SDA_OFF;
DELAY_US (1);
IIC_SCL_ON;
DELAY_US(1);
IIC_SCL_OFF;
DELAY_US(2);
}
IIC_SCL_OFF;
IIC_SDA_ON;
DELAY_US(10);
}
unsigned char eeprom_read_byte(void)
{
unsigned char i;
unsigned char ucChar = 0;
for(i=0; i<8; i++)
{
if(IIC_SDA_VALUE == 1)
{
ucChar |= BIT(7 - i);
}
else
{
ucChar &= ~BIT(7 - i);
}
IIC_SCL_ON;
DELAY_US(1);
IIC_SCL_OFF;
DELAY_US(2);
}
IIC_SCL_OFF;
IIC_SDA_ON;
DELAY_US(10);
return ucChar;
}
void eeprom_write_char(unsigned int nAddress,unsigned char ucChar)
{
eeprom_start();
if(nAddress>=0x10000) eeprom_write_byte(0xa2);
else eeprom_write_byte(0xa0);
eeprom_checkack();
eeprom_write_byte(nAddress/256);
eeprom_checkack();
eeprom_write_byte(nAddress%256);
eeprom_checkack();
eeprom_write_byte(ucChar);
eeprom_checkack();
eeprom_stop();
if(nAddress%256 == 0) DELAY_MS(100);
else DELAY_MS(8);
}
unsigned char eeprom_read_char(unsigned int nAddress)
{
unsigned char ucChar;
eeprom_start();
if(nAddress>=0x10000) eeprom_write_byte(0xa2);
else eeprom_write_byte(0xa0);
eeprom_checkack();
eeprom_write_byte(nAddress/256);
eeprom_checkack();
eeprom_write_byte(nAddress%256);
eeprom_checkack();
eeprom_start();
if(nAddress>=0x10000) eeprom_write_byte(0xa3);
else eeprom_write_byte(0xa1);
eeprom_checkack();
ucChar = eeprom_read_byte();
eeprom_noack();
eeprom_stop();
DELAY_US(10);
return ucChar;
}
其中IIC_SCL_ON和IIC_SCL_OFF表示SCL引脚电平拉高或拉低,
IIC_SDA_ON和IIC_SDA_OFF表示SDA引脚电平拉高或拉低,IIC_SDA_VALUE表示读取SDA引脚电平。需要注意的是,模拟IIC时引脚需要设置为开漏输出且需要上拉电阻。
有两个需要注意的点,一个是器件地址指令,当写存储地址处于前一半时,发送A0指令,当写存储地址处于后一半时,发送A2指令。另一个则是跨页写,每256字节为一页,当出现跨页写时,需要增大延时,否则有可能出错。