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.

MSP430G2553 I2C Master=>Slave Communication

Other Parts Discussed in Thread: MSP430G2553

Hi all,

I'm currently working on a project where I need to set a digital potentiometer. After reading the manual and looking over a few other examples. I've come up with the following code.

    //I2C Config
    P1SEL |= BIT6 + BIT7;                                                         // Assign I2C pins to USCI_B0
    P1SEL2|= BIT6 + BIT7;                                                        // Assign I2C pins to USCI_B0
    P1REN |= BIT6+BIT7;                                                          //Enable pull up resistors

    //Set Potentiometers
    UCB0CTL1 = UCSWRST;                                                  //Hold I2C bus during initiation
    UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC;        //sets I2C mode, master mode, synchronous mode
    UCB0CTL1 |= UCSSEL_3;                                                //select SMCLK
    UCB0I2CSA = 0x28;                                                            //slave address
    UCB0CTL1 &= ~UCSWRST;                                             //enable i2c
    UCB0CTL1 |= UCTR + UCTXSTT;                                    //set transmit, generate start
    while(!(UCB0TXIFG)){;}                                                       //wait for transmission to finish
    UCB0TXBUF = 0xAF;                                                           //send command byte
    while(!(UCB0TXIFG)){;}                                                       //wait for transmission to finish
    UCB0TXBUF = 255;                                                             //set pot value
    UCB0CTL1 |= UCTXSTP;                                                   //generate stop condition
    while(!(UCB0TXIFG)){;}                                                       //wait for transmission to finish
    UCB0CTL1 = UCSWRST;                                                  //release I2C bus

Most of what is listed here is from info on the data sheet, found here: http://www.ti.com/lit/ds/symlink/msp430g2553.pdf, and the users guide, found here:http://www.ti.com/lit/ug/slau144i/slau144i.pdf, on pages around 461 and 467.

The data sheet for the digital pot I'm writing to is a DS1803-010: http://datasheets.maxim-ic.com/en/ds/DS1803.pdf

