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.

MSP430FR5969: I2C to FT24C256A EEPROM wont work

Part Number: MSP430FR5969


Tool/software:

Hello,

I am currently working on writing data on a FT24C256A eeprom using a MSP430FR5969 and I2C protocol. I am using a MSP430FR5969 launchpad and use the P1.6 and P1.7 for my SCL and SDA. 

I have connected the a0, a1 and a2 pins to GND which leads to the address being 1010000 (0x50). When I try and sent data using the write function in my code (code is down below) I keep getting stuck in the second     while (!(UCB0IFG & UCTXIFG)); function which with the research I have done means that the eeprom doesn't send an ACK back. How do I fix this problem?

I also have measured the SCL and SDA lines and came to the observation that there is no block signal on the SCL which I would expect. Also when I measured the SDA line the signal on the line was high and when I sent an startbit (using UCB0CTLW0 |= UCTR + UCTXSTT;) it becomes low.  So my question is, is there anything wrong with my code?

#include <msp430fr5969.h>

#define EEPROM_ADDR 0x50


void i2c_init(void) {
// Zet pinfunctie voor I2C
P1SEL1 |= BIT6 + BIT7;
P1SEL0 &= ~(BIT6 + BIT7);

// Zet eUSCI_B0 in reset
UCB0CTLW0 = UCSWRST;

// Configureer als I2C master
UCB0CTLW0 |= UCMODE_3 + UCMST + UCSYNC + UCSSEL__SMCLK;
UCB0BRW = 160; // SCL = SMCLK / 160 = ~100kHz bij 16 MHz
UCB0I2CSA = EEPROM_ADDR;
UCB0CTLW0 &= ~UCSWRST; // Haal uit reset
}

void i2c_write_byte(unsigned int mem_addr, unsigned char data) {
while (UCB0STATW & UCBBUSY); // Wacht tot bus vrij is
UCB0CTLW0 |= UCTR + UCTXSTT; // Master transmitter, START

while (!(UCB0IFG & UCTXIFG));
UCB0TXBUF = (mem_addr >> 8) & 0xFF;

while (!(UCB0IFG & UCTXIFG));
UCB0TXBUF = mem_addr & 0xFF; // Laag byte

while (!(UCB0IFG & UCTXIFG));
UCB0TXBUF = data; // Gegevensbyte

while (!(UCB0IFG & UCTXIFG));
UCB0CTLW0 |= UCTXSTP; // STOP

while (UCB0CTLW0 & UCTXSTP);
}

unsigned char i2c_read_byte(unsigned int mem_addr) {
unsigned char val;

while (UCB0STATW & UCBBUSY);
UCB0CTLW0 |= UCTR + UCTXSTT; // Transmit START

while (!(UCB0IFG & UCTXIFG0));
UCB0TXBUF = mem_addr >> 8;

while (UCB0IFG & UCTXIFG0);
UCB0TXBUF = mem_addr & 0xFF;

while (UCB0IFG & UCTXIFG0);
UCB0CTLW0 &= ~UCTR; // Switch naar receive
UCB0CTLW0 |= UCTXSTT; // Repeated START

while (UCB0CTLW0 & UCTXSTT); // Wacht tot START klaar
UCB0CTLW0 |= UCTXSTP;

val = UCB0RXBUF;

return val;
}

int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop de watchdog timer
PM5CTL0 &= ~LOCKLPM5; // Zet GPIO pins actief (voor FRAM-specific)

// Zet P1.3, P1.4, P1.5 en P3.0 als output en trek ze laag
P1DIR |= BIT3 | BIT4 | BIT5; // Output
P1OUT &= ~(BIT3 | BIT4 | BIT5); // Zet omlaag

P3DIR |= BIT0;
P3OUT &= ~BIT0;

// Zet P4.3 als output en trek die omhoog
P4DIR |= BIT3;
P4OUT |= BIT3;

i2c_init(); // Initialiseer I2C
// __delay_cycles(160000); // EEPROM warm-up tijd
//
// // Schrijf een byte naar de EEPROM op geheugenadres 0x00
// StartStopTest(0x00);

