MSP430FR6928: AT24C256 interfacing with MSP430FR6928

Part Number: MSP430FR6928

Tool/software:

hi , I am writing 4 byte to eeprom (AT24C256),But not able to write more than one byte. One byte can write read but more than one byte not able to write. Please refer below code .kindly reply on same

void InitI2C(unsigned char eeprom_i2c_address)
{

UCB1CTLW0 = UCSWRST; // Enable SW reset
UCB1CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
UCB1BRW = 160; // fSCL = SMCLK/160 = ~100kHz
UCB1I2CSA = SLAVE_ADDR; // Slave Address
UCB1CTLW0 &= ~UCSWRST; // Clear SW reset, resume operation
UCB1IE |= UCNACKIE

}

I2C_Mode I2C_Master_ReadReg(unsigned char dev_addr,unsigned char reg_addr,unsigned char count)
{
/* Initialize state machine */
MasterMode = TX_REG_ADDRESS_MODE;
//TransmitRegAddr = reg_addr;
//P4OUT |=(BIT3);
P3OUT |=(BIT0);

TransmitRegAddr_1 = (reg_addr >> 8);//MSB
TransmitRegAddr_2 = (reg_addr & 0xFF); // LSB

RXByteCtr = count;
TXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;

/* Initialize slave address and interrupts */
UCB1I2CSA = dev_addr;
UCB1IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts
UCB1IE &= ~UCRXIE; // Disable RX interrupt
UCB1IE |= UCTXIE; // Enable TX interrupt

UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
__enable_interrupt();
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts

return MasterMode;

}
void CopyArray(unsigned char *source, unsigned char *dest, unsigned char count)
{
unsigned char copyIndex = 0;
for (copyIndex = 0; copyIndex < count; copyIndex++)
{
dest[copyIndex] = source[copyIndex];
}
}


