• Join
  • Sign In with my.TI Login
Texas Instruments
  • Products
  • Applications
  • Tools & Software
  • Support & Community
  • Sample & Buy
  • About TI
Sample & Purchase Cart Sample & Purchase Cart
  • Search
  • Advanced
TI E2E™ Community
  • Support Forums
  • Blogs
  • Groups
  • Videos
  • 简体中文
  • More ...
TI Home » TI E2E Community » Support Forums » Microcontrollers » MSP430™ Microcontrollers » MSP430 Ultra-Low Power 16-bit Microcontroller Forum » How does this example code work? I2C Receive using TX interrupt? How?
Share
MSP430™ Microcontrollers
  • Forum
  • Announcements
  • E2E Wiki
Options
  • Subscribe via RSS
MSP430 Resources
  • MSP430 Product Folder
  • MSP-EXP430G2 - MSP430 LaunchPad Value Line Development kit
  • MSP430 Getting Started Guide
  • MSP430 Microcontroller Projects
  • More Resources >
  • How does this example code work? I2C Receive using TX interrupt? How?

    How does this example code work? I2C Receive using TX interrupt? How?

    This question is not answered
    Scott Brenneman
    Posted by Scott Brenneman
    on Feb 03 2011 19:23 PM
    Intellectual380 points

    TI distributes example code for various MSP430 parts.  There's a specific example file which isn't making sense to me: msp430x22x4_uscib0_i2c_12.  It transmits and then receives, all from within an ISR for USCIAB0TX.  It enables RX interrupts at some point (UCB0RXIE) but there's no ISR for RX, and the RX flag (UCB0RXIFG) is never checked for.  So, my question is, how does it work without these features, and why does the code enable an interrupt it appears never to use?

    Here's the code:

    //******************************************************************************
    //  MSP430F22x4 Demo - USCI_B0 I2C Master TX/RX multiple bytes from MSP430 Slave
    //                     with a repeated start in between TX and RX operations.
    //
    //  Description: This demo connects two MSP430's via the I2C bus. The master
    //  transmits to the slave, then a repeated start is generated followed by a
    //  receive operation. This is the master code. This code demonstrates how to
    //  implement an I2C repeated start with the USCI module using the USCI_B0 TX
    //  interrupt.
    //  ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.2MHz
    //
    //    ***to be used with msp430x22x4_uscib0_i2c_13.c***
    //
    //                                /|\  /|\
    //               MSP430F24x      10k  10k     MSP430F22x4
    //                   slave         |    |        master
    //             -----------------   |    |  -----------------
    //           -|XIN  P3.1/UCB0SDA|<-|---+->|P3.1/UCB0SDA  XIN|-
    //            |                 |  |      |                 |
    //           -|XOUT             |  |      |             XOUT|-
    //            |     P3.2/UCB0SCL|<-+----->|P3.2/UCB0SCL     |
    //            |                 |         |                 |
    //
    //  R. B. Elliott / H. Grewal
    //  Texas Instruments Inc.
    //  April 2008
    //  Built with IAR Embedded Workbench Version: 3.42A
    //******************************************************************************
    #include "msp430x22x4.h"

    #define NUM_BYTES_TX 3                         // How many bytes?
    #define NUM_BYTES_RX 2

    int RXByteCtr, RPT_Flag = 0;                // enables repeated start when 1
    volatile unsigned char RxBuffer[128];       // Allocate 128 byte of RAM
    unsigned char *PTxData;                     // Pointer to TX data
    unsigned char *PRxData;                     // Pointer to RX data
    unsigned char TXByteCtr, RX = 0;
    unsigned char MSData = 0x55;

    void Setup_TX(void);
    void Setup_RX(void);
    void Transmit(void);
    void Receive(void);

    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      P3SEL |= 0x06;                            // Assign I2C pins to USCI_B0
     
      while(1){
       
      //Transmit process
      Setup_TX();
      RPT_Flag = 1;
      Transmit();
      while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
     
      //Receive process
      Setup_RX();
      Receive();
      while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
      }
    }

    //-------------------------------------------------------------------------------
    // The USCI_B0 data ISR is used to move received data from the I2C slave
    // to the MSP430 memory. It is structured such that it can be used to receive
    // any 2+ number of bytes by pre-loading RXByteCtr with the byte count.
    //-------------------------------------------------------------------------------
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    {
      if(RX == 1){                              // Master Receive?
      RXByteCtr--;                              // Decrement RX byte counter
      if (RXByteCtr)
      {
        *PRxData++ = UCB0RXBUF;                 // Move RX data to address PRxData
      }
      else
      {
        if(RPT_Flag == 0)
            UCB0CTL1 |= UCTXSTP;                // No Repeated Start: stop condition
          if(RPT_Flag == 1){                    // if Repeated Start: do nothing
            RPT_Flag = 0;
          }
        *PRxData = UCB0RXBUF;                   // Move final RX data to PRxData
        __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
      }}
     
      else{                                     // Master Transmit
          if (TXByteCtr)                        // Check TX byte counter
      {
        UCB0TXBUF = MSData++;                   // Load TX buffer
        TXByteCtr--;                            // Decrement TX byte counter
      }
      else
      {
        if(RPT_Flag == 1){
        RPT_Flag = 0;
        PTxData = &MSData;                      // TX array start address
        TXByteCtr = NUM_BYTES_TX;                  // Load TX byte counter
        __bic_SR_register_on_exit(CPUOFF);
        }
        else{
        UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
        IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
        __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
        }
      }
     }
     
    }

    void Setup_TX(void){
      _DINT();
      RX = 0;
      IE2 &= ~UCB0RXIE; 
      while (UCB0CTL1 & UCTXSTP);               // Ensure stop condition got sent// Disable RX interrupt
      UCB0CTL1 |= UCSWRST;                      // Enable SW reset
      UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
      UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
      UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
      UCB0BR1 = 0;
      UCB0I2CSA = 0x48;                         // Slave Address is 048h
      UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
      IE2 |= UCB0TXIE;                          // Enable TX interrupt
    }
    void Setup_RX(void){
      _DINT();
      RX = 1;
      IE2 &= ~UCB0TXIE; 
      UCB0CTL1 |= UCSWRST;                      // Enable SW reset
      UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
      UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
      UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
      UCB0BR1 = 0;
      UCB0I2CSA = 0x48;                         // Slave Address is 048h
      UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
      IE2 |= UCB0RXIE;                          // Enable RX interrupt
    }
    void Transmit(void){
        PTxData = &MSData;                      // TX array start address
        TXByteCtr = NUM_BYTES_TX;                  // Load TX byte counter
        while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
        UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
        __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts
    }
    void Receive(void){
        PRxData = (unsigned char *)RxBuffer;    // Start of RX buffer
        RXByteCtr = NUM_BYTES_RX-1;              // Load RX byte counter
        while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
        UCB0CTL1 |= UCTXSTT;                    // I2C start condition
        __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts
    }

    I2C I2C examples on MSP430F2274 I2C master I2C TX
    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    All Replies
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on Feb 04 2011 10:59 AM
      Guru139900 points

      Scott Brenneman
      So, my question is, how does it work without these features, and why does the code enable an interrupt it appears never to use?

      Oh, it uses it. It's just a bit different than in SPI/UART mode.

      In I2C mode, RX and TX interrupts are triggering the TX ISR, while the status interrupts trigger the RX ISR. The reason is that I2C is half-duplex, so during one transmission, you only either receive or transmit, but not both.
      This is described in the users guide, bt you can easily miss this info. And it's nothing you would expect. But after some thinking it makes sense and allows more efficient programming.

      On the 5x devices, the (else identical) USART has the interrupts distributed differently: Here ther i s only one USCIARXTX and one USCIBRXTX ISR. So RX and TX (and in case of I2C the status interrupts) arrive in the same ISR, but there are different ISRs for each USCI sub-module (and for each USCI). With this setup, you won't tap into the trap you stepped in for the 2x series USCI.

      _____________________________________
      Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.
      If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Scott Brenneman
      Posted by Scott Brenneman
      on Feb 04 2011 12:24 PM
      Intellectual380 points

      Wow, that's certainly counter-intuitive.  Where in the Guide does it explain this, so I can read more about it?

      Thank you so much for clarifying!

      Scott

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on Feb 10 2011 12:54 PM
      Guru139900 points

      Scott Brenneman
      Wow, that's certainly counter-intuitive.

      Reason was since only RX or TX are active during one complete transmission, to have one interrupt for the transmission and one for the status changes.

      Scott Brenneman
      Where in the Guide does it explain this, so I can read more about it?

      There are only 2 sentences about it in the users guide which explain everything and nothing:

      slau144e.pdf chapter 17.3.7 (page 543): One interrupt
      vector is associated with the transmit and receive interrupt flags. The other
      interrupt vector is associated with the four state change interrupt flags.

      THe problem is that I cannot locate wnywhere which USART interrupt is used for what. The interrupt vector table in the datasheet  does not list this I2C special handling and associates one vector with RX and one with TX (which is correct for UART and SPI). You can only see it in the provided code example where the two ISRs are named
      USCIA0_RX_USCIB0_I2C_STATE_ISR and USCIA0_TX_USCIB0_I2C_DATA_ISR.

      _____________________________________
      Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.
      If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Scott Brenneman
      Posted by Scott Brenneman
      on Feb 10 2011 12:57 PM
      Intellectual380 points

      Thank you Jens-Michael.  I guess documentation isn't what it used to be...!

      Scott

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on Feb 14 2011 13:40 PM
      Guru139900 points

      Scott Brenneman
      I guess documentation isn't what it used to be...!

      Well, the TI documentation is quite good, compared to soem crap you find for other devices.

      It's jsut that the whole stuff is so complex that not everything can be written everywhere, so you need to carefully read all of it so you do not miss something.
      It's not bug-free, however, and sometimes it really isn't exhausting enough or explanation is so short that that you just might miss the point on first (or second) reading.

       

      _____________________________________
      Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.
      If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    TI E2E™ Community
    • Support Forums
    • Blogs
    • Videos
    • Groups
    • Site Support & Feedback
    • Settings
    TI E2E™ Community Groups
    • TI University Program
    • Make the Switch
    • Microcontroller Projects
    • Motor Drive & Control
    Other Communities
    • Deyisupport
    • Designsomething.org
    • beagleboard.org
    • TI on Element 14
    • TI on TechXchangeSM
    Other Technical & Support Resources
    • WEBENCH® Design Center
    • Product Information Centers
    • Technical Documents
    • TI Design Network
    • TI Technical Articles
    • TI Training

    All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.

    Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI, its suppliers and providers of content reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

    Follow Us Texas Instruments on Facebook Texas Instruments on Twitter Texas Instruments on LinkedIn Texas Instruments on Google+
    TI Worldwide | Contact Us | my.TI Login | Site Map | Corporate Citizenship | mobile m.ti.com (Mobile Version)

    TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs and
    embedded processors, along with software, tools and the industry’s largest sales/support staff.

    © Copyright 1995-2013 Texas Instruments Incorporated. All rights reserved.
    Trademarks | Privacy Policy | Terms of Use