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.

MSP430FR2633: interfacing EEProm with msp340fr2633 using i2c protocol

Part Number: MSP430FR2633
Other Parts Discussed in Thread: MSPWARE

Hello,

        In master transmit mode and making eeprom(24LC256) as slave with address 0x50. I would like to know the folllowing.

1)how to check the acknowledgement(ACK) form the slave in msp430fr2633.

2)how to set the r/w bit of the controlbyte of eeprom

3)NACK is turned on the control byte is transmitted.

Thanks in advance,

Regards,

Gourav 

  • Hello Gourav,

    1. The UCTXIFG flag will be set after master send the data and get the ACK from the slave.

        Also the UCNACKIFG flag will be set if the master get the NACK from the slave.

    2. For the control byte of the eeprom you are using, since msp430fr2633 is a master, you will need to set the slave address use UCB0I2CSA.

        And configure UCTR=1 (Write) or 1) UCTR=0 (Read).

    3. I am not sure I understand this question, could you please clarify it?

    And if you have the MSPware you can find the example code of how to use I2C for any specific device.

    I attached one example for master I2C transmit and master I2C receive.

    eusci_b_i2c_ex1_masterRxMultiple.zipeusci_b_i2c_ex3_masterTxMultiple.zip

    Also in the MSP430FR2633 device user's guide page 628, it has detail explanation on the I2C master transmit flow.

    Thanks,

    Yiding

  • Hello Yiding,

    I have gone through the examples and user guide. But could not find about ACK bit. So I would like to know how to check acknowledge (ACK) received from slave.  Is there any specific bit to check??

    Do I  need to send slave addresses with r/w in control byte or its sent by the Microcontroller??

    Thanks,

    Gourav

  • Hi Gourav!

    The slave address is automatically sent when the UCTXSTT bit is set, along with R/W bit (decided with UCTR bit). You have to load the selected slave address into a register called UCxI2CSA before setting UCTXSTT.

    Something like this

    UCB0I2CSA = Slave_Address; // Address Assignment
    UCB0IFG &=~ UCTXIFG; // Flag Clear
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
    while(!(UCB0IFG&UCTXIFG)); // While Flag=0;
    UCB0IFG &=~ UCTXIFG; // Flag Clear

    UCTR bit is set if you want to TRansmit, or write. IF you want to read, clear UCTR and only set UCTXSTT.
    Then, for check if there were ACK/NACK, you have to write something in the TXBUF.
    Wait until UCTXSTT is set and then check for NACK (UCxIFG&UCNACKIFG or similar) : if there is no NACK, you have an ACK!

    It's all in the manual's scheme.
  • *wait until UCTXSTT is clear (cleared if message ACK'ed)

    something like this

    while(UCB0CTL1&UCTXSTT) // While start not ack'ed
    {
    if(UCB0IFG&UCNACKIFG) // if NACK, issue stop and exit
    {
    UCB0IFG &=~ UCNACKIFG;
    UCB0CTL1 |= UCTXSTP;
    return 1;
    }
    }
  • Hello Mirco Franchetti,

                                          I have followed what you have said but still i am facing problem in reading from EEPROM (BYTE_READ and Sequential read).  I have problem with NACK bit. There is a UCSTPNACK bit in  UCB0CTLW1 reg.  which says at the end of  master receive mode it automatically sends NACK bit. But this cannot be seen in the reg. here is the code for which i am working .

    Regards, 

    Gourav

    23557.main.c
    //polling based
    #include <msp430fr2633.h>
    
    #define SDA BIT2
    #define SCL BIT3
    
    #define LED1_POUT                                                       (P1OUT)
    #define LED1_PDIR                                                       (P1DIR)
    #define LED1_PIN                                                         (BIT7)
    #define LED1_ON                                         (LED1_POUT |= LED1_PIN)
    #define LED1_OFF                                       (LED1_POUT &= ~LED1_PIN)
    #define LED1_TOGGLE                                     (LED1_POUT ^= LED1_PIN)
    
    #define LED2_POUT                                                       (P1OUT)
    #define LED2_PDIR                                                       (P1DIR)
    #define LED2_PIN                                                         (BIT6)
    #define LED2_ON                                         (LED2_POUT |= LED2_PIN)
    #define LED2_OFF                                       (LED2_POUT &= ~LED2_PIN)
    #define LED2_TOGGLE                                     (LED2_POUT ^= LED2_PIN)
    
    #define LED3_POUT                                                       (P1OUT)
    #define LED3_PDIR                                                       (P1DIR)
    #define LED3_PIN                                                         (BIT0)
    #define LED3_ON                                         (LED3_POUT |= LED3_PIN)
    #define LED3_OFF                                       (LED3_POUT &= ~LED3_PIN)
    #define LED3_TOGGLE                                     (LED3_POUT ^= LED3_PIN)
    
    //unsigned char I2CBufferArray[]={'\0','\0','\0','\0'};
    unsigned char ReadArray[]={'\0','\0','\0','\0','\0','\0','\0'};
    static unsigned int count=0;
    static unsigned char I2CBuffer='\0';
    int PtrTransmit=0;
    
    #define     MAXPAGEWRITE   64
    
    int PtrTransmit;
    unsigned char I2CBufferArray[66];
    
    void init_i2c();
    void configureClocks(unsigned long clkFrequency);
    void switchCase(unsigned long clkFrequency);
    
    void EEPROM_ByteWrite(unsigned char address, unsigned char data);
    void EEPROM_PageWrite(unsigned int StartAddress , unsigned char * Data , unsigned char Size);
    
    void EEPROM_AckPolling(void);
    
    unsigned char EEPROM_RandomRead(unsigned char address);
    unsigned char EEPROM_CurrentAddressRead(void);
    unsigned char* EEPROM_SequentialRead(unsigned int address , unsigned int size);
    
    void reset_i2c_array();
    
    unsigned char ch[MAXPAGEWRITE];
    
    void main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;               // stop watchdog timer
        PM5CTL0 &= ~LOCKLPM5;                    // Disable the GPIO power-on default high-impedance mode to activate 1previously configured port settings
        unsigned char d='\0';
        unsigned char e='\0';
        unsigned char f='\0';
        unsigned char *c;
        int i=0;
        reset_i2c_array();
        P1OUT&=0X00;
        P1DIR |=BIT0|BIT6|BIT7;
        P1OUT&=0X00;
        configureClocks(1000000);
        init_i2c();//8000000);
    
        for(i=0; i<4; i++)
            ch[i]=65+i;
    
        EEPROM_PageWrite(0x00,ch ,4);
        //EEPROM_SequentialRead(0x00,6);
        /*EEPROM_ByteWrite(0x0000, 0x0012);
        EEPROM_ByteWrite(0x0001, 0x0013);
        EEPROM_ByteWrite(0x0002, 0x0014);
        EEPROM_ByteWrite(0x0003, 0x0015);
        EEPROM_ByteWrite(0x0004, 0x0016);
        EEPROM_ByteWrite(0x0005, 0x0017);
        EEPROM_ByteWrite(0x0006, 0x0018);
        EEPROM_ByteWrite(0x0007, 0x0019);
        EEPROM_ByteWrite(0x0008, 0x0020);
        EEPROM_ByteWrite(0x0009, 0x0021);
        EEPROM_ByteWrite(0x0010, 0x0022);*/
        d = EEPROM_RandomRead(0x0000); // Read from address 0x0000
        e = EEPROM_CurrentAddressRead();
    
        f = EEPROM_CurrentAddressRead(); // Read from address 0x0000
    
        c= EEPROM_SequentialRead(0x00,8);
    
    
        if(d==0x12)
                {
                    LED1_ON;
                    LED2_OFF;
                }
                else if(e==0x0000)
                {
                    LED2_ON;
                    LED1_OFF;
                }
    
    
        //EEPROM_AckPolling();
        d = EEPROM_RandomRead(0x0001); // Read from address 0x0000
        e = EEPROM_CurrentAddressRead(); // Read from address 0x0001
    
        if(d==0x13)
            {
                LED1_ON;
                LED2_OFF;
            }
            else if(f==0x0001)
            {
                LED2_ON;
                LED1_OFF;
            }
    }
    
    void init_i2c()//unsigned long clkFrequency)
    {
        //const unsigned long x=clkFrequency;
    
        P1SEL0 |= SCL | SDA;
        // Configure I2C
        UCB0CTLW0 |=UCSWRST;
        UCB0CTLW0 |=  UCMST|UCMODE_3|UCSSEL__SMCLK|UCSYNC; //master mode, i2c, smclk selected
        //UCB0BRW &=0x0000;                           //clear the baud rate
        UCB0BRW |=0X0010;//(unsigned int)(x/8);              //set the baud rate=SMCLK/8
        UCB0CTLW1 = UCASTP_0;//2                       // AUTOMATIC STOP CONDITION
        //UCB0TBCNT = 0x07;                           //
        //UCB0I2CA0=0X000A;                          // MASTER ADDRESS SET
        UCB0I2CSA = 0x0050;                         // address slave is 51hex
            //UCB0CTLW1 |= UCSTPNACK;
        UCB0CTLW0 &= ~UCSWRST;                        // software reset
        //UCB0IE |= UCNACKIE;
        //UCB0IE |= UCTXIE0 | UCRXIE0 | UCNACKIE;                       // enable tx interrupt
        //__bic_SR_register(GIE);
    
    
    }
    
    void configureClocks(unsigned long clkFrequency)
    {
         const unsigned long x=clkFrequency;
        // using DCO HARDWARE TRIM FUNCTION
        __bis_SR_register(SCG0);                 // disable FLL
         CSCTL3 |= SELREF__REFOCLK;               // Set REFO as FLL reference source
         CSCTL0 = 0;                              // clear DCO and MOD registers
         CSCTL1 &= ~(DCORSEL_7);                  // Clear DCO frequency select bits first
         //CSCTL1 |= DCORSEL_4;//DCORSEL_4; for 12 MHz//DCORSEL_3;                     // Set DCO = 8MHz
         switchCase(x);
         //x=clkFrequency;
         //((243/8000000))); //365;//365 FOR 12MHz  //243;                   // DCODIV = 8MHz
         CSCTL2 = FLLD_0 +(unsigned int)(x*243/8000000);//0.0000003075);
         __delay_cycles(3);
         __bic_SR_register(SCG0);                 // enable FLL
         while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked
    
         CSCTL4 = SELMS__DCOCLKDIV;// | SELA__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz
                                                  // default DCODIV as MCLK and SMCLK source
    }
    void switchCase(unsigned long clkFrequency)
    {
         switch(clkFrequency)
         {
                 case 1000000:  CSCTL1 |= DCORSEL_0;
                                 break;
                 case 2000000:  CSCTL1 |= DCORSEL_1;
                                 break;
                 case 4000000:  CSCTL1 |= DCORSEL_2;
                                 break;
                 case 8000000:  CSCTL1 |= DCORSEL_3;
                                 break;
                 case 12000000:  CSCTL1 |= DCORSEL_4;
                                 break;
                 case 16000000:  CSCTL1 |= DCORSEL_5;
                                 break;
                 case 20000000:  CSCTL1 |= DCORSEL_6;
                                 break;
                 case 24000000:  CSCTL1 |= DCORSEL_7;
                                 break;
                 default      :  //not found;
                                 break;
         }
    }
    void EEPROM_ByteWrite(unsigned char address, unsigned char data)
    {
            unsigned char addr_hi;
            unsigned char addr_lo;
    
            while (UCB0STAT & UCBBUSY);                // wait until I2C module has
                                                      // finished all operations.
            addr_hi = address >> 8;                    // calculate high byte
            addr_lo = address & 0xFF;                  // and low byte of address
    
            I2CBufferArray[2]=addr_hi;
            I2CBufferArray[1]=addr_lo;
            I2CBufferArray[0]=data;
            PtrTransmit = 2;                          // set I2CBufferArray Pointer
    
            UCB0IFG &= ~UCTXIFG0;                   // Clear USCI_B0 TX int flag
            UCB0CTLW0 |= UCTR;                      // I2C TX, start condition
            UCB0CTLW0 |= UCTXSTT;                      // I2C TX, start condition
            while(UCB0CTLW0 & UCTXSTT);
            while(PtrTransmit>=0)
            {
               UCB0TXBUF = I2CBufferArray[PtrTransmit];// Load TX buffer
               while(!(UCB0IFG & UCTXIFG0));
               UCB0IFG &= ~UCTXIFG0;                   // Clear USCI_B0 TX int flag
               PtrTransmit--;                          // Decrement TX byte counter
            }
            if(PtrTransmit < 0)
            {
                 UCB0CTLW0 |= UCTXSTP;                  // I2C stop condition
                 UCB0IFG &= ~UCTXIFG0;                   // Clear USCI_B0 TX int flag
            }
            while(UCB0CTLW0 & UCTXSTP);                // Ensure stop condition got sent
            UCB0IFG &= ~UCSTPIFG;
    }
    
    void EEPROM_PageWrite(unsigned int startAddress , unsigned char *data , unsigned char size)
    {
        while (UCB0STAT & UCBBUSY);                // wait until I2C module has finished all operations.
    
        unsigned char addr_hi;
        unsigned char addr_lo;
    
        addr_hi = startAddress >> 8;                    // calculate high byte
        addr_lo = startAddress & 0xFF;                  // and low byte of address
        PtrTransmit = 0;
        while(*data)
        {
            I2CBufferArray[PtrTransmit]=*data;
            data++;
            PtrTransmit++;
        }
        I2CBufferArray[PtrTransmit++]=addr_lo;
        I2CBufferArray[PtrTransmit]=addr_hi;
    
        //PtrTransmit = 2;                          // set I2CBufferArray Pointer
    
        UCB0IFG &= ~UCTXIFG0;                   // Clear USCI_B0 TX interrupt flag
        UCB0CTLW0 |= UCTR;                      // I2C TX, start condition
        UCB0CTLW0 |= UCTXSTT;                      // I2C TX, start condition
        while(UCB0CTLW0 & UCTXSTT);
        while(PtrTransmit>=0)
        {
           UCB0TXBUF = I2CBufferArray[PtrTransmit];// Load TX buffer
           while(!(UCB0IFG & UCTXIFG0));
           UCB0IFG &= ~UCTXIFG0;                   // Clear USCI_B0 TX interrupt flag
           PtrTransmit--;                          // Decrement TX byte counter
        }
        if(PtrTransmit < 0)
        {
             UCB0CTLW0 |= UCTXSTP;                  // I2C stop condition
             UCB0IFG &= ~UCTXIFG0;                   // Clear USCI_B0 TX interrupt flag
        }
        while(UCB0CTLW0 & UCTXSTP);                // Ensure stop condition got sent
        //UCB0IFG &= ~UCSTPIFG;
    }
    
    unsigned char EEPROM_RandomRead(unsigned char address)
    {
        while (UCB0STAT & UCBBUSY);                 // wait until I2C module has finished all operations.
    
        unsigned char addr_hi;
        unsigned char addr_lo;
    
        addr_hi = address >> 8;                    // calculate high byte
        addr_lo = address & 0xFF;                  // and low byte of address
    
        I2CBufferArray[1]=addr_hi;
        I2CBufferArray[0]=addr_lo;
        I2CBuffer='\0';
        PtrTransmit=1;
    
        //UCB0I2CSA = 0x0050;
        UCB0CTLW0 |= UCTR;
        UCB0CTLW0 |= UCTXSTT;                      // I2C TX, start condition
        while(UCB0CTLW0 & UCTXSTT);
    
        __delay_cycles(20);                     // wait for ack
    
        while(PtrTransmit>=0)
        {
           UCB0TXBUF = I2CBufferArray[PtrTransmit];// Load TX buffer
           while(!(UCB0IFG & UCTXIFG0));
           UCB0IFG &= ~UCTXIFG0;                   // Clear USCI_B0 TX int flag
           PtrTransmit--;                          // Decrement TX byte counter
        }
        UCB0IFG &= ~UCTXIFG0;                   // Clear USCI_B0 TX int flag
    
        //Reading the data from eeprom
        UCB0CTLW0 &= ~UCTR;                         // configure EEPROM in read mode and i2c in receive mode
        UCB0CTLW0 |= UCTXSTT;                      // I2C TX, start condition
        while(UCB0CTLW0 & UCTXSTT)                  // wait until start bit has been sent
        {
            if((UCB0IFG & UCNACKIFG))               // if nackifg is high then send stop condition
            {
                UCB0IFG &= ~UCNACKIFG;
                UCB0CTLW0 |= UCTXSTP;
                    while(UCB0CTLW0 & UCTXSTP);                // Ensure stop condition got sent
                break;
            }
        }
        __delay_cycles(20);
        //I2CBuffer = ReadArray[count++] = UCB0RXBUF;
        I2CBuffer = UCB0RXBUF;                      //data read from i2c
    
        while(!(UCB0IFG & UCRXIFG0));                  // wait until rx flag is cleared
        __delay_cycles(20);
        //UCB0CTLW0 |= UCTXNACK;
        __delay_cycles(20);                     // wait for ack
        //UCB0CTLW0 &= ~UCTXNACK;
        //while(UCB0CTLW0 & UCTXNACK);
    //    while(!(UCB0IFG & UCRXIFG0));                  // wait until rx flag is cleared
    /*    if((UCB0IFG & UCRXIFG0))
            UCB0IFG &= ~UCRXIFG0;*/                   // Clear USCI_B0 TX int flag
    
        //UCB0CTLW0 |= UCTXNACK;
        //while(!(UCB0CTLW0 & UCTXNACK));
        UCB0CTLW0 |= UCTXSTP;                       // set stop condition
        UCB0IFG &= ~UCRXIFG0;
        while(UCB0CTLW0 & UCTXSTP);                // Ensure stop condition got sent
        return I2CBuffer;
    }
    
    unsigned char EEPROM_CurrentAddressRead()
    {
        unsigned char I2CBuffer='\0';
    
        while (UCB0STAT & UCBBUSY);                 // wait until I2C module has finished all operations.
    
        UCB0CTLW0 |= UCTXSTT;                      // I2C TX, start condition
        while(UCB0CTLW0 & UCTXSTT);                 // Ensure start condition got sent
        UCB0CTLW0 &= ~UCTR;
    
        I2CBuffer = UCB0RXBUF;                      //data read from i2c
    
        UCB0CTLW0 |= UCTXSTP;                       // send stop condition
        while(UCB0CTLW0 & UCTXSTP);                // Ensure stop condition got sent
    
        return I2CBuffer;
    }
    
    unsigned char* EEPROM_SequentialRead(unsigned int address , unsigned int size)
    {
        while (UCB0STAT & UCBBUSY);                 // wait until I2C module has finished all operations.
    
        unsigned char addr_hi;
        unsigned char addr_lo;
        unsigned int count;
    
        addr_hi = address >> 8;                    // calculate high byte
        addr_lo = address & 0xFF;                  // and low byte of address
    
        reset_i2c_array();
        I2CBufferArray[1]=addr_hi;
        I2CBufferArray[0]=addr_lo;
    
        PtrTransmit=1;
    
        UCB0I2CSA = 0x0050;
        UCB0CTLW0 |= UCTR;
        UCB0CTLW0 |= UCTXSTT;                      // I2C TX, start condition
        while(UCB0CTLW0 & UCTXSTT);
    
        __delay_cycles(50);                     // wait for ack
    
        while(PtrTransmit>=0)
        {
           UCB0TXBUF = I2CBufferArray[PtrTransmit];// Load TX buffer
           while(!(UCB0IFG & UCTXIFG0));
           UCB0IFG &= ~UCTXIFG0;                   // Clear USCI_B0 TX int flag
           PtrTransmit--;                          // Decrement TX byte counter
        }
        UCB0IFG &= ~UCTXIFG0;                   // Clear USCI_B0 TX int flag
    
        //Reading the data from eeprom
        reset_i2c_array();
        UCB0CTLW0 &= ~UCTR;                         // configure EEPROM in read mode and i2c in receive mode
        UCB0CTLW0 |= UCTXSTT;                      // I2C TX, start condition
        while(UCB0CTLW0 & UCTXSTT)                  // wait until start bit has been sent
        {
            if((UCB0IFG & UCNACKIFG))               // if nackifg is high then send stop condition
            {
                UCB0IFG &= ~UCNACKIFG;
                UCB0CTLW0 |= UCTXSTP;
                    while(UCB0CTLW0 & UCTXSTP);                // Ensure stop condition got sent
                break;
            }
        }
        reset_i2c_array();
        for(count=0; count<size; count++)
        {
            I2CBufferArray[count] = ReadArray[count] = UCB0RXBUF; //I2CBuffer = UCB0RXBUF;                      //data read from i2c
        }
    
        //UCB0CTLW0 |= UCTXNACK;
        //while(!(UCB0CTLW0 & UCTXNACK));
    
        while(!(UCB0IFG & UCRXIFG0));                  // wait until rx flag is cleared
        if((UCB0IFG & UCRXIFG0))
            UCB0IFG &= ~UCRXIFG0;                   // Clear USCI_B0 TX int flag
    
        UCB0CTLW0 |= UCTXSTP;                       // set stop condition
        while(UCB0CTLW0 & UCTXSTP);                // Ensure stop condition got sent
        return I2CBufferArray;
    }
    
    void reset_i2c_array()
    {
        for(count=0; count< MAXPAGEWRITE+2; count++)
        {
            ch[count]=I2CBufferArray[count] ='\0';
        }
    }

  • Hello Gourav,

    Master does not need to send the NACK and you should not need to use it either.

    In master receive mode, a STOP condition is either generated by the automatic STOP generation or by setting the UCTXSTP bit. The next byte received from the slave is followed by a NACK and a STOP condition. This NACK occurs immediately if the eUSCI_B module is currently waiting for UCBxRXBUF to be read.

    Thanks,
    Yiding

**Attention** This is a public forum