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.

I2C stop bit set for single byte Tx Rx

Other Parts Discussed in Thread: MSP430F5335

Hi,

 I have implmenting I2C in MSP430f5335 with slave device AMC6821SDBQ temp sensor. In this i face the following issues

1. If i tried to read single byte only but my master read two bytes after that only it sends stop bit.For that i am written code using interrupt both rx and tx as follows

switch(i2cReg_ptr->UCBxIV)
    {
        case  2:        // Vector  2: ALIFG
            break;
        case  4:        // Vector  4: NACKIFG
            // UCTXSTP - Generate Stop condition
            i2cReg_ptr->UCBxCtl1 |= 0x04;            
            break;
        case  6:        // Vector  6: STTIFG
            break;
        case  8:        // Vector  8: STPIFG
            break;
        case 10:        // Vector 10: RXIFG         
            if(i2cRWBuf_ptr->size == 1)  // size of the receive bytes
            {
                // UCTXSTP - Generate Stop condition
                i2cReg_ptr->UCBxCtl1 |= 0x04;               
                *(i2cRWBuf_ptr->data) = i2cReg_ptr->UCBxRXBuf; // read data from rxbuf
                i2cReg_ptr->UCBxIE &= ~(0x01);       //disable Rx interrupt       
            }
            break;
        case 12:        // Vector 12: TXIFG   
                if(i2cRWBuf_ptr->size > 0)   //size of the data transmitted
                {
                    // Transfer next byte
                    i2cReg_ptr->UCBxTXBuf = *(i2cRWBuf_ptr->data); // assign data to TXbuf
                    i2cRWBuf_ptr->size--;
                    i2cRWBuf_ptr->data++;
                }
                if(i2cRWBuf_ptr->size == 0)
                {
                    // UCTXSTP - Generate Stop condition
                    i2cReg_ptr->UCBxCtl1 |= 0x04;
                    // Transfer completed
                    // Disable Transmit Interrupt
                    i2cReg_ptr->UCBxIE &= ~(0x02);                   
                }
            }
            break;

If suppose i want to read device id i use the following sequence

i2ctransmit()

{

           // Transmit Interrupt enable
            i2cReg_ptr->UCBxIE |= 0x02;

           // UCTR - Enable Transmit
           i2cReg_ptr->UCBxCtl1 |= 0x10;
       
          // UCTXSTT - Generate Start condition
          i2cReg_ptr->UCBxCtl1 |= 0x02;

}

then it hit the interrupt i have the data to be transfer in  *(i2cRWBuf_ptr->data) its assigned in interrupt.

i2creceive()

{  
    i2cReg_ptr->UCBxIE |= 0x01;  // Receive Interrupt enable

    i2cReg_ptr->UCBxCtl1 &= ~(0x10);     // UCTR - Enable Receive       

    i2cReg_ptr->UCBxCtl1 |= 0x02;    // UCTXSTT - Generate Start condition

}
      

