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.

Problem with MSP430 I2C write

Other Parts Discussed in Thread: MSP430F5529

Hi,

Currently I can read data from sensor using I2C protocol, but I cannot write data on sensor. 

Here is my write code:


char UCB0_I2C_write ( unsigned char slave_addr,unsigned char _addr, unsigned char val)

{

    //WAIT FOR PREVIOUS TRAFFIC TO CLEAR

    while ( UCB0STAT & UCBBUSY );

    // LOAD THE DEVICE SLAVE ADDRESS

    UCB0I2CSA = slave_addr;

    // ENABLE TRANSMIT, GENERATE START BIT

    UCB0CTL1 |= UCTR + UCTXSTT;

    // WAIT FOR FIRST INT

    while ( ! ( UCB0IFG & UCTXIFG ) ); // 0000 0010 & 0000 0010 = 0000 0010

    // LOAD THE REGISTER ADDRESS

    UCB0TXBUF = _addr;

    // NOW WAIT FOR START BIT TO COMPLETE

    while ( UCB0CTL1 & UCTXSTT );

    UCB0TXBUF = val;

    while ( UCB0CTL1 & UCTXSTT );

    UCB0CTL1 |= UCTXSTP;

    return 0;

}


And here is my init code:


void I2Cinit()

{

UCB0CTL1 |= UCSWRST;                      // Enable SW reset

UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode

UCB0CTL1 = UCSSEL_2 + UCSWRST + UCTR;     // Use SMCLK, keep SW reset

UCB0BR0 = 11;                             // fSCL = SMCLK/12 = ~100kHz

UCB0BR1 = 0;

//UCB0I2CSA = 0xEE;                         // Slave Address is 048h

UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation

//UCB0IFG = 0x10;

//UCB0IE |= UCRXIE+UCALIE+UCTXIE;           // Enable RX interrupt

}


I'm using MSP430F5529LP. If I'm not mistaken, USCI automatically reads ack, so if I write two data on TXBUF, the first one being register address and the second being data needed to input into the register, the data should be written, but somehow no data can be written. 

Here is how I've tested if data has been written according to my write code:


     UCB0_I2C_read(ITG3200_ADDR_AD0_LOW,0x1A,data12,1);

    __no_operation();

    UCB0_I2C_write(ITG3200_ADDR_AD0_LOW,0x1A,0);

    __no_operation();


I've added two break point in _no_operation();. After reading the data, which happens to be 1, I wrote data 0 into that register. However, after re-reading the register, the data shown is still 1. 

What is the problem here? Any help would be appreciated.

HeeJun Kim

  • Hi,

    Hee Jun Kim said:


    char UCB0_I2C_write ( unsigned char slave_addr,unsigned char _addr, unsigned char val)

    {

        //WAIT FOR PREVIOUS TRAFFIC TO CLEAR

        while ( UCB0STAT & UCBBUSY );

        // LOAD THE DEVICE SLAVE ADDRESS

        UCB0I2CSA = slave_addr;

        // ENABLE TRANSMIT, GENERATE START BIT

        UCB0CTL1 |= UCTR + UCTXSTT;

        // WAIT FOR FIRST INT

        while ( ! ( UCB0IFG & UCTXIFG ) ); // 0000 0010 & 0000 0010 = 0000 0010

        // LOAD THE REGISTER ADDRESS

        UCB0TXBUF = _addr;

        // NOW WAIT FOR START BIT TO COMPLETE

        while ( UCB0CTL1 & UCTXSTT );

        UCB0TXBUF = val;

        while ( UCB0CTL1 & UCTXSTT );

        UCB0CTL1 |= UCTXSTP;

        return 0;

    }

    It is not necessary to manually send out the slave address after setting the UCTXSTT bit of UCBxCTL1 register. This will be done automatically by the USCI module by using the UCBxI2CSA register and the UCTR bit for the R/W bit. This is described in detail in the User's Guide - http://www.ti.com/lit/pdf/slau208 - chapter 36.3.4.2.1 "I2C Master Transmitter Mode".

    I would suggest you also to refer to the example codes of MSP430F5529: http://www.ti.com/lit/zip/slac300

  • The second ‘while (UCB0CTL1&UCTXSTT) ‘ is wrong. It must read “while(!(UCB0IFG&UCTXIFG)).
    You already waited for UCTXSTT clear. It won’t reappear, so the second while is void and you’re setting UCTXSTP while the address is still being sent. This will stop before the value is sent.

    By waiting for UXTXIFG, you ensure that the address was sent and the data has started sending (so TXBUF is empty again), before you set the stop.

    Leo, '_addr' is not the slave address but a register address. So sending it is completely correct.

**Attention** This is a public forum