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.

F6779 and I2C EEPROM

Other Parts Discussed in Thread: MSP430F6779, MSP430WARE

Hi all,

I am very new to this MSP430 programming. I am working on a project that involves the MSP430F6779 and an external Cat24C256 EEPROM. I have searched for two days now a for a sample code that will help me getting started with EEPROM programming using I2C. I have found the following link which is exactly what I need.

http://www.ti.com/litv/pdf/slaa208a

http://www.ti.com/litv/zip/slaa208a

But the problem is that it was for old MSP430 controllers and the it won't compile obviously and gives errors. I need a similar routine but updated for the newer MSP430F6779 controller. I have downloaded the MSP430WARE and looked at the examples for I2C. I can find the Master-Slave examples but I don't know how to modify it to communicate with the EEPROM. Has someone written a wrapper for EEPROM ? or some alternate routines for I2C eeprom for MSP6779 or any compatible controller?

Here is my hardware configuration. I am using the PM_UCB0SCL and PM_UCB0SDA pins ( P2.5 and P2.6) to communicate with the  eeprom and both are pulled up as described in the documentation.

  • You need to separate two different things in your application: what you send and how you send it.
    The what depends on the slave device, the how on the MSP.
    If the application note you cited works for your EEPROM, then the what is there (and will still work), but the how has changed due to the different MSP. All you need is to adapt the code ‘send something to any I2C device’ and ‘receive something from any I2C device’. There are lots of examples available, and also many threads in this forum. Or MSP430Ware. And of course the users guide and the device datasheet, which tell you how to configure port pins and how to configure the SPI hardware.

  • Thanks for the reply... Using your suggestion I tried to modify the SLAA208 example for my MSP which is MSP430F6779.

    Here is some of it.

    #define I2C_PORT_SEL  P2SEL0
    #define I2C_PORT_OUT  P2OUT
    #define I2C_PORT_REN  P2REN
    #define I2C_PORT_DIR  P2DIR
    #define SDA_PIN       BIT6                  // UCB0SDA pin
    #define SCL_PIN       BIT5                  // UCB0SCL pin
    #define SCL_CLOCK_DIV 0x12                  // SCL clock divider
    
    void InitI2C(unsigned char eeprom_i2c_address)
    {
        I2C_PORT_SEL |= SDA_PIN + SCL_PIN;        // Assign I2C pins to USCI_B0
    
      // Recommended initialisation steps of I2C module as shown in User Guide:
     
                                               
        UCB0CTLW0 |= UCSWRST;                         // Enable SW reset
        UCB0CTLW0 |= UCMST | UCMODE_3 | UCSSEL_2;         // I2C Master, use SMCLK
    
        UCB0BRW_L = 12;                                   // fSCL = SMCLK/12 = ~100kHz
        UCB0BRW_H = 0;
    
        UCB0I2CSA = eeprom_i2c_address;                   // Slave Address is 048h
      // UCB1I2COA1 = 0x01A5;
        UCB0CTLW0 &= ~UCSWRST;                            // Clear SW reset, resume operation
        UCB0IE |= UCTXIE0;                                // Enable TX interrupt
        UCB0IE |= UCRXIE0;                                
        UCB0IE |= UCSTPIE;                            // Enable STP interrupt
        
      if (UCB0STAT & UCBBUSY)                   // test if bus to be free
      {                                         // otherwise a manual Clock on is
                                                // generated
        I2C_PORT_SEL &= ~SCL_PIN;               // Select Port function for SCL
        I2C_PORT_OUT &= ~SCL_PIN;               //
        I2C_PORT_DIR |= SCL_PIN;                // drive SCL low
        I2C_PORT_SEL |= SDA_PIN + SCL_PIN;      // select module function for the
                                                // used I2C pins
      }
    }
    
    /*---------------------------------------------------------------------------*/
    // Description:
    //   Initialization of the I2C Module for Write operation.
    /*---------------------------------------------------------------------------*/
    void I2CWriteInit(void)
    {
      UCB0CTLW0 |= UCTR;                         // UCTR=1 => Transmit Mode (R/W bit = 0)
      UCB0IFG &= ~UCTXIFG0;
      UCB0IE &= ~UCRXIE0;                         // disable Receive ready interrupt
      UCB0IE |= UCTXIE0;                          // enable Transmit ready interrupt
    }
    
    /*----------------------------------------------------------------------------*/
    // Description:
    //   Initialization of the I2C Module for Read operation.
    /*----------------------------------------------------------------------------*/
    void I2CReadInit(void)
    {
      UCB0CTLW0 &= ~UCTR;                        // UCTR=0 => Receive Mode (R/W bit = 1)
      UCB0IFG &= ~UCRXIFG0;
      UCB0IE  &= ~UCTXIE0;                         // disable Transmit ready interrupt
      UCB0IE  |= UCRXIE0;                          // enable Receive ready interrupt
    }
     
    
      
    /*----------------------------------------------------------------------------*/
    // Description:
    //   Byte Write Operation. The communication via the I2C bus with an EEPROM
    //   (2465) is realized. A data byte is written into a user defined address.
    /*----------------------------------------------------------------------------*/
    void EEPROM_ByteWrite(unsigned int Address, unsigned char Data)
    {
      unsigned char adr_hi;
      unsigned char adr_lo;
    
      while (UCB0STAT & UCBUSY);                // wait until I2C module has
                                                // finished all operations.
    
      adr_hi = Address >> 8;                    // calculate high byte
      adr_lo = Address & 0xFF;                  // and low byte of address
    
      I2CBufferArray[2] = adr_hi;               // Low byte address.
      I2CBufferArray[1] = adr_lo;               // High byte address.
      I2CBufferArray[0] = Data;
       tx_count =2;
     //tx_byte_count = tx_count + 1;
     //tx_byte_counter = tx_count; 
     
       I2CWriteInit();
       UCB0CTLW0 |= UCTXSTT;                      // start condition generationemain in LPM0 until all data is TX'd
      __bis_SR_register(LPM0_bits + GIE);      // Enter LPM0 w/ interrupts
       
      // UCB1CTLW0 |= UCTR | UCTXSTT;                                         // => I2C communication is started
    
     UCB0CTLW0 |= UCTXSTP;                      // I2C stop condition
     // __bis_SR_register(LPM0_bits + GIE); 
     while (UCB0CTLW0 & UCTXSTP) ;             // Ensure stop condition got sent
    }
    
    /*----------------------------------------------------------------------------*/
    // Description:
    //   Random Read Operation. Data is read from the EEPROM. The EEPROM
    //   address is defined with the parameter Address.
    /*----------------------------------------------------------------------------*/
    
    unsigned char EEPROM_RandomRead(unsigned int Address)
    {
      unsigned char adr_hi;
      unsigned char adr_lo;
      I2CBuffer =0;
    
      while (UCB0STAT & UCBUSY);                // wait until I2C module has
                                                // finished all operations
    
      adr_hi = Address >> 8;                    // calculate high byte
      adr_lo = Address & 0xFF;                  // and low byte of address
    
      I2CBufferArray[1] = adr_hi;               // store single bytes that have to
      I2CBufferArray[0] = adr_lo;  
       tx_count =1;  
     // tx_byte_count = tx_count + 1;
     // tx_byte_counter = tx_count;  
     
       I2CWriteInit();
       UCB0CTLW0 |= UCTXSTT;                      // start condition generationemain in LPM0 until all data is TX'd
      __bis_SR_register(LPM0_bits + GIE);      // Enter LPM0 w/ interrupts
       
      
      // Read Data byte
      I2CReadInit();
    
      UCB0CTLW0 |= UCTXSTT;                      // I2C start condition
     
      while(UCB0CTLW0 & UCTXSTT);                // Start condition sent? // Enter LPM0 w/ interrupts
       __bis_SR_register(LPM0_bits + GIE);
      UCB0CTLW0 |= UCTXSTP;                      // I2C stop condition
      while(UCB0CTLW0 & UCTXSTP);                // Ensure stop condition got sent
      return I2CBuffer;
    }
    /*----------------------------------------------------------------------------*/
    // Description:
    //   Acknowledge Polling. The EEPROM will not acknowledge if a write cycle is
    //   in progress. It can be used to determine when a write cycle is completed.
    /*----------------------------------------------------------------------------*/
    void EEPROM_AckPolling(void)
    {
      while (UCB0STAT & UCBUSY);                // wait until I2C module has
                                                // finished all operations
      do
      {
        UCB0STAT = 0x00;                        // clear I2C interrupt flags
        UCB0CTLW0 |= UCTR;                       // I2CTRX=1 => Transmit Mode (R/W bit = 0)
        UCB0CTLW0 &= ~UCTXSTT;
        UCB0CTLW0 |= UCTXSTT;                    // start condition is generated
        while(UCB0CTLW0 & UCTXSTT)               // wait till I2CSTT bit was cleared
        {
          if(!(UCNACKIFG & UCB0STAT))           // Break out if ACK received
            break;
        }
        UCB0CTLW0 |= UCTXSTP;                    // stop condition is generated after
                                                // slave address was sent => I2C communication is started
        while (UCB0CTLW0 & UCTXSTP);             // wait till stop bit is reset
        __delay_cycles(500);                    // Software delay
      }while(UCNACKIFG & UCB0STAT);
    }
    
    
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    
    {
      switch (__even_in_range(UCB0IV, 30))
        {
            case USCI_NONE: break;                    // No interrupts
            case USCI_I2C_UCALIFG: break;             // ALIFG
            case USCI_I2C_UCNACKIFG: break;           // NACKIFG
            case USCI_I2C_UCSTTIFG: break;            // STTIFG
            case USCI_I2C_UCSTPIFG:                   // STPIFG
                I2CBuffer = UCB0RXBUF;                   // Get RX data
                __bis_SR_register_on_exit(LPM0_bits); // Exit from LPM0 on return
                break;
            case USCI_I2C_UCRXIFG3: break;            // RXIFG3
            case USCI_I2C_UCTXIFG3: break;            // TXIFG3
            case USCI_I2C_UCRXIFG2: break;            // RXIFG2
            case USCI_I2C_UCTXIFG2: break;            // TXIFG2
            case USCI_I2C_UCRXIFG1: break;            // RXIFG1
            case USCI_I2C_UCTXIFG1: break;            // TXIFG1
            case USCI_I2C_UCRXIFG0: break;            // RXIFG0
            case USCI_I2C_UCTXIFG0:                   // TXIFG0
              UCB0TXBUF = I2CBufferArray[tx_count];   // Load TX buffer
              tx_count--;                             // Decrement TX byte counter
              if (tx_count < 0)                       // Less then 0 means all data send. (I2CBufferArray[0] is send).
                {
                    UCB0IFG &= ~UCTXIFG;                  // Clear USCI_B0 TX int flag
                    UCB0CTL1 |= UCTXSTP;                  // I2C stop condition
                    __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
                }
                break;          
              
            case USCI_I2C_UCBCNTIFG: break;           // CNTIFG
            case USCI_I2C_UCCLTOIFG: break;           // LTOIFG
            case USCI_I2C_UCBIT9IFG: break;           // BIT9IFG
            default: break;
        }
    }
    
    //In the main I do something like
    
    InitI2C(SlaveAddress); 
    EEPROM_ByteWrite(0x0000,0x12);
    EEPROM_AckPolling(); // Wait for EEPROM write cycle
    read_val[0] = EEPROM_RandomRead(0x0000); // Read from address 0x0000

    Now the problem is that the Interrupt is never called and the code is struck on

    while (UCB0CTLW0 & UCTXSTP);

    or
     while(UCB0CTLW0 & UCTXSTT);  
    Can you tell me what am I doing wrong here? I have tried different variations of Slave Address. The documentation of 
    my EEPROM says that the slave address of my EEPROM is 1010 A2 A1 A0 W/R. As my A2,A1,A0 are all connected to
    ground So I have tried 0xA0 and 0x50 but to no avail.


  • Now the problem is that the Interrupt is never called. I tried inserting breakpoints as well as flashing an LED but it never reaches there and the code is struck on

    while (UCB0CTLW0 & UCTXSTP);

    or

     while(UCB0CTLW0 & UCTXSTT);  

    Can you tell me what am I doing wrong here? I have tried different variations of Slave Address. The documentation of my EEPROM says that the slave address of my EEPROM is 1010 A2 A1 A0 W/R. As my A2,A1,A0 are all connected to ground So I have tried 0xA0 and 0x50 but to no avail.

  • The logic in EEPROM_ACK_polling is wrong.
    You loiop while TXSTT is set and break if UCNACKIFG is clear. Which is wrong for several reasons:
    NACKIFG will only be set (if at all) after the start byte is sent. At this point, TXSTT is reset (at the same moment). While TXSTT is set, NACKIFG is always clear.
    In TX mode (UCTR set), TXSTT won’t clear (and the start byte won’t complete) unless you either set TXSTP at the same time or write a first byte to TXBUF. Which won’t happen byt e ISR if GIE is not set.
    Since sending the start byte won’t complete, TXSTP won’t ever clear too. So you are stuck there.

**Attention** This is a public forum