can anyone guide me how to set stop bit for both transmit and receive of single byte in interrupt method.

  • Hi Prakash,

    Code Composer Studio's (Release 6.0) Reource Explorer (View->Resource Explorer) has a couple of examples on I2C. 

    Once you bring up Resource Explorer, if you select 'Devices->MSP430F5xx/6xx->Code Examples->MSP430F5334' there are various i2c examples that you might be able to reference to solve your issue.

    Regards,

    Arthi Bhat 

  • Hi Arthi,

     Thanks for your reply. I am developing my driver using IAR workbench. In IAR work bench sample programs given only for MSP as master and slave. Though i will check in CCS also can you share me any link where i get the codes.

    can you please look in to my code and tell me the stop bit generation is correct or not.

  • Hi Prakash,

    I have attached the sample master/slave code from Code composer studio that does transference of single byte of data with interrupt.  I am not sure if the problem you are seeing is because of the way you setup the registers or because you are not polling the control register for the stop command as the sample code indicates.  

    User Guide SLAU208n.pdf for the MSP430F5xx/6xx, section 36.3.4.2.1 states the following:

    When transmitting a single byte of data, the UCTXSTP bit must be set while the byte is being transmitted or anytime after transmission begins, without writing new data into UCBxTXBUF. Otherwise, only the address is transmitted.

    /* --COPYRIGHT--,BSD_EX
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     *******************************************************************************
     * 
     *                       MSP430 CODE EXAMPLE DISCLAIMER
     *
     * MSP430 code examples are self-contained low-level programs that typically
     * demonstrate a single peripheral function or device feature in a highly
     * concise manner. For this the code may rely on the device's power-on default
     * register values and settings such as the clock configuration and care must
     * be taken when combining code from several examples to avoid potential side
     * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
     * for an API functional library-approach to peripheral configuration.
     *
     * --/COPYRIGHT--*/
    //******************************************************************************
    //  MSP430F530x Demo - USCI_B0 I2C Master RX single bytes from MSP430 Slave
    //
    //  Description: This demo connects two MSP430's via the I2C bus. The master
    //  reads from the slave. This is the MASTER CODE. The data from the slave
    //  transmitter begins at 0 and increments with each transfer. The received
    //  data is in R5 and is checked for validity. If the received data is
    //  incorrect, the CPU is trapped and the P1.0 LED will stay on. The USCI_B0
    //  RX interrupt is used to know when new data has been received.
    //  ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.045MHz
    //
    //  ***to be used with "MSP430F530x_uscib0_i2c_05.c" ***
    //
    //                                /|\  /|\
    //               MSP430F5310      10k  10k     MSP430F5310
    //                   slave         |    |        master
    //             -----------------   |    |   -----------------
    //           -|XIN  P3.0/UCB0SDA|<-|----+->|P3.0/UCB0SDA  XIN|-
    //            |                 |  |       |                 | 32kHz
    //           -|XOUT             |  |       |             XOUT|-
    //            |     P3.1/UCB0SCL|<-+------>|P3.1/UCB0SCL     |
    //            |                 |          |             P1.0|--> LED
    //
    //   K. Chen
    //   Texas Instruments Inc.
    //   Ver 2.00 - May 2012
    //   Built with CCS Version: 5.2 and IAR Embedded Workbench Version: 5.40.3
    //******************************************************************************
    #include <msp430.h>
    
    unsigned char RXData;
    unsigned char RXCompare;
    
    int main(void)
    {
      WDTCTL = WDTPW | WDTHOLD;                 // Stop WDT
      P1OUT &= ~0x01;                           // P1.0 = 0
      P1DIR |= 0x01;                            // P1.0 output
      P3SEL |= 0x03;                            // Assign I2C pins to USCI_B0
      UCB0CTL1 |= UCSWRST;                      // Enable SW reset
      UCB0CTL0 = UCMST | UCMODE_3 | UCSYNC;     // I2C Master, synchronous mode
      UCB0CTL1 = UCSSEL_2 | UCSWRST;            // Use SMCLK
      UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
      UCB0BR1 = 0;
      UCB0I2CSA = 0x48;                         // Slave Address is 048h
      UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
      UCB0IE |= UCRXIE;                         // Enable RX interrupt
      RXCompare = 0x0;                          // Used to check incoming data
    
      while (1)
      {
        while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
        UCB0CTL1 |= UCTXSTT;                    // I2C start condition
        while(UCB0CTL1 & UCTXSTT);              // Start condition sent?
        UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
        
        __bis_SR_register(LPM0_bits | GIE);     // Enter LPM0, enable interrupts
        __no_operation();                       // For debugger
      
        if (RXData != RXCompare)                // Trap CPU if wrong
        {
          P1OUT |= 0x01;                        // P1.0 = 1
          while(1);
        }
    
        RXCompare++;                            // Increment correct RX value
      }
    }
    
    // USCI_B0 Data ISR
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCB0IV,12))
      {
      case  0: break;                           // Vector  0: No interrupts
      case  2: break;                           // Vector  2: ALIFG
      case  4: break;                           // Vector  4: NACKIFG
      case  6: break;                           // Vector  6: STTIFG
      case  8: break;                           // Vector  8: STPIFG
      case 10:                                  // Vector 10: RXIFG
        RXData = UCB0RXBUF;                     // Get RX data
        __bic_SR_register_on_exit(LPM0_bits);   // Exit active CPU
        break;
      case 12: break;                           // Vector 12: TXIFG
      default: break; 
      }
    }
    
    
    
     

    Regards,

    Arthi

     

  • Hi Arthi,

     So the transmit or receive of single byte is not possible through interrupt. Am i wright? If wrong means how to set a stop while transmit? I referred the code which you have attached the same only for IAR also given.From that code understaing only i asked the above question? can you please guide i struggled lot of days due to this issue.

     

    Thanks in Advance

  • Transmitting a single byte is possible with interrupts.
    When TXSTT is set, TXIFG is set too. So the ISR will write the first byte to TXBUF. (which must be done – or TXSTP must be set, in order to complete the ACK cycle of the start byte and get TXSTT clear)

    When the USCI begins to transmit the first byte, TXIFG is set again. At this point, TXSTP can be set to stop after the first byte.

    Transmitting zero bytes with interrupts is not possible (and not required,. AFAIK, it works if you just set TXSTT and TXSTP together – but I’m not sure whether a possible NACKIFG remains set if the stop immediately follows the start byte).

    Receiving a single byte is not possible using interrupts. TXSTP needs to be set during the reception of the first byte. And you don’t get any interrupts during this period. When you get the RXIFG, then receiving of the second byte has already begun. So you need to busy-wait until TXSTT clears, then set TXSTP.

**Attention** This is a public forum