This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/MSP430F67791A: F6779 and I2C EEPROM

Part Number: MSP430F67791A
Other Parts Discussed in Thread: MSPDRIVERLIB

Tool/software: TI C/C++ Compiler

hello sir,

              i have written code for EEPROM communication i2c of msp430f67791a, here we haves used EEPROM 24c02c microchip.

i am attaching my code also here i am getting problem in writing the data in EEPROM, because when i read the data using EEPROM i get "0xFF".

please suggest me changes in code for proper write data in EEPROM & read data from EEPROM on given address.

// ============= MAIN.C=========================================

#include "msp430.h"
#include "i2c f67791a.c"


unsigned char read_val[100];
unsigned char write_val[100];
unsigned int address;

int main(void)
{
unsigned int i;
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

InitI2C(0x50); // Initialize I2C module

EEPROM_ByteWrite(0x0000,0x05);
EEPROM_AckPolling(); // Wait for EEPROM write cycle
// completion
EEPROM_ByteWrite(0x0001,0x34);
EEPROM_AckPolling(); // Wait for EEPROM write cycle
// completion
EEPROM_ByteWrite(0x0002,0x56);
EEPROM_AckPolling(); // Wait for EEPROM write cycle
// completion
EEPROM_ByteWrite(0x0003,0x78);
EEPROM_AckPolling(); // Wait for EEPROM write cycle
// completion
EEPROM_ByteWrite(0x0004,0x9A);
EEPROM_AckPolling(); // Wait for EEPROM write cycle
// completion
EEPROM_ByteWrite(0x0005,0xBC);
EEPROM_AckPolling(); // Wait for EEPROM write cycle
// completion
read_val[0] = EEPROM_RandomRead(0x0000); // Read from address 0x0000
read_val[1] = EEPROM_CurrentAddressRead(); // Read from address 0x0001
read_val[2] = EEPROM_CurrentAddressRead(); // Read from address 0x0002
read_val[3] = EEPROM_CurrentAddressRead(); // Read from address 0x0003
read_val[4] = EEPROM_CurrentAddressRead(); // Read from address 0x0004
read_val[5] = EEPROM_CurrentAddressRead(); // Read from address 0x0005

// Fill write_val array with counter values
for(i = 0 ; i <= sizeof(write_val) ; i++)
{
write_val[i] = i;
}

address = 0x0000; // Set starting address at 0

// Write a sequence of data array
EEPROM_PageWrite(address , write_val , sizeof(write_val));

// Read out a sequence of data from EEPROM
EEPROM_SequentialRead(address, read_val , sizeof(read_val));

__bis_SR_register(GIE);

__no_operation();

}

//====================== i2c f67791a.c================================//

#include "msp430f67791a.h"
#include "I2Croutines.h"

#define MAXPAGEWRITE 64

int PtrTransmit;
unsigned char I2CBufferArray[66];
unsigned char I2CBuffer;

/*----------------------------------------------------------------------------*/
// Description:
// Initialization of the I2C Module
/*----------------------------------------------------------------------------*/
void InitI2C(unsigned char eeprom_i2c_address)
{
I2C_PORT_DIR |= SDA_PIN + SCL_PIN;
I2C_PORT_SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0

// Recommended initialisation steps of I2C module as shown in User Guide:
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTLW0 |= UCMST + UCMODE_3 + UCSYNC + UCSSEL_2; // I2C Master, synchronous mode
//UCB0CTL1 = UCSSEL_2 + UCTR + UCSWRST; // Use SMCLK, TX mode, keep SW reset
UCB0BRW_L = 12; // fSCL = SMCLK/12 = ~100kHz
UCB0BRW_H = 0;
UCB0I2CSA = eeprom_i2c_address; // define Slave Address
// In this case the Slave Address
// defines the control byte that is
// sent to the EEPROM.
//UCB0I2COA = 0x01A5; // own address.
// UCB0IE|=UCTXIE+UCRXIE;
UCB0CTLW0 &= ~UCSWRST; // Clear SW reset, resume operation

if (UCB0STAT & UCBBUSY) // test if bus to be free
{ // otherwise a manual Clock on is
// generated
I2C_PORT_SEL &= ~SCL_PIN; // Select Port function for SCL
I2C_PORT_OUT &= ~SCL_PIN; //
I2C_PORT_DIR |= SCL_PIN; // drive SCL low
I2C_PORT_SEL |= SDA_PIN + SCL_PIN; // select module function for the
// used I2C pins
};
__enable_interrupt();
}

/*---------------------------------------------------------------------------*/
// Description:
// Initialization of the I2C Module for Write operation.
/*---------------------------------------------------------------------------*/
void I2CWriteInit(void)
{
UCB0CTLW0 |= UCTR; // UCTR=1 => Transmit Mode (R/W bit = 0)
UCB0IFG &= ~UCTXIFG;
UCB0IE &= ~UCRXIE0; // disable Receive ready interrupt
UCB0IE|= UCTXIE0; // enable Transmit ready interrupt
}

