Tool/software:
I am currently using the TMS320F28P65DK9 and connecting to an EEPROM (24LC256) through I2C. I am facing an issue with writing and reading data.
I have attached the i2c_driver_lib.c and i2c_driver.c files for your reference.
I have configured the slave address as 0x50.
Write Sequence:
-
START
-
[0xA0]→ EEPROM 7-bit address (0x50) << 1 + Write bit (0) = 0xA0 -
[0x00]→ High byte ofControlAddr(0x0000 >> 8) -
[0x00]→ Low byte ofControlAddr(0x0000 & 0xFF) -
[0x46]→ Data byte (value 70) -
STOP
Read Sequence:
-
START
-
[0xA0]→ Write mode -
[0x00] -
[0x00] -
REPEATED START
-
[0xA1]→ Read mode -
READ BYTE
-
STOP
Please guide me to resolve the above issue and tell me where I made the mistake.
#include <stdio.h>
#include "driverlib.h"
#include "device.h"
#include "libs/i2c/i2c_driver_lib.h"
#include "libs/i2c/i2c_driver.h"
#define EEPROM_ADDR 0x50 // 7-bit EEPROM I2C address
#define MAX_BUFFER_SIZE 32
#define I2C_SUCCESS 0
int i2c_init()
{
uint16_t AvailableI2C_slaves[20];
// Configure GPIOs for I2CB (SDA on GPIO34, SCL on GPIO35)
GPIO_setDirectionMode(34, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(34, GPIO_PIN_TYPE_PULLUP);
GPIO_setQualificationMode(34, GPIO_QUAL_ASYNC);
GPIO_setPinConfig(GPIO_34_I2CB_SDA);
GPIO_setDirectionMode(35, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(35, GPIO_PIN_TYPE_PULLUP);
GPIO_setQualificationMode(35, GPIO_QUAL_ASYNC);
GPIO_setPinConfig(GPIO_35_I2CB_SCL);
// I2C Module Initialization
I2C_disableModule(I2CB_BASE);
I2C_initController(I2CB_BASE, DEVICE_SYSCLK_FREQ, 100000, I2C_DUTYCYCLE_50);
I2C_setConfig(I2CB_BASE, I2C_CONTROLLER_SEND_MODE);
I2C_disableLoopback(I2CB_BASE);
I2C_setBitCount(I2CB_BASE, I2C_BITCOUNT_8);
I2C_setAddressMode(I2CB_BASE, I2C_ADDR_MODE_7BITS);
I2C_enableFIFO(I2CB_BASE);
I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_ARB_LOST | I2C_INT_NO_ACK);
I2C_setFIFOInterruptLevel(I2CB_BASE, I2C_FIFO_TXEMPTY, I2C_FIFO_RX2);
I2C_enableInterrupt(I2CB_BASE, I2C_INT_ARB_LOST | I2C_INT_NO_ACK | I2C_INT_STOP_CONDITION);
I2C_setEmulationMode(I2CB_BASE, I2C_EMULATION_FREE_RUN);
I2C_enableModule(I2CB_BASE);
// Scan and print found devices
uint16_t status = I2CBusScan(I2CB_BASE, AvailableI2C_slaves);
uart_printf("AIN Initialization Successful\r\n");
uart_printf("[I2C INIT] Found devices:");
int i;
for (i= 0; i < 6; i++) {
uart_printf(" %02x", AvailableI2C_slaves[i]);
}
uart_printf("\r\n");
return status;
}
int write_eeprom()
{
uart_printf("[EEPROM WRITE] Initializing I2C...\r\n");
uint16_t TX_MsgBuffer[MAX_BUFFER_SIZE] = {0};
uint32_t ControlAddr = 0x0000;
uint16_t status;
struct I2CHandle EEPROM = {
.SlaveAddr = EEPROM_ADDR,
.base = I2CB_BASE,
.pControlAddr = &ControlAddr,
.NumOfAddrBytes = 2,
.pTX_MsgBuffer = TX_MsgBuffer,
.NumOfDataBytes = 1,
.NumOfAttempts = 5,
.Delay_us = 10,
.WriteCycleTime_in_us = 10000 // EEPROM write cycle time
};
TX_MsgBuffer[0] = 70;
uart_printf("[EEPROM WRITE] Writing value: %d to EEPROM address: 0x%04X\r\n",
TX_MsgBuffer[0], ControlAddr);
status = I2C_MasterTransmitter(&EEPROM);
if (status == I2C_SUCCESS) {
uart_printf("[EEPROM WRITE] Write successful.\r\n");
} else {
uart_printf("[EEPROM WRITE] Write failed. Status = %d (0x%X)\r\n", status, status);
uart_printf("[EEPROM WRITE] I2C getStatus = 0x%X\r\n", I2C_getStatus(I2CB_BASE));
}
DEVICE_DELAY_US(EEPROM.WriteCycleTime_in_us);
uart_printf("[EEPROM WRITE] EEPROM write delay complete.\r\n");
return status;
}
int read_eeprom()
{
uart_printf("[EEPROM READ] Initializing I2C...\r\n");
uint16_t RX_MsgBuffer[MAX_BUFFER_SIZE] = {0};
uint32_t ControlAddr = 0x0000;
uint16_t status;
struct I2CHandle EEPROM = {
.SlaveAddr = EEPROM_ADDR,
.base = I2CB_BASE,
.pControlAddr = &ControlAddr,
.NumOfAddrBytes = 2,
.pRX_MsgBuffer = RX_MsgBuffer,
.NumOfDataBytes = 1,
.NumOfAttempts = 5,
.Delay_us = 10,
.WriteCycleTime_in_us = 10000
};
uart_printf("[EEPROM READ] Reading from EEPROM address: 0x%04X\r\n", ControlAddr);
status = I2C_MasterReceiver(&EEPROM);
if (status == I2C_SUCCESS) {
uart_printf("[EEPROM READ] Read successful.\r\n");
uart_printf("[EEPROM READ] Received data: %d from EEPROM address: 0x%04X\r\n",
RX_MsgBuffer[0], ControlAddr);
} else {
uart_printf("[EEPROM READ] Read failed. Status = %d (0x%X)\r\n", status, status);
uart_printf("[EEPROM READ] I2C getStatus = 0x%X\r\n", I2C_getStatus(I2CB_BASE));
}
while (I2C_getStatus(I2CB_BASE) & I2C_STS_BUS_BUSY);
uart_printf("[EEPROM READ] Read complete.\r\n");
return status;
}
void pass(void)
{
asm(" ESTOP0");
for (;;);
}
void fail(void)
{
asm(" ESTOP0");
for (;;);
}#include <stdio.h>
#include "driverlib.h"
#include "device.h"
#include "libs/i2c/i2c_driver.h"
#include "drivers_internal/uart/uart_driver.h"
uint16_t I2CBusScan(uint32_t base, uint16_t *pAvailableI2C_slaves)
{
uint16_t status;
uint16_t probeSlaveAddress, i;
//Disable interrupts on Stop condition, NACK and arbitration lost condition
I2C_disableInterrupt(base, (I2C_INT_ADDR_TARGET|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK));
i = 0;
for(probeSlaveAddress=1;probeSlaveAddress<=MAX_10_BIT_ADDRESS;probeSlaveAddress++)
{
//Check I2C bus status
status = checkBusStatus(base);
if(status)
{
ESTOP0;
return status;
}
I2C_setConfig(base, (I2C_CONTROLLER_SEND_MODE | I2C_REPEAT_MODE));
//Enable 10-bit addressing if probeSlaveAddress is greater than 127U
if(probeSlaveAddress > MAX_7_BIT_ADDRESS)
{
//10-bit addressing
I2C_setAddressMode(base, I2C_ADDR_MODE_10BITS);
}
// Setup slave address
I2C_setTargetAddress(base, probeSlaveAddress);
I2C_sendStartCondition(base);
//Wait for the slave address to be transmitted
while(!(I2C_getStatus(base) & I2C_STS_REG_ACCESS_RDY));
//Generate STOP condition
I2C_sendStopCondition(base);
//Wait for the I2CMDR.STP to be cleared
while(I2C_getStopConditionStatus(base));
//Wait for the Bus busy bit to be cleared
while(I2C_isBusBusy(base));
uint16_t I2CStatus = I2C_getStatus(base);
//If Slave address is acknowledged, store slave address
//in pAvailableI2C_slaves
if(!(I2CStatus & I2C_STS_NO_ACK))
{
pAvailableI2C_slaves[i++] = probeSlaveAddress;
}
//Clear NACK bit in I2CSTR
I2C_clearStatus(base,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION);
}
I2C_setConfig(base, (I2C_CONTROLLER_SEND_MODE));
I2C_setAddressMode(base, I2C_ADDR_MODE_7BITS); //7-bit addressing
I2C_enableInterrupt(base, (I2C_INT_ADDR_TARGET|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK));
return SUCCESS;
}
uint16_t I2C_TransmitSlaveAddress_ControlBytes(struct I2CHandle *I2C_Params)
{
uint16_t status, attemptCount=1;
uint32_t base = I2C_Params->base;
status = 1;
while(status & (attemptCount <= I2C_Params->NumOfAttempts))
{
status = checkBusStatus(base);
attemptCount++;
DEVICE_DELAY_US(I2C_Params->Delay_us);
}
if(status)
{
return status;
}
I2C_setConfig(base, (I2C_CONTROLLER_SEND_MODE|I2C_REPEAT_MODE));
if((I2C_Params->SlaveAddr) > MAX_7_BIT_ADDRESS)
{
//10-bit addressing
I2C_setAddressMode(base, I2C_ADDR_MODE_10BITS);
}
}
// Setup slave address
//I2C_setSlaveAddress(base, I2C_Params->SlaveAddr);
//I2C_setTargetAddress(base, 2C_Params->SlaveAddr)
int I2C_setSlaveAddress(uint32_t base,uint16_t SlaveAddr) {
// int attemptCount = 0;
// int i;
// uint32_t temp = *(I2C_Params->pControlAddr);
//
// for(i=I2C_Params->NumOfAddrBytes-1;i>=0;i--)
// {
// I2C_putData(base, (temp >> (i*8U)) & 0xFF);
// }
//
// I2C_sendStartCondition(base);
//
// DEVICE_DELAY_US(150U);
//
// status = handleNACK(base);
// if(status)
// {
// if(attemptCount <= (I2C_Params->NumOfAttempts))
// {
// attemptCount++;
// I2C_setConfig(base, (I2C_CONTROLLER_SEND_MODE));
// I2C_sendStartCondition(base);
// DEVICE_DELAY_US(I2C_Params->Delay_us);
// }
// else
// {
// return status;
// }
// }
//
// attemptCount = 1;
//
// while(I2C_getTxFIFOStatus(base) && attemptCount <= 9 * (I2C_Params->NumOfAddrBytes + 2U))
// {
// status = handleNACK(base);
// if(status)
// {
// return status;
// }
// attemptCount++;
// DEVICE_DELAY_US(I2C_Params->Delay_us);
// }
//
// return 0;
}
uint16_t I2C_MasterTransmitter(struct I2CHandle *I2C_Params)
{
uint16_t status, attemptCount;
uint32_t base = I2C_Params->base;
uart_printf("[I2C TX] Starting transmission\r\n");
I2C_disableFIFO(base);
I2C_enableFIFO(base);
status = I2C_TransmitSlaveAddress_ControlBytes(I2C_Params);
uart_printf("[I2C TX] Transmit control bytes status = 0x%X\r\n", status);
if(status) return status;
I2C_setDataCount(base, (I2C_Params->NumOfAddrBytes + I2C_Params->NumOfDataBytes));
I2C_setFIFOInterruptLevel(base, I2C_FIFO_TXEMPTY, I2C_FIFO_RXFULL);
I2C_enableInterrupt(base, I2C_INT_TXFF);
uint16_t numofSixteenByte = (I2C_Params->NumOfDataBytes) / I2C_FIFO_LEVEL;
uint16_t remainingBytes = (I2C_Params->NumOfDataBytes) % I2C_FIFO_LEVEL;
uint16_t i, count = 0, buff_pos = 0;
while(count < numofSixteenByte)
{
for(i = 1; i <= I2C_FIFO_LEVEL; i++)
{
I2C_putData(base, I2C_Params->pTX_MsgBuffer[buff_pos++]);
}
attemptCount = 1;
while(I2C_getTxFIFOStatus(base) && attemptCount <= 9 * (I2C_FIFO_LEVEL + 2U))
{
status = handleNACK(base);
if(status)
{
uart_printf("[I2C TX] NACK received during burst write. Status = 0x%X\r\n", status);
return status;
}
attemptCount++;
DEVICE_DELAY_US(I2C_Params->Delay_us);
}
count++;
}
for(i = 0; i < remainingBytes; i++)
{
I2C_putData(base, I2C_Params->pTX_MsgBuffer[buff_pos++]);
}
attemptCount = 1;
while(I2C_getTxFIFOStatus(base) && attemptCount <= 9 * (remainingBytes + 2U))
{
status = handleNACK(base);
if(status)
{
uart_printf("[I2C TX] NACK received during remaining byte write. Status = 0x%X\r\n", status);
return status;
}
attemptCount++;
DEVICE_DELAY_US(I2C_Params->Delay_us);
}
I2C_sendStopCondition(base);
attemptCount = 1;
while(I2C_getStopConditionStatus(base) && attemptCount <= 3U)
{
DEVICE_DELAY_US(I2C_Params->Delay_us);
attemptCount++;
}
uart_printf("[I2C TX] Transmission complete. Status = 0x%X\r\n", SUCCESS);
return SUCCESS;
}
uint16_t I2C_MasterReceiver(struct I2CHandle *I2C_Params)
{
uint16_t status, attemptCount;
uint32_t base = I2C_Params->base;
uart_printf("[I2C RX] Starting reception\r\n");
I2C_disableFIFO(base);
I2C_enableFIFO(base);
status = I2C_TransmitSlaveAddress_ControlBytes(I2C_Params);
uart_printf("[I2C RX] Transmit control bytes status = 0x%X\r\n", status);
if(status) return status;
uint16_t numofSixteenByte = (I2C_Params->NumOfDataBytes) / I2C_FIFO_LEVEL;
uint16_t remainingBytes = (I2C_Params->NumOfDataBytes) % I2C_FIFO_LEVEL;
I2C_setConfig(base, (I2C_CONTROLLER_RECEIVE_MODE | I2C_REPEAT_MODE));
I2C_sendStartCondition(base);
uint16_t i, count = 0, buff_pos = 0;
while(count < numofSixteenByte)
{
status = handleNACK(base);
if(status)
{
uart_printf("[I2C RX] NACK during burst receive. Status = 0x%X\r\n", status);
return status;
}
count++;
attemptCount = 1;
while(!(I2C_getRxFIFOStatus(base) == I2C_FIFO_RXFULL) && attemptCount <= 9 * (I2C_FIFO_RXFULL + 2U))
{
DEVICE_DELAY_US(I2C_Params->Delay_us);
attemptCount++;
}
for(i = 0; i < I2C_FIFO_LEVEL; i++)
{
I2C_Params->pRX_MsgBuffer[buff_pos++] = I2C_getData(base);
}
}
attemptCount = 1;
while(!(I2C_getRxFIFOStatus(base) == remainingBytes) && attemptCount <= 9 * (remainingBytes + 2U))
{
DEVICE_DELAY_US(I2C_Params->Delay_us);
attemptCount++;
}
I2C_sendStopCondition(base);
for(i = 0; i < remainingBytes; i++)
{
I2C_Params->pRX_MsgBuffer[buff_pos++] = I2C_getData(base);
}
status = handleNACK(base);
if(status)
{
uart_printf("[I2C RX] NACK after receive. Status = 0x%X\r\n", status);
return status;
}
I2C_disableFIFO(base);
attemptCount = 1;
while(I2C_getStopConditionStatus(base) && attemptCount <= 3U)
{
DEVICE_DELAY_US(I2C_Params->Delay_us);
attemptCount++;
}
uart_printf("[I2C RX] Reception complete. Status = 0x%X\r\n", SUCCESS);
return SUCCESS;
}
uint16_t checkBusStatus(uint32_t base)
{
if(I2C_isBusBusy(base))
{
return ERROR_BUS_BUSY;
}
if(I2C_getStopConditionStatus(base))
{
return ERROR_STOP_NOT_READY;
}
return SUCCESS;
}
uint16_t handleNACK(uint32_t base)
{
if(I2C_getStatus(base) & I2C_STS_NO_ACK)
{
I2C_clearStatus(base, I2C_STS_NO_ACK);
I2C_sendStopCondition(base);
return ERROR_NACK_RECEIVED;
}
return SUCCESS;
}