您好,I2C驱动程序的头文件中的示例代码是正确的,只演示了使用I2CJMistMraveX(…)和I2CyMistRead,并没有真正考虑EEPROM设备的实际属性。做一个当前地址读,是最简单的处理,只需调用:用POIN唯一的障碍是当从芯片1到芯片2通过不同的I2C从地址时,当写入一个数据块时,只写单个字节是不必要的,使用时间很长,并且在存储器阵列中造成不必要的磨损,但是编写单个字节避免处理页面边界交叉所需的逻辑。这里是一个修改的示例代码,处理一些问题,它是24LC65,它有64字节页:对于24x1026页大小是128字节,因此逻辑应该相应地调整。TE缓冲器,以便在存储数据之前定位内存地址。直接从用户缓冲区传输写入数据将需要一些额外的欺骗。即使驱动程序本身没有阻塞,上面的代码也会等到传输完成。版本的I2C驱动程序在状态代码中有一些不同。代码是已经在另一个线程中发布的一些测试和示例代码的一部分:
* Example test code for EEPROM MCHP24LC65 with I2C interface
* ________
* |o-oo|A0 Vcc|o-----o +
* |o-oo|A1 |o |--o SDA
* |o-oo|A2 SCL|o--+--o SCL
* |o o|Vss SDA|o--| o
* |---|----------------o GND
* A0 = 1
* A1 = 1
* A2 = 0
* A = 0x53
*/
#include "mcc.h"
#include "I2C_Master.h"
#include "MCHP24LC65.h"
// Example code from I2C2.h
#define MCHP24AA512_RETRY_MAX 10 // define the retry count maximum
#define MCHP24LC65_ADDRESS 0x53 /* Actual I2C address. */
#define SLAVE_I2C_GENERIC_RETRY_MAX 10
#ifdef __PIC32MX
#define I2C_DEVICE_TIMEOUT 8000 /* define slave timeout, 4360 ticks/byte during debugging */
#else /* On PIC32MX running 80 MHz, 8000 ticks is 0.2 millisecond, */
#define I2C_DEVICE_TIMEOUT 50 /* a little longer than transfer time for each byte, */
#endif /* when I2C is running 100 kHz, and there are no other traffic causing delays for the driver. */
/* Counting Timeout as test iterations need to scale with processor speed and transfer length. */
#ifdef __PIC32MX
static inline
uint32_t __attribute__(( always_inline, nomips16)) ReadTimer(void)
{
uint32_t count;
asm volatile("mfc0 %0, $9" : "=r"(count));
return(count);
}
#else
/* On chips without Core timer, just increment a counter, or use some other timing resource. */
static inline
uint32_t __attribute__((always_inline, nomips16)) ReadTimer(void)
{
static uint32_t count;
count++;
return(count);
}
#endif
uint8_t MCHP24LC65_Write( uint16_t dataAddress, /* EEPROM Memory address. */
uint8_t *pData, /* Pointer to user data buffer. */
uint16_t nCount) /* Number of bytes to write. */
{
// write to a EEPROM Device
uint16_t slaveDeviceAddress = MCHP24LC65_ADDRESS;
uint16_t counter = 0, icount;
uint8_t i, retryCount;
unsigned int slaveTimeOut;
static uint8_t writeBuffer[18];
volatile static I2C_MESSAGE_STATUS writeStatus = I2C_MESSAGE_PENDING;
while (nCount > 0)
{
icount = nCount; // number of bytes to write
/* For a real EEPROM, it is a bad practice to write single bytes,
* when a block of data is to be Written. */
/* For a real MCHP24LC65, starting address + write_count should be less
* than the next 64 byte boundary 0x003F */
if ((dataAddress + nCount) > (dataAddress | 0x003F))
icount = (dataAddress | 0x003F) - (dataAddress - 1);
/* In this example code, the scratch array is limited at 16 Byte. */
if (icount > 16)
icount = 16;
// Build the write buffer first
// starting address of the EEPROM memory
writeBuffer[0] = (dataAddress >> 8); // high address
writeBuffer[1] = (uint8_t)(dataAddress); // low low address
// data to be written
i = 0;
while (i < icount)
{ writeBuffer[2+i] = *(pData +i);
i++;
}
// Now it is possible that the slave device will be slow.
// As a work around on these slaves, the application can
// retry sending the transaction
retryCount = 0;
while(writeStatus != I2C_ERROR_FAIL)
{ writeStatus = I2C_MESSAGE_START;
slaveTimeOut = ReadTimer(); /* Start time */
// write icount bytes to EEPROM (2 is the number of address bytes.)
I2C1_MasterWrite( writeBuffer,
2 + icount,
slaveDeviceAddress,
&writeStatus);
// wait for the message to be sent or status has changed.
while(writeStatus < I2C_MESSAGE_COMPLETE) // == I2C_MESSAGE_PENDING)
{
/* Timeout is wrong, and PIC is fast, each Byte will use about 100 microsecond * 80 instructions/ microsecond */
/* But EEPROM device that is active, will not acknowledge its address, until internal operation is completed.
* Then Trying to Redo a transfer that is still active, using the same buffer and Status word will only cause more problem. */
/* This is just I2C transfer time, EEPROM internal write time is after message complete. */
if ( ReadTimer() - slaveTimeOut > I2C_DEVICE_TIMEOUT * (1 + 2 + icount))
return (0); /* Timeout expired. */ /* But Timeout here will not cancel task that is already queued. */
}
if (writeStatus == I2C_MESSAGE_COMPLETE)
{ dataAddress += icount;
counter += icount;
pData += icount;
nCount -= icount;
break;
}
slaveTimeOut = ReadTimer(); /* New start time */
if (writeStatus == I2C_MESSAGE_QUEUE_FULL)
{ /* Delay until timeout expire, for other transfer to complete. */
while (ReadTimer() - slaveTimeOut < I2C_DEVICE_TIMEOUT * (1 + 2 + icount));
}
if (writeStatus == I2C_MESSAGE_ADDRESS_NO_ACK ||
writeStatus == I2C_MESSAGE_DATA_NO_ACK)
{
// The device may be busy with internal operation, following
// a previous write. Wait a millisecond before trying again.
while (ReadTimer() - slaveTimeOut < I2C_DEVICE_TIMEOUT * 5);
}
// check for max retry and skip this byte
if (retryCount >= SLAVE_I2C_GENERIC_RETRY_MAX)
return (0);
retryCount++;
}
if (writeStatus == I2C_MESSAGE_FAIL)
{
return (0);
}
}
return counter;
}