at24c1024数据怎么写不进去?写的数据读出来都是0./*******************************************************************/
/* 函数功能:给AT24C1024写数据 */
/* 入口参数StartAddr:起始地址,跨页写时,需要重新写入地址数据。 */
/* *pData:把这个数组中的数据写入 */
/* nBytes:要写的数据字节个数 */
/*******************************************************************/
void AT24C1024_Write(uint8_t *pData,uint32_t StartAddr, uint16_t nBytes)
{
uint16_t i;
uint8_t StartAddr_L, StartAddr_H, P0;
while(nBytes != 0) // 所有数据发送完毕,退出循环
{
StartAddr_L = StartAddr & 0x0000ff; // 计算低位地址
StartAddr_H = (StartAddr >> 8) & 0x0ff; // 计算高位地址
P0 = (StartAddr / 0x10000) << 1; // 计算第17位,即P0
/* 第0步:发停止信号,启动内部写操作 */
i2c_Stop();
for (i = 0; i < 100; i++)
{
/* 第1步:发起I2C总线启动信号 */
i2c_Start();
/* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
i2c_SendByte(AT24C1024_Addr | P0 | I2C_WR); /* 此处是写指令 */
/* 第3步:发送一个时钟,判断器件是否正确应答 */
if (i2c_WaitAck() == 0)
{
break;
}
}
if (i == 1000)
{
goto cmd_fail; /* EEPROM器件写超时 */
}
i2c_SendByte(AT24C1024_Addr | P0 | I2C_WR); // 带P0发送器件地址
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件无应答 */
}
i2c_SendByte(StartAddr_H); // 发送高位地址
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件无应答 */
}
i2c_SendByte(StartAddr_L); // 发送低位地址
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件无应答 */
}
while(nBytes != 0) // 数据未发送完,循环
{
i2c_SendByte(*pData);
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件无应答 */
}
pData++;
nBytes--;
StartAddr++;
if((StartAddr & 0x00ff) == 0) // 跨页,终止当前页循环,重新写入新地址
break;
}
}
i2c_Stop();
delay_ms(3);
cmd_fail:
i2c_Stop();
delay_ms(3);
}
/************************************************************/
/* 函数功能:从AT24C1024中读数据 */
/* 入口参数StartAddr:起始地址,经测试跨页时地址会自动加1。*/
/* *pData:读入的数据放到这个数组中 */
/* nBytes:要写的数据字节个数 */
/************************************************************/
void AT24C1024_Read(uint8_t *pData,uint32_t StartAddr, uint16_t nBytes)
{
uint16_t i;
uint8_t StartAddr_L, StartAddr_H, P0;
StartAddr_L = StartAddr & 0x0000ff; // 计算低位地址
StartAddr_H = (StartAddr >> 8) & 0x0ff; // 计算高位地址
P0 = (StartAddr / 0x10000) << 1;
/* 采用串行EEPROM随即读取指令序列,连续读取若干字节 */
/* 第1步:发起I2C总线启动信号 */
i2c_Start();
/* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
i2c_SendByte(AT24C1024_Addr | P0 | I2C_WR); /* 此处是写指令 */
/* 第3步:发送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件无应答 */
}
/* 第4步:发送字节地址,24C02只有256字节,因此1个字节就够了,如果是24C04以上,那
么此处需要连发多个地址 */
i2c_SendByte(StartAddr_H);
/* 第5步:发送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件无应答 */
}
/* 第4步:发送字节地址,24C02只有256字节,因此1个字节就够了,如果是24C04
以上,那么此处需要连发多个地址 */
i2c_SendByte(StartAddr_L);
/* 第5步:发送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件无应答 */
}
/* 第6步:重新启动I2C总线。前面的代码的目的向EEPROM传送地址,下面开始读取数据 */
i2c_Start();
/* 第7步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
i2c_SendByte(AT24C1024_Addr | P0 | I2C_RD); /* 此处是读指令 */
/* 第8步:发送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件无应答 */
}
/* 第9步:循环读取数据 */
for (i = 0; i < nBytes; i++)
{
pData = i2c_ReadByte(); /* 读1个字节 */
/* 每读完1个字节后,需要发送Ack, 最后一个字节不需要Ack,发Nack */
if (i != nBytes - 1)
{
i2c_Ack(); /* 中间字节读完后,CPU产生ACK信号(驱动SDA = 0) */
}
else
{
i2c_NAck(); /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
}
}
cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
/* 发送I2C总线停止信号 */
i2c_Stop();
i2c_Delay();
} |