EEPROM:24AA16
我已经用 C 语言为 PIC 编写了一些代码,以通过 I2C 读取和写入外部 EEPROM。当我使用这些方法写入单个字节,然后再次读取它以进行验证时,它可以工作。如果我更改写入位置,它会起作用,所以我认为寻址是有效的,并且我读回的字节与写入匹配,所以这似乎也有效。到目前为止一切都很好!
然后我将代码扩展为使用相同的例程 100 次,在相邻位置写入不同的字节。IE 在位置 x 到 x + 99 中写入值 0 到 99。然后我继续读回 100 个位置以验证写入,这就是出错的地方。
从各种测试来看,write 方法在同一位置执行所有写入操作,因为 read 方法从第一个位置获取最后一个值 (99),而从其他位置获取任何值 (0xFF)!
示波器显示时钟良好,数据线切换,这是我预期的单次写入工作。
PIC 上的调试显示这些方法使用的地址是连续的,所以我有点困惑为什么所有的写入都在同一个位置执行!我可以更改此位置,但它始终只使用所有值的第一个字节。
有谁知道可能出了什么问题?
我的代码在这里,入口点是testEeprom():
// ----------------------------------------------------------------------------
#include "eeprom.h"
//#define _PLIB_DISABLE_LEGACY
#include <plib.h>
//// ----------------------------------------------------------------------------
#define SYS_CLOCK (80000000L)
#define GetSystemClock() (SYS_CLOCK)
#define GetPeripheralClock() (SYS_CLOCK / 2)
#define GetInstructionClock() (SYS_CLOCK)
#define I2C_CLOCK_FREQ 100000
#define EEPROM_I2C_BUS I2C1
#define EEPROM_ADDRESS 0x50 // 0b1010000 Serial EEPROM address
#define EEPROM_STORAGE_LOCATION 0x0100
#define DATA_ARRAY_SIZE 100
// ----------------------------------------------------------------------------
UINT8 EEPROM_Data_Array[DATA_ARRAY_SIZE];
UINT8 EEPROM_Data_Array_RX[DATA_ARRAY_SIZE];
BOOL EEPROM_Success;
I2C_7_BIT_ADDRESS SlaveAddress;
// ----------------------------------------------------------------------------
void i2c_wait(unsigned int cnt)
{
while (--cnt)
{
Nop();
Nop();
} // while
}
// ----------------------------------------------------------------------------
BOOL StartTransfer(BOOL restart)
{
I2C_STATUS status;
// Send the Start (or Restart) signal
if (restart)
{
I2CRepeatStart(EEPROM_I2C_BUS);
}
else
{
// Wait for the bus to be idle, then start the transfer
while (!I2CBusIsIdle(EEPROM_I2C_BUS));
if (I2CStart(EEPROM_I2C_BUS) != I2C_SUCCESS)
{
debugTrace("I2C Error: Bus collision during transfer Start\r\n");
return FALSE;
}
}
// Wait for the signal to complete
do
{
status = I2CGetStatus(EEPROM_I2C_BUS);
}
while (!(status & I2C_START));
return TRUE;
}
// ----------------------------------------------------------------------------
BOOL TransmitOneByte(UINT8 data)
{
// Wait for the transmitter to be ready
while (!I2CTransmitterIsReady(EEPROM_I2C_BUS));
// Transmit the byte
if (I2CSendByte(EEPROM_I2C_BUS, data) == I2C_MASTER_BUS_COLLISION)
{
debugTrace("I2C Error: I2C Master Bus Collision\r\n");
return FALSE;
}
// Wait for the transmission to finish
while (!I2CTransmissionHasCompleted(EEPROM_I2C_BUS));
return TRUE;
}
// ----------------------------------------------------------------------------
void StopTransfer(void)
{
I2C_STATUS status;
// Send the Stop signal
I2CStop(EEPROM_I2C_BUS);
// Wait for the signal to complete
do
{
status = I2CGetStatus(EEPROM_I2C_BUS);
}
while (!(status & I2C_STOP));
}
// ----------------------------------------------------------------------------
void initIcd()
{
UINT32 actualClock;
EEPROM_Success = TRUE;
// Set the I2C baudrate
actualClock = I2CSetFrequency(EEPROM_I2C_BUS, GetPeripheralClock(), I2C_CLOCK_FREQ);
if (abs(actualClock - I2C_CLOCK_FREQ) > I2C_CLOCK_FREQ / 10)
{
debugTrace("Error: I2C1 clock frequency (%u) error exceeds 10%%.\r\n", (unsigned) actualClock);
}
// Enable the I2C bus
I2CEnable(EEPROM_I2C_BUS, TRUE);
}
// ----------------------------------------------------------------------------
// Send the data to EEPROM to program one location
// ----------------------------------------------------------------------------
void txIcd(unsigned int address, unsigned char value)
{
BOOL Acknowledged;
int Index;
UINT8 i2cData[4];
int DataSz;
EEPROM_Success = TRUE;
// Initialize the data buffer
I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_ADDRESS, I2C_WRITE);
i2cData[0] = SlaveAddress.byte;
i2cData[1] = address >> 8; // EEPROM location to program (high address byte)
i2cData[2] = address & 0xFF; // EEPROM location to program (low address byte)
i2cData[3] = value; // EEPROM location to program (low address byte)
DataSz = 4;
// Start the transfer to write data to the EEPROM
if (!StartTransfer(FALSE))
{
debugTrace("I2C Error: Can't Start Transfer TX (1)\r\n");
return;
}
// Transmit all header
Index = 0;
while (EEPROM_Success && (Index < DataSz))
{
// Transmit a byte
if (TransmitOneByte(i2cData[Index]))
{
// Advance to the next byte
Index++;
// Verify that the byte was acknowledged
if (!I2CByteWasAcknowledged(EEPROM_I2C_BUS))
{
debugTrace("I2C Error: Sent byte was not acknowledged (1)\r\n");
EEPROM_Success = FALSE;
}
}
else
{
EEPROM_Success = FALSE;
}
}
// End the transfer (hang here if an error occured)
StopTransfer();
if (!EEPROM_Success)
{
debugTrace("I2C Error: No Success on TX (1)\r\n");
return;
}
// Wait for EEPROM to complete write process, by polling the ack status.
Acknowledged = FALSE;
do
{
// Start the transfer to address the EEPROM
if (!StartTransfer(FALSE))
{
debugTrace("I2C Error: Can't Start Transfer TX (2)\r\n");
return;
}
// Transmit just the EEPROM's address
if (TransmitOneByte(SlaveAddress.byte))
{
// Check to see if the byte was acknowledged
Acknowledged = I2CByteWasAcknowledged(EEPROM_I2C_BUS);
}
else
{
EEPROM_Success = FALSE;
}
// End the transfer (stop here if an error occured)
StopTransfer();
if (!EEPROM_Success)
{
debugTrace("I2C Error: No Success on TX (2)\r\n");
return;
}
}
while (Acknowledged != TRUE);
}
// ----------------------------------------------------------------------------
// Read the data back from the EEPROM.
// ----------------------------------------------------------------------------
unsigned char rxIcd(unsigned int address)
{
UINT8 i2cbyte;
UINT8 i2cData[3];
int DataSz;
int Index;
EEPROM_Success = TRUE;
// Initialize the data buffer
I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_ADDRESS, I2C_WRITE);
i2cData[0] = SlaveAddress.byte;
i2cData[1] = address >> 8; // EEPROM location to program (high address byte)
i2cData[2] = address & 0xFF; // EEPROM location to program (low address byte)
DataSz = 3;
// Start the transfer to write data to the EEPROM
if (!StartTransfer(FALSE))
{
debugTrace("I2C Error: Can't Start Transfer TX (1)\r\n");
return;
}
// Transmit all header
Index = 0;
while (EEPROM_Success && (Index < DataSz))
{
// Transmit a byte
if (TransmitOneByte(i2cData[Index]))
{
// Advance to the next byte
Index++;
}
else
{
EEPROM_Success = FALSE;
}
// Verify that the byte was acknowledged
if (!I2CByteWasAcknowledged(EEPROM_I2C_BUS))
{
debugTrace("I2C Error: Sent byte was not acknowledged (1)\r\n");
EEPROM_Success = FALSE;
}
}
// Restart and send the EEPROM's internal address to switch to a read transfer
if (EEPROM_Success)
{
// Send a Repeated Started condition
if (!StartTransfer(TRUE))
{
debugTrace("I2C Error: Can't Start Transfer TX (4)\r\n");
return;
}
// Transmit the address with the READ bit set
I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_ADDRESS, I2C_READ);
if (TransmitOneByte(SlaveAddress.byte))
{
// Verify that the byte was acknowledged
if (!I2CByteWasAcknowledged(EEPROM_I2C_BUS))
{
debugTrace("I2C Error: Sent byte was not acknowledged (3)\r\n");
EEPROM_Success = FALSE;
}
}
else
{
EEPROM_Success = FALSE;
}
}
// Read the data from the desired address
if (EEPROM_Success)
{
if (I2CReceiverEnable(EEPROM_I2C_BUS, TRUE) == I2C_RECEIVE_OVERFLOW)
{
debugTrace("I2C Error: I2C Receive Overflow\r\n");
EEPROM_Success = FALSE;
}
else
{
while (!I2CReceivedDataIsAvailable(EEPROM_I2C_BUS));
i2cbyte = I2CGetByte(EEPROM_I2C_BUS);
}
}
// End the transfer (stop here if an error occured)
StopTransfer();
if (!EEPROM_Success)
{
debugTrace("I2C Error: No Success on TX (3)\r\n");
return;
}
return i2cbyte;
}
// ----------------------------------------------------------------------------
void testEeprom(void)
{
unsigned int i;
BOOL failed = FALSE;
unsigned char value;
// Create & Write 100 byte array
for (i = 0; i < DATA_ARRAY_SIZE; i++)
{
EEPROM_Data_Array[i] = i;
initIcd();
txIcd(EEPROM_STORAGE_LOCATION + i, EEPROM_Data_Array[i]);
StopTransfer();
I2CEnable(EEPROM_I2C_BUS, FALSE);
} // for i
// Read back & varify data against array
for (i = 0; i < DATA_ARRAY_SIZE; i++)
{
initIcd();
value = rxIcd(EEPROM_STORAGE_LOCATION + i);
if (EEPROM_Data_Array[i] != value)
{
failed = TRUE;
break;
}
StopTransfer();
I2CEnable(EEPROM_I2C_BUS, FALSE);
} // for i
if (failed == FALSE)
{
debugTrace("I2C SUCCESS\r\n");
}
else
{
debugTrace("I2C FAILED %d: %d != %d\r\n", i, value, EEPROM_Data_Array[i]);
}
while(1);
}
// ----------------------------------------------------------------------------