I’m working on a project and for part of it I am trying to use the Harmony I2C driver library in order to send data to and from the eeprom using the SDA and SCL lines.
When reading the SDA and SCL lines with an oscilloscope, the correct sequence of bits is passed to the EEPROM, and the EEPROM acks the data. However, when trying to read from the EEPROM, it sends back all 1s. Additionally, when calling the built in I2C function DRV_I2C_BytesTransferred
, it returns 0 bytes for both the read and the write.
I’ve been troubleshooting the past few days, but I can’t seem to find what is causing this.
I'm using the PIC32MZ1024ECM144-I/PL microcontroller and Harmony V2.06 on the MPLAB X IDE. The EEPROM that I’m working with is the M24C02-RMN6TP.
Here is the oscilloscope when writing to the EEPROM:
Here is the oscilloscope when reading from the EEPROM:
Here are the functions for the EEPROM read and write. The call to the eepromWrite
and eepromRead
are called in a separate function not listed here, and there is an added delay between the read and the write function calls.
SYS_MODULE_OBJ objectHandle;
uint8_t deviceAddressSlave;
uint8_t numOfBytes;
uint8_t TXbuffer[32];
/* I2C driver RX Buffer */
uint8_t RXbuffer[32];
DRV_I2C_BUFFER_EVENT APP_Check_Transfer_Status(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle);
uint32_t APP_Number_Of_Bytes_Transferred(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle);
DRV_HANDLE drvI2CMasterHandle; //Returned from DRV_I2C_Open for I2C Master
DRV_I2C_BUFFER_HANDLE bufHandle_M1; //Returned from calling a Data Transfer function
uintptr_t i2cOpStatus; //Operation status of I2C operation returned from callback
DRV_HANDLE drvI2CSlaveHandle; //Returned from DRV_I2C_Open for I2C Slave
DRV_I2C_BUFFER_HANDLE bufHandle_S1; //Returned from calling a Data Transfer function
DRV_I2C_BUFFER_HANDLE bufHandle_S2; //Returned from calling a Data Transfer function
typedef enum {
TxRx_OPEN = 0,
TxRx_TO_EXTERNAL_SLAVE,
TxRx_EXTERNAL_SLAVE_STATUS_CHECK_1,
TxRx_STATUS_CHECK,
TxRx_COMPLETED
} APP_EEPROM_WR_STATES;
static APP_EEPROM_WR_STATES appWriteState = TxRx_OPEN;
DRV_I2C_BUFFER_EVENT Transaction;
bool APP_Write_Tasks(void)
{
switch (appWriteState)
{
case TxRx_OPEN:
{;
/* Open the I2C Driver for Master */
appData.drvI2CHandle_Master = DRV_I2C_Open( DRV_I2C_INDEX_0,
DRV_IO_INTENT_READWRITE );
if(appData.drvI2CHandle_Master != DRV_HANDLE_INVALID)
{
appWriteState = TxRx_TO_EXTERNAL_SLAVE;
}
else
{
appData.state = APP_STATE_ERROR;
}
break;
}
case TxRx_TO_EXTERNAL_SLAVE:
{
/* Number of bytes to transfer */
numOfBytes = 3;
deviceAddressSlave = 0xA0;
if ( (appData.appI2CWriteBufferHandle[0] == DRV_I2C_BUFFER_HANDLE_INVALID) ||
(APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]) == DRV_I2C_BUFFER_EVENT_COMPLETE) ||
(APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]) == DRV_I2C_BUFFER_EVENT_ERROR) )
{
appData.appI2CWriteBufferHandle[0] = DRV_I2C_Transmit (appData.drvI2CHandle_Master,deviceAddressSlave, &TXbuffer[0], numOfBytes, NULL);
}
if (APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]) == DRV_I2C_BUFFER_EVENT_ERROR){
}
appWriteState = TxRx_EXTERNAL_SLAVE_STATUS_CHECK_1;
break;
}
case TxRx_EXTERNAL_SLAVE_STATUS_CHECK_1:
{
Transaction = APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]);
appWriteState =TxRx_STATUS_CHECK;
if ( Transaction == DRV_I2C_BUFFER_EVENT_COMPLETE)
{
appWriteState =TxRx_STATUS_CHECK;
}
else if (Transaction == DRV_I2C_BUFFER_EVENT_ERROR) //Useful for error checking
{
appWriteState =TxRx_STATUS_CHECK;
}
break;
}
case TxRx_STATUS_CHECK:
{
// Only defined for dynamic driver.
#ifdef DRV_I2C_CLIENTS_NUMBER
extern const DRV_I2C_INIT drvI2C0InitData;
DRV_I2C_Close( appData.drvI2CHandle_Master );
DRV_I2C_Deinitialize (sysObj.drvI2C0);
#endif
DelayMs(800);
#ifdef DRV_I2C_CLIENTS_NUMBER
sysObj.drvI2C0 = DRV_I2C_Initialize(DRV_I2C_INDEX_0, (SYS_MODULE_INIT *)&drvI2C0InitData);
#endif
/* to run the application only once,
* set next state to TxRx_COMPLETED */
// appWriteState = TxRx_COMPLETED;
/* to run the application in a continuous loop,
* set next state to TxRx_OPEN */
#ifdef DRV_I2C_CLIENTS_NUMBER
appWriteState = TxRx_COMPLETED;
#else
appWriteState = TxRx_TO_EXTERNAL_SLAVE;
#endif
break;
}
case TxRx_COMPLETED:
{
return true;
break;
}
}
return false;
}
void writeEEPROM(void) {
TXbuffer[0] = 0xF0;
TXbuffer[1] = ((unsigned short)300 >> 8); //1
TXbuffer[2] = (char) 300; //44
while (!APP_Write_Tasks());
DRV_I2C_Close( appData.drvI2CHandle_Master );
}
void readEEPROM(void) {
appData.drvI2CHandle_Master = DRV_I2C_Open( DRV_I2C_INDEX_0, DRV_IO_INTENT_READWRITE );
/*memset(TXbuffer, 0, sizeof TXbuffer); //Used when not calling write function
deviceAddressSlave = 0xA0;
numOfBytes = 3;
TXbuffer[0] = 0xF0;
TXbuffer[1] = ((unsigned short)300 >> 8); //1
TXbuffer[2] = (char) 300; //44*/
appData.appI2CReadBufferHandle[0] = DRV_I2C_TransmitThenReceive(appData.drvI2CHandle_Master, 0xA0, &TXbuffer[0], 1, &RXbuffer, 2, NULL);
DRV_I2C_Close(appData.drvI2CHandle_Master);
}
DRV_I2C_BUFFER_EVENT APP_Check_Transfer_Status(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle)
{
return (DRV_I2C_TransferStatusGet (appData.drvI2CHandle_Master, drvBufferHandle));
}
uint32_t APP_Number_Of_Bytes_Transferred(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle)
{
return (DRV_I2C_BytesTransferred (appData.drvI2CHandle_Master,drvBufferHandle));
}
These are functions are based off the driver example code that comes with Harmony. I have been testing sending the value 300 split into 2 bytes to the EEPROM. However no matter what address I try or what values I send, the EEPROM only every sends back 255, I.E. all bits set to 1. There is write control on the EEPROM that block write, however I have confirmed that the write block is currently disabled.