1、eeprom
eeprom是一种掉电不丢失数据的器件,常用于上电加载初始化数据,最常用的通讯方式是I2C协议。
如下图,芯片型号AT24C02(共存256个字节,每页8个字节),设备地址一共7位,高四位固定,后三位由A0 A1 A2如下图连接的电平决定。
R/W是读写方向,与地址无关,即主设备读取时=1,主设备写时=0。
wp是写保护,即可写入数据时=0,不可写入数据时=1。
2、软件模拟
配置两个IO口
void i2c_CfgGpio(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(EEPROM_RCC_I2C_PORT, ENABLE);
GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SDA_PIN | EEPROM_I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏模式
GPIO_Init(EEPROM_GPIO_PORT_I2C, &GPIO_InitStructure);
i2c_Stop();//复位从设备
}
检查eeprom器件是否在线
uint8_t i2c_CheckDevice(uint8_t _Address)
{
uint8_t ucAck;
i2c_CfgGpio();
i2c_Start();
i2c_SendByte(_Address | EEPROM_I2C_WR);
ucAck = i2c_WaitAck();
i2c_Stop();
return ucAck;
}
写函数
uint8_t ee_WriteBytes(uint8_t *_pWriteBuf, uint16_t _usAddress, uint16_t _usSize)
{
uint16_t i,m;
uint16_t usAddr;
usAddr = _usAddress;
for (i = 0; i < _usSize; i++)
{
if ((i == 0) || (usAddr & (EEPROM_PAGE_SIZE - 1)) == 0)
{
i2c_Stop();
for (m = 0; m < 1000; m++)
{
i2c_Start();
i2c_SendByte(EEPROM_DEV_ADDR | EEPROM_I2C_WR);
if (i2c_WaitAck() == 0)
{
break;
}
}
if (m == 1000)//写数据超时监测
{
goto cmd_fail;
}
i2c_SendByte((uint8_t)usAddr);
if (i2c_WaitAck() != 0)
{
goto cmd_fail;
}
}
i2c_SendByte(_pWriteBuf[i]);
if (i2c_WaitAck() != 0)
{
goto cmd_fail;
}
usAddr++;
}
i2c_Stop();
return 1;
cmd_fail:
i2c_Stop();
return 0;
}
读函数
uint8_t ee_ReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize)
{
uint16_t i;
i2c_Start();
i2c_SendByte(EEPROM_DEV_ADDR | EEPROM_I2C_WR);//写入地址
if (i2c_WaitAck() != 0)
{
goto cmd_fail;
}
i2c_SendByte((uint8_t)_usAddress);
if (i2c_WaitAck() != 0)
{
goto cmd_fail;
}
i2c_Start();
i2c_SendByte(EEPROM_DEV_ADDR | EEPROM_I2C_RD);//读取指令
if (i2c_WaitAck() != 0)
{
goto cmd_fail;
}
for (i = 0; i < _usSize; i++)
{
_pReadBuf[i] = i2c_ReadByte();
if (i != _usSize - 1)
{
i2c_Ack();
}
else
{
i2c_NAck();
}
}
i2c_Stop();
return 1;
cmd_fail:
i2c_Stop();
return 0;
}
起始信号和停止信号
void i2c_Start(void)
{
EEPROM_I2C_SDA_1();
EEPROM_I2C_SCL_1();
i2c_Delay();
EEPROM_I2C_SDA_0();
i2c_Delay();
EEPROM_I2C_SCL_0();
i2c_Delay();
}
//
void i2c_Stop(void)
{
EEPROM_I2C_SDA_0();
EEPROM_I2C_SCL_1();
i2c_Delay();
EEPROM_I2C_SDA_1();
}
应答与非应答
void i2c_Ack(void)
{
EEPROM_I2C_SDA_0();
i2c_Delay();
EEPROM_I2C_SCL_1();
i2c_Delay();
EEPROM_I2C_SCL_0();
i2c_Delay();
EEPROM_I2C_SDA_1();
}
//
void i2c_NAck(void)
{
EEPROM_I2C_SDA_1();
i2c_Delay();
EEPROM_I2C_SCL_1();
i2c_Delay();
EEPROM_I2C_SCL_0();
i2c_Delay();
}
3、实验
向EEPROM写入15个数据,0 1 2 3 。。。14
读取第15个数据