Any help would be greatly appreciated and thank you for your time.

  • I dont know anything about I2C but I am pretty sure ur program never waited for transmission to finish (logical mistake).

    Ryan Wilkerson said:

    while(!(UCB0TXIFG)){;}                                                       //wait for transmission to finish

    This is because UCB0TXIFG has a constant value of 0b1000 and !UCB0TXIFG is 0. Thus the contents of while loop never got executed.

    UCB0TXIFG is actually a constant while IFG2 is varying. You should actually use this

    while (!(IFG2 & UCB0TXIFG)) { ;}

    Good luck

  • UCB0TXIFG is cleared while data in UCB0TXBUF is being pushed to the shift register, it is cleared once the bus is not busy, see pg 471 sec 17.3.4.2.1.

    I tried what you suggested, Raju, but it hung up at the first statement. I believe it is because UCB0TXIFG is in the IFG2 register and that operation would always execute as true.

    Since the last post, I realized that I forgot to append the R/W bit to the slave address. Since I corrected that I got some reaction out of the UCB0TXIFG bit, although strange, and I changed the while statement to be more explicit. The updated code is as follows:

        //I2C Config
        P1SEL |= BIT6 + BIT7;                                                       // Assign I2C pins to USCI_B0
        P1SEL2|= BIT6 + BIT7;                                                      // Assign I2C pins to USCI_B0
        P1REN |= BIT6+BIT7;                                                        //Enable pull up resistors

        //Set Potentiometers
        UCB0CTL1 = UCSWRST;                                                 //Hold I2C bus during initiation
        UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC;       //sets I2C mode, master mode, synchronous mode
        UCB0CTL1 |= UCSSEL_3;                                               //select SMCLK
        UCB0I2CSA = 0x50;                                                          //slave address(0101000) & write bit(0)
        UCB0CTL1 &= ~UCSWRST;                                           //enable i2c
        UCB0CTL1 |= UCTR + UCTXSTT;                                 //set transmit, generate start
        while(UCB0TXIFG==0){;}                                                 //wait for transmission to finish
        UCB0TXBUF = 0xAF;                                                        //send command byte
        while(UCB0TXIFG==0){;}                                                 //wait for transmission to finish
        UCB0TXBUF = 255;                                                          //set pot value
        UCB0CTL1 |= UCTXSTP;                                                //generate stop condition
        while(UCB0TXIFG==0){;}                                                 //wait for transmission to finish
        UCB0CTL1 |= UCSWRST;                                              //release I2C bus

    According to the manual, I get usual response out of the UCB0TXIFG bit until the second while statement. For some reason as I step through, UCB0TXIFG stays 0 at the line 'UCB0YXBUF = 255;'. Additionally, according to the manual, UCTXSTT should be cleared after the slave address is acknowledged, but it stays set throughout the block. This particular problem persisted with the appended slave address.

    Hopefully this provides enough information for a diagnosis.

    -Ryan Wilkerson

  • Hi Ryan,

                I don't know much about the I2C stuff yet , I think you should generate a stop condition before second while loop. From the same section of data sheet you mentioned before,,says, If we were transmitting byte by byte you should generate a stop after every byte. Give a try if u find some thing useful.

    Regards,

    Sri.

  • Ryan Wilkerson said:
    For some reason as I step through, UCB0TXIFG stays 0 at the line 'UCB0YXBUF = 255;'. Additionally, according to the manual, UCTXSTT should be cleared after the slave address is acknowledged, but it stays set throughout the block.

    For UCTXSTT, this seems to indicate that the start sequence hasn't finished yet. This usually happens if there are no pullups on teh clock and data lines. In this case, the master thinks the slave intentionally holds teh clokc line low before answering, btui in fact, the bus is simply stalled.

    This also explains why UCTXIFG noever goes high again. It goes high as soon as you set UCTXSTT, as teh TX buffer is double.buffering and you ma yalready fiill it while the slave hasn't been addressed at all. But since the slave addressing doesn't complete, the ocntent of TXBUF isn't moved to the output and TXBUF is still full - and TXIFG won't raise.

  • Hi all,

    i'm doing i2c interface between msp430g2553 and my accelerometer (ADXL345).

    Currently i'm trying out the multiple read.

    Pin SDO of ADXL345 been tied to logic 1. Therefore the device address is 0x1D. Reset default state is 0xE5 and it should get it back. And i got it right for single-byte read.

    Below is my waveform pic and my main program.

    Please help. many many thanks. :)

    waveform for multiple read but wrong. :(

    Main program for single read.

    #include <stdio.h>

    #include <msp430g2553.h>

    #include "MSP430G2553(AddOn).h"

    #include "GPIO.h"

    #include "UART.h"

    #include "i2c.h"

    #include "ADXL345.h"

    #include "ADXL345(RegMap).h"

    #include "L3G4200D.h"

    #include "L3G4200D(RegMap).h"

    unsigned char readValue;

     

    void main(void) {

    StopWatchDog();

    CalDCO16MHz();

    UARTInit(); //For serial Communication

    // i2cFastModeInit(); //I2C - 400kHz

    i2cInit(); //I2C - 100kHz

    while(1)

    {

    i2c_start(0x1D); //Perform a I2C Start with the Device Address of ADXL345

    i2c_write(0x00); //0x00 register for DEVICE ID (ADXL345 datasheet pg 23)

    delay_us(100);

    i2c_restart(); //Perform a restart; this can also be a stop and follow by a start

    // delay_us(100);

    readValue = i2c_read(); //Perform a read. (Expected value is 0xE5)

    i2c_stop(); //Stop the I2C

    delay_us(300);

    // while(1); /*** SET BREAKPOINT HERE***/

    }

    }

  • Sorry its been a while since I last looked at I2C so this might not be too helpful. But I notice you didn't quote the following resource which I found invaluable when getting I2C up and running. I see you realised you had to fix the R/W byte at the end of the address. Depending on the data sheet you might have to shift the slave address by 1 bit left before setting the R/W bit.

    EDIT: Also you may find that you need external pull up resistors if you are currently relying solely on the internal resistors.

    Code Examples:

**Attention** This is a public forum