I2C_Mode I2C_Master_WriteReg(unsigned char dev_addr,unsigned int reg_addr, unsigned char *reg_data, unsigned char count)
//I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
{
/* Initialize state machine */
MasterMode = TX_REG_ADDRESS_MODE;
// TransmitRegAddr = reg_addr;
// P4OUT &=~(BIT3);
P3OUT &=~(BIT0);
TransmitRegAddr_1 = (reg_addr >> 8);//MSB
TransmitRegAddr_2 = (reg_addr & 0xFF); // LSB

//Copy register data to TransmitBuffer
// unsigned char dt =88;
// putstr("\nstr");
CopyArray(reg_data,TransmitBuffer,count);

TXByteCtr = count;
RXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;

/* Initialize slave address and interrupts */
UCB1I2CSA = dev_addr;
UCB1IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts
UCB1IE &= ~UCRXIE; // Disable RX interrupt
UCB1IE |= UCTXIE; // Enable TX interrupt

UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
__enable_interrupt();
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts

return MasterMode;
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B1_ISR (void)
#else
#error Compiler not supported!
#endif
//Must read from UCB2RXBUF
{
//putch('B');
unsigned char rx_val = 0;
switch(__even_in_range(UCB1IV, USCI_I2C_UCBIT9IFG))
{
case USCI_NONE: break; // Vector 0: No interrupts
case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG
case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG
break;
case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG
case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG
case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3
case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3
case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2
case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2
case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1
case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1
case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0
rx_val = UCB1RXBUF;
if (RXByteCtr)
{
ReceiveBuffer[ReceiveIndex++] = rx_val;
;
RXByteCtr--;
}

if (RXByteCtr == 1)
{
UCB1CTLW0 |= UCTXSTP;
}
else if (RXByteCtr == 0)
{
UCB1IE &= ~UCRXIE;
MasterMode = IDLE_MODE;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;

case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0

switch (MasterMode)
{
case TX_REG_ADDRESS_MODE:
if(UCB1I2CSA ==0x50)
{
UCB1TXBUF = TransmitRegAddr_1; //0X32 MSB
//UCB1TXBUF = TransmitRegAddr;
MasterMode = TX_LSB_MODE;
}
else
{
UCB1TXBUF = TransmitRegAddr;
if (RXByteCtr)
MasterMode = SWITCH_TO_RX_MODE; // Need to start receiving now
else
MasterMode = TX_DATA_MODE; // Continue to transmision with the data in Transmit Buffer
}
break;
case TX_LSB_MODE:
UCB1TXBUF = TransmitRegAddr_2; //LSB
//UCB1TXBUF = TransmitRegAddr_1; //LSB
if (RXByteCtr)
MasterMode = SWITCH_TO_RX_MODE; // Need to start receiving now
else
MasterMode = TX_DATA_MODE; // Continue to transmision with the data in Transmit Buffer
break;
case SWITCH_TO_RX_MODE:
UCB1IE |= UCRXIE; // Enable RX interrupt
UCB1IE &= ~UCTXIE; // Disable TX interrupt
UCB1CTLW0 &= ~UCTR; // Switch to receiver
MasterMode = RX_DATA_MODE; // State state is to receive data
UCB1CTLW0 |= UCTXSTT; // Send repeated start
if (RXByteCtr == 1)
{
//Must send stop since this is the N-1 byte
while((UCB1CTLW0 & UCTXSTT));
UCB1CTLW0 |= UCTXSTP; // Send stop condition
}
break;

case TX_DATA_MODE:
if (TXByteCtr)
{
UCB1TXBUF = TransmitBuffer[TransmitIndex++]; // data=9
// UCB2CTLW0 |= UCTXSTP;
TXByteCtr--;
}
else
{
//Done with transmission
UCB1CTLW0 |= UCTXSTP; // Send stop condition
MasterMode = IDLE_MODE;
UCB1IE &= ~UCTXIE; // disable TX interrupt
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;

default:
__no_operation();
break;
}
break;
default: break;
}
}

  • If you have logic analyzer it will better to put signals here, like Saeae, that will be easy to identify the issue 

  • I don't speak register, but if you are using 4 wire mode, the CS line gets toggled for each byte. This may cancel the transaction on the EEPROM side. You may need to use 3 wire mode and control a GPIO for CS manually.

  • It looks to me that, if you read exactly 1 byte, you won't issue a Stop (UCTXSTP) and the bus will hang. Otherwise I don't see anything obviously wrong. [It would be easier to read if you used Insert->Code]

    I don't see your main() program here.

    How do you tell that writing more than 1 byte fails? NACK? Read-back mismatch? Breakpoint? Oscilloscope?

    The usual things that people trip over:

    1) Using Page Write, the EEPROM address matters, since you can only write within a single (64-byte) page. [Ref DOC0670 p. 10]. (In case you're wondering, Byte Write is just a 1-byte Page Write; the description is simpler since it can't cross a page boundary.)

    2) After any Write operation, you need to wait Twr=5ms [Ref Table 4] before talking to the device again. In the meantime the device will NACK.

  • int main(void)

    {

    unsigned int guiDigit1=0,guiDigit2=0;

    unsigned long data =0;

    I2C_Master_WriteReg(0x50, 0x05,5555,4);
    __delay_cycles(1000);


    I2C_Master_ReadReg(0x50,Address,1);
    __delay_cycles(500);
    guiDigit1=(unsigned int)((unsigned int)(ReceiveBuffer[1]<<8)|ReceiveBuffer[0]);

    guiDigit2=(unsigned int)(((ReceiveBuffer[3]<<8)|ReceiveBuffer[2]));

     data  = ((unsigned long)(((unsigned long)((unsigned long)guiDigit2<<8)<<8)|guiDigit1));

    return 0;

    }

  • 1) I don't see where you call InitI2C()

    2) Sooner or later you need to do a "PM5CTL0 &= ~LOCKLPM5;"

    3) A 1000-cycle delay (at 1MHz) is 1ms, not Twr=5ms.

    4) > I2C_Master_WriteReg(0x50, 0x05,5555,4);

         According to your earlier post, that 5555 is an "unsigned char *", not an integer. I suspect you didn't put anything at address 5555. Maybe you intended something like:

         > unsigned long dat = 5555;

         > I2C_Master_WriteReg(0x50, 0x05,(unsigned char *)&dat,4);

    5) > I2C_Master_ReadReg(0x50,Address,1);

         You're writing 4 bytes but reading back 1. (Also, how is "Address" defined?) Maybe you meant something like:

         > I2C_Master_ReadReg(0x50,Address,4);

    ---

    I'm somewhat surprised that the compiler didn't tell you about (2) and (4) in particular.

**Attention** This is a public forum