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.

MSP-EXP430FR5739: I2C @ M24C02-FMN6TP

Part Number: MSP-EXP430FR5739

Hi,

I'm trying to communicate to an EEPROM (M24C02-FMN6TP) using the below code. If I execute this code and observe SDA & SCL with an oscilloscope, I see only one "sequence":

Start Condition - EEPROM Address (0x50) - #WRITE_FLAG - ACK from the EEPROM - 1 Byte (0x66) - ACK from the EEPROM - Stop Condition

Now, the question is NOT why I can see just one sequence, and neither I wonder why it comprises only one single byte. The question is why that byte in the sequence is the data byte (0x66) and not the address (0x05)?

Thanks for any reply.

Christian

#include <msp430.h>
#include <stdint.h>

void init_16_MHz_clock(void)
{
  //Unlock CS registers with CSKEY password.
  CSCTL0 = CSKEY;
  //Set DCOCLK = 16 MHz.
  CSCTL1 &= ~(DCOFSEL1 + DCOFSEL0);
  CSCTL1 |= DCORSEL + DCOFSEL_2;
  //Set ACLK = SMCLK = MCLK = DCOCLK.
  CSCTL2 = SELA_3 + SELS_3 + SELM_3;
  //Set all dividers to 0.
  CSCTL3 = DIVA_0 + DIVS_0 + DIVM_0;

  //Lock CS registers again.
  CSCTL0_H = 0;
}

void hold_watchdog_timer(void) {
  WDTCTL = WDTPW + WDTHOLD;
}

void init_i2c(const uint8_t eeprom_address) {
  P1SEL0 &= ~(0xC0u);
  P1SEL1 |= 0xC0u;

  UCB0CTLW0 |= UCSWRST;
  UCB0CTLW0 &= ~(UCA10 + UCSLA10 + UCMM + UCTXACK + UCTXNACK + UCTXSTP +
    UCTXSTT);
  UCB0CTLW0 |= UCMST + UCMODE_3 + UCSYNC + UCSSEL__SMCLK + UCTR;
  UCB0CTLW1 &= ~(UCETXINT + UCCLTO1 + UCCLTO0 + UCSTPNACK + UCSWACK + UCASTP1 +
    UCASTP0 + UCGLIT1 + UCGLIT0);
  UCB0CTLW1 |= UCASTP_2;
  UCB0BRW = 160;
  UCB0TBCNT = 1;
  UCB0I2COA0 &= ~(UCGCEN + UCOAEN);
  UCB0I2COA1 &= ~(UCOAEN);
  UCB0I2COA2 &= ~(UCOAEN);
  UCB0I2COA3 &= ~(UCOAEN);
  UCB0ADDMASK |= 0x3FFu;
  UCB0CTLW0 &= ~UCSWRST;
  UCB0I2CSA = eeprom_address;

  //Test if the bus is free, otherwise a manual clock on is generated.
  if(UCB0STATW & UCBBUSY) {
    P1SEL1 &= ~0x80;
    P1OUT &= ~0x80;
    P1DIR |= 0x80;
    P1SEL1 |= 0x80;
  }

  UCB0IE = 0; UCB0IFG = 0; UCB0IV |= 0xFFFFu;
}

void eeprom_write(const uint8_t address, const uint8_t data) {
  unsigned short i;

  const uint8_t buffer[2] = {data, address};

  UCB0CTLW0 |= UCTR;
  UCB0IE |= UCTXIE0;
  while(UCB0STATW & UCBBUSY);
  UCB0CTLW0 |= UCTXSTT;
  for(i = 2; i > 0; --i) {
    UCB0TXBUF = buffer[i - 1];
    while(!(UCB0IFG & UCTXIFG0));
  }
  UCB0IE &= ~UCTXIE0;
  UCB0IFG = 0; UCB0IV |= 0xFFFFu;
  while(UCB0STATW & UCTXSTP);
}

uint8_t eeprom_read(const uint16_t address) {
  return 0;
}

int main(void) {
  unsigned short i;

  const uint8_t EEPROM_ADDRESS = 0x50u;

  const uint8_t write_values[6] = {0x11u, 0x22u, 0x33u, 0x44u, 0x55u, 0x66u};
  volatile uint8_t read_values[6] = {0};

  hold_watchdog_timer();

  init_16_MHz_clock();

  init_i2c(EEPROM_ADDRESS);

  //Write values to addresses 0x05..0x00 in the EEPROM.
  for(i = 6; i > 0; --i) {
    eeprom_write(0x00u + i - 1, write_values[i - 1]);
  }

  //Read values from addresses 0x05..0x00 in the EEPROM.
  for(i = 6; i > 0; --i)
    read_values[i - 1] = eeprom_read(0x00u + i - 1);

  return 0;
}

  • >  UCB0TXBUF = buffer[i - 1];
    >  while(!(UCB0IFG & UCTXIFG0));
    Notwithstanding User Guide (SLAU272D) Fig 20-12, I'm pretty sure I've observed a detectable delay between the CPU setting TXSTT=1 and the I2C unit setting UCTXIFG=1. This would cause the first byte (address) to get lost. In any case, you should stick with the general rule that you shouldn't write to TXBUF unless TXIFG=1.

    Specifically: I recommend you reverse the order of these two statements.

    Unsolicited: I recommend you Not set UCTXIE if you're not using interrupts (i.e. you don't have an ISR). It appears you don't enable interrupts globally (GIE) in this program, so it works by accident, but it serves no purpose and will cause trouble when you do decide to enable GIE.

**Attention** This is a public forum