/*----------------------------------------------------------------------------*/
// Description:
// Initialization of the I2C Module for Read operation.
/*----------------------------------------------------------------------------*/
void I2CReadInit(void)
{
UCB0CTLW0 &= ~UCTR; // UCTR=0 => Receive Mode (R/W bit = 1)
UCB0IFG |= UCRXIFG;
//UCB0IE &= ~UCTXIE0; // disable Transmit ready interrupt
UCB0IE |= UCRXIE0; // enable Receive ready interrupt
}

/*----------------------------------------------------------------------------*/
// Description:
// Byte Write Operation. The communication via the I2C bus with an EEPROM
// (2465) is realized. A data byte is written into a user defined address.
/*----------------------------------------------------------------------------*/
void EEPROM_ByteWrite(unsigned int Address, unsigned char Data)
{
unsigned char adr_hi;
unsigned char adr_lo;

while (UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations.

adr_hi = Address >> 8; // calculate high byte
adr_lo = Address & 0xFF; // and low byte of address

I2CBufferArray[2] = adr_hi; // Low byte address.
I2CBufferArray[1] = adr_lo; // High byte address.
I2CBufferArray[0] = Data;
PtrTransmit = 2; // set I2CBufferArray Pointer

I2CWriteInit();
UCB0CTLW0 |= UCTXSTT; // start condition generation
// => I2C communication is started
// __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
while (UCB0CTLW0 & UCTXSTP) ; // Ensure stop condition got sent

}

/*----------------------------------------------------------------------------*/
// Description:
// Page Write Operation. The communication via the I2C bus with an EEPROM
// (24xx65) is realized. A data byte is written into a user defined address.
/*----------------------------------------------------------------------------*/
void EEPROM_PageWrite(unsigned int StartAddress, unsigned char * Data, unsigned char Size)
{
volatile unsigned int i = 0;
volatile unsigned char counterI2cBuffer;
unsigned char adr_hi;
unsigned char adr_lo;
unsigned int currentAddress = StartAddress;
unsigned char currentSize = Size;
unsigned char bufferPtr = 0;
unsigned char moreDataToRead = 1;

while (UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations.

// Execute until no more data in Data buffer
while(moreDataToRead)
{
adr_hi = currentAddress >> 8; // calculate high byte
adr_lo = currentAddress & 0xFF; // and low byte of address

// Chop data down to 64-byte packets to be transmitted at a time
// Maintain pointer of current startaddress
if(currentSize > MAXPAGEWRITE)
{
bufferPtr = bufferPtr + MAXPAGEWRITE;
counterI2cBuffer = MAXPAGEWRITE - 1;
PtrTransmit = MAXPAGEWRITE + 1; // set I2CBufferArray Pointer
currentSize = currentSize - MAXPAGEWRITE;
currentAddress = currentAddress + MAXPAGEWRITE;

// Get start address
I2CBufferArray[MAXPAGEWRITE + 1] = adr_hi; // High byte address.
I2CBufferArray[MAXPAGEWRITE] = adr_lo; // Low byte address.
}
else
{
bufferPtr = bufferPtr + currentSize;
counterI2cBuffer = currentSize - 1;
PtrTransmit = currentSize + 1; // set I2CBufferArray Pointer.
moreDataToRead = 0;
currentAddress = currentAddress + currentSize;

// Get start address
I2CBufferArray[currentSize + 1] = adr_hi; // High byte address.
I2CBufferArray[currentSize] = adr_lo; // Low byte address.
}

// Copy data to I2CBufferArray
unsigned char temp;
for(i ; i < bufferPtr ; i++)
{
temp = Data[i]; // Required or else IAR throws a
// warning [Pa082]
I2CBufferArray[counterI2cBuffer] = temp;
counterI2cBuffer--;
}

I2CWriteInit();
UCB0CTLW0 |= UCTXSTT; // start condition generation
// => I2C communication is started
// __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent

EEPROM_AckPolling(); // Ensure data is written in EEPROM
}
}

/*----------------------------------------------------------------------------*/
// Description:
// Current Address Read Operation. Data is read from the EEPROM. The current
// address from the EEPROM is used.
/*----------------------------------------------------------------------------*/
unsigned char EEPROM_CurrentAddressRead(void)
{
while(UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations
I2CReadInit();

UCB0CTLW0 |= UCTXSTT; // I2C start condition
while(UCB0CTLW0 & UCTXSTT); // Start condition sent?
UCB0CTLW0 |= UCTXSTP; // I2C stop condition
//__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
return I2CBuffer;
}

/*----------------------------------------------------------------------------*/
// Description:
// Random Read Operation. Data is read from the EEPROM. The EEPROM
// address is defined with the parameter Address.
/*----------------------------------------------------------------------------*/
unsigned char EEPROM_RandomRead(unsigned int Address)
{
unsigned char adr_hi;
unsigned char adr_lo;

while (UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations

adr_hi = Address >> 8; // calculate high byte
adr_lo = Address & 0xFF; // and low byte of address

I2CBufferArray[1] = adr_hi; // store single bytes that have to
I2CBufferArray[0] = adr_lo; // be sent in the I2CBuffer.
PtrTransmit = 1; // set I2CBufferArray Pointer

// Write Address first
I2CWriteInit();
UCB0CTLW0 |= UCTXSTT; // start condition generation
// => I2C communication is started
//__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent

// Read Data byte
I2CReadInit();

UCB0CTLW0 |= UCTXSTT; // I2C start condition
while(UCB0CTLW0 & UCTXSTT); // Start condition sent?
UCB0CTLW0 |= UCTXSTP; // I2C stop condition
//__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
return I2CBuffer;
}

/*----------------------------------------------------------------------------*/
// Description:
// Sequential Read Operation. Data is read from the EEPROM in a sequential
// form from the parameter address as a starting point. Specify the size to
// be read and populate to a Data buffer.
/*----------------------------------------------------------------------------*/
void EEPROM_SequentialRead(unsigned int Address , unsigned char * Data , unsigned int Size)
{
unsigned char adr_hi;
unsigned char adr_lo;
unsigned int counterSize;

while (UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations

adr_hi = Address >> 8; // calculate high byte
adr_lo = Address & 0xFF; // and low byte of address

I2CBufferArray[1] = adr_hi; // store single bytes that have to
I2CBufferArray[0] = adr_lo; // be sent in the I2CBuffer.
PtrTransmit = 1; // set I2CBufferArray Pointer

// Write Address first
I2CWriteInit();
UCB0CTLW0 |= UCTXSTT; // start condition generation
// => I2C communication is started
//__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent

// Read Data byte
I2CReadInit();

UCB0CTLW0 |= UCTXSTT; // I2C start condition
while(UCB0CTLW0 & UCTXSTT); // Start condition sent?

for(counterSize = 0 ; counterSize < Size ; counterSize++)
{
//__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
Data[counterSize] = I2CBuffer;
}
UCB0CTLW0 |= UCTXSTP; // I2C stop condition
//__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
}

/*----------------------------------------------------------------------------*/
// Description:
// Acknowledge Polling. The EEPROM will not acknowledge if a write cycle is
// in progress. It can be used to determine when a write cycle is completed.
/*----------------------------------------------------------------------------*/
void EEPROM_AckPolling(void)
{
while (UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations
do
{
UCB0STAT = 0x00; // clear I2C interrupt flags
UCB0CTLW0 |= UCTR; // I2CTRX=1 => Transmit Mode (R/W bit = 0)
UCB0CTLW0 &= ~UCTXSTT;
UCB0CTLW0 |= UCTXSTT; // start condition is generated
while(UCB0CTLW0 & UCTXSTT) // wait till I2CSTT bit was cleared
{
if(!(UCNACKIFG & UCB0STAT)) // Break out if ACK received
break;
}
UCB0CTLW0 |= UCTXSTP; // stop condition is generated after
// slave address was sent => I2C communication is started
while (UCB0CTLW0 & UCTXSTP); // wait till stop bit is reset
__delay_cycles(500); // Software delay
}while(UCNACKIFG & UCB0STAT);
}

/*---------------------------------------------------------------------------*/
/* Interrupt Service Routines */
/* Note that the Compiler version is checked in the following code and */
/* depending of the Compiler Version the correct Interrupt Service */
/* Routine definition is used. */
//#if __VER__ < 200
// interrupt [USCIAB0TX_VECTOR] void TX_ISR_I2C(void)
//#else
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
//#endif
{
if(UCTXIFG & UCB0IFG)
{
UCB0TXBUF = I2CBufferArray[PtrTransmit];// Load TX buffer
PtrTransmit--; // Decrement TX byte counter
if(PtrTransmit < 0)
{
while(!(UCB0IFG & UCTXIFG));
UCB0CTLW0 |= UCTXSTP; // I2C stop condition
UCB0IE &= ~UCTXIE0; // disable interrupts.
UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
// __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
}
}
else if(UCRXIFG & UCB0IFG)
{
I2CBuffer = UCB0RXBUF; // store received data in buffer
//__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
}
}

regards,

kinjal

  • Hello,

    Have you read through Section 5 Common I2C Communication Issues (and the sub-sections in Section 5) in the Solutions to Common eUSCI and USCI Serial Communication Issues on MSP430™ MCUs app note yet? As far as code recommendations, it's very hard to read through your code since you've made your own functions and have lots of commented-out code. I would encourage you to start with our I2C code examples in CCS before trying to make your own functions, etc. We also offer a MSP Driver (MSPDRIVERLIB) with easier-to-use APIs for I2C communication. Have you looked into this library?

    For future reference when you post code, don't post too much code or else the community may not want to spend the time going through it. Also, please use the Syntax Highlighter tool (looks like "</>") found under the "Insert Code, Attach Files and more..." link shown after you click the "Reply" button. It makes the code more readable.

    Regards,

    James

    MSP Customer Applications

**Attention** This is a public forum