__delay_cycles(320000); // EEPROM warm-up tijd

// Schrijf een byte naar de EEPROM op geheugenadres 0x00
i2c_write_byte(0x50, 0x42);

__delay_cycles(320000); // Wacht even voor de EEPROM om te schrijven

// Lees de byte terug van geheugenadres 0x00
unsigned char val = i2c_read_byte(0x0000);

// Stop de uitvoering, gebruik een breakpoint hier om 'val' te bekijken
while (1);

}

  • A hang at the second UCTXIFG check in i2c_write_byte is consistent with getting a NACK. Do you see UCB0IFG:UCNACKIFG=1 if you pause in the debugger?

    -----------

    Are you fairly certain it's i2c_write_byte() and not i2c_read_byte() that's hanging?

    I'm asking since I see this (twice) in i2c_read_byte():

    while (UCB0IFG & UCTXIFG0);

    which should be:

    > while (!(UCB0IFG & UCTXIFG0));

    like the others.

    ----------

    I'm not quite sure what you mean by "there is no block signal on the SCL". Are you referring to clock stretching?

  • I have checked the UCB0IFG:UCNACKIFG and that does equal to 1. 
    Yes I am sure it is the i2c_write_byte() because i used break points to determine where the program gets stuck and it is in i2c_write_byte(). 
    I have tried some things in the i2c_read_byte() and it does run through which should not happen right?

  • Yes sorry. With the block signal on the SCL i mean that the clock pulls it from high to low and from low to high. when i measured it it just stayed high

  • The NACK (along with the apparent lack of activity on SCL) suggests something more basic. The PSEL settings look correct. I (personally) would take one more look to make sure that the EEPROM device is powered, that A0-A2 and the pullup resistors are tightly connected, and that I didn't inadvertently reverse SDA/SCL. 

    It sounds like you have a scope trace. Is that something you can post?

    -------------

    The first UCTXIFG appears very quickly after the STT; subsequent UCTXIFGs are paced according to the SCL speed. The positive tests (while(UCTXIFG))  in the read function would probably happen before TXIFG asserts again, and so wouldn't spin at all. This is particularly true since your I2C clock is so slow.

    -------------

    Speaking of which: With BRW=160, your I2C clock is (1MHz/160)=6.25kHz, which is pretty slow. I2C doesn't mandate a minimum clock speed, and the data sheet (DS24C256-A2) doesn't specify one. All the same, you might want to set e.g. BRW=10 (100kHz); I suggest this only since I hadn't ever heard of this manufacturer/device before about an hour ago, and one wonders whether minimum-clock is a corner-case they don't test.

    -------------

    Unsolicited: It looks like you're writing EEPROM location 0x50, but reading location 0x00. It sounds like you haven't run into this discrepancy yet, but I imagine you will eventually.

  • Hi Sytze,
    I second the recommendation of making the clock to be 100KHz since that's the minimum that we recommend for I2C communication.

    Best Regards,

    Diego Abad

  • I have looked at all the connections en found out that I have put the A0, A1, A2, WP to high. Which was a problem, so now I have put them to GND and I have checked the rest of the connections and everything should be connected right. SDA and SCL are connected correctly as well.

    I have also set the BRW = 10. I have read somewhere that the SMCLK was 16MHz but I could be wrong, thats why it was 160. I have changed everything according to your suggestions. 

    I could show you a picture of the scope except it only shows SDA being high and SCL being high. When i send the startbit the SDA line is low and the SCL is still high. So I think it has to do with not receiving the acknowledgement, but i dont know how to fix this problem.

  • I have rewired the SCL and SDA line and for some reason it all works now. Thanks for the help!!

  • I'm glad you got it working.

    In the meantime I tried your code with a CAT24C512 and noticed that I needed to add:

    >  UCB0IFG &= ~(UCRXIFG | UCTXIFG);

    at the beginning of the read and write functions. The symptom was an incorrect readback due to the stale IFGs.

**Attention** This is a public forum