• 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 » I2C: MSP430 to TMP102, Issues in Write operation
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 >
  • I2C: MSP430 to TMP102, Issues in Write operation

    I2C: MSP430 to TMP102, Issues in Write operation

    This question is answered
    Deepika Ranade86842
    Posted by Deepika Ranade86842
    on Mar 28 2012 01:32 AM
    Prodigy100 points

    Hi,

    I am using MSP430f249, and I2C in USCI-B1 to connect to TMP102.I can read the temperatures on power on reset using msp430x24x_uscib0_i2c_01.c.

    However, I want to use the SD + OC mode too, hence I am trying to use the MSP as a Master Transmitter followed by Master Receiver. I have to write 3 bytes to TMP102 (Priority Register, Config. register byte 1, config register byte 2).(Ideally, then I would send a stop signal, and then one more write operation with updated pointer register. Followed by multiple Read operations to Temp. Register.

    I am using the following code. I am getting error after the 1st byte is transmitted to TMP102. The control returns to main routine from ISR instead of waiting in ISR for transmitting 3 bytes. I tried to use two additional  __bis_SR_register(CPUOFF + GIE); with the hope to send the control back to ISR. But the code exitted with error: Cannot single step at the 2nd  __bis_SR_register(CPUOFF + GIE);

    Can someone please point out where am I going wrong?

    # include <msp430f249.h>
    unsigned char RxByteCtr, TxByteCtr;
    unsigned int RxWord;
    unsigned char DataToBeTx[3]={0x01, 0xE1, 0xA0};

    void main(void)
    {
      --code to init USC1_B1 -- (i have used it, but not posted the init_code here)
      TxByteCtr = 3;               // Load TX byte counter
      UCB1CTL1 |= UCTR + UCTXSTT;                    // I2C start condition
                                                      //here when UCB1TXIFG=1 indiacates that data should be placed in TXBUF.
                                                      //code to send data in TXBUF and send stop signal is in ISR
      while ( UCB1CTL1  & UCTXSTT);
     /* while (UCB1STAT & UCNACKIFG){                 // send STOP if slave sends NACK
        UCB1CTL1 |= UCTXSTP;
        UCB1STAT &= ~UCNACKIFG;
        while (UCB1CTL1 & UCTXSTP);            
        UCB1CTL1 |= UCTXSTT;
        while ( UCB1CTL1  & UCTXSTT);
      } */
      __bis_SR_register(CPUOFF + GIE);

    __bis_SR_register(CPUOFF + GIE);
    __bis_SR_register(CPUOFF + GIE);


      __disable_interrupt();                               //if you dont disable here, then you lose 1st data in RXBUF     
     
    --code to read 2 bytes  from TMP102, to ensure correct write operation. Ultimately, I will use 1 more write operation to update pointer register, followed by code to read as many sets of 2 bytes of Temp. Register as required. Code modified from  msp430x24x_uscib0_i2c_01.c.

    --this code was same as the example code, hence not posted here--

    }
    --ISR for TA0


    #pragma vector = USCIAB1TX_VECTOR
    __interrupt void USCIAB1TX_ISR(void)
    {
     /
      if (UC1IFG & UCB1RXIFG)
      {    
         ISR as from example code  msp430x24x_uscib0_i2c_01.c
      }

      if (UC1IFG & UCB1TXIFG)
      {
          TxByteCtr--;                              // Decrement RX byte counter

          if (TxByteCtr)
          {
            UCB1TXBUF = DataToBeTx[TxByteCtr];  // Get received byte
          }
          else
          {
            UCB1TXBUF = DataToBeTx[TxByteCtr];                    // Get final received byte,
            UCB1CTL1 |= UCTXSTP;  
            UC1IFG &= ~UCB1TXIFG;                                
               __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
          }
      }
    }

    Thanks,

    Deepika

    I2C USCIABxTX_VECTOR Master Transmitter to Master Receiver
    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    All Replies
    • Deepika Ranade86842
      Posted by Deepika Ranade86842
      on Mar 28 2012 09:39 AM
      Prodigy100 points

      Theoretically, I think, even if the control exits the ISR, until I specify to disable the interrupts, it should still be able to access the ISR. Hence I think this could be something that single stepping wont catch but actual hardware will.

      I tried this approach too.. but only 1 byte was sent, and code stopped at __disable_interrupts();.

      If I comment out the __disable_interrupts() parts, still only 1 byte is sent, the code still gets stuck at the 1st iteration of while loop. (Error: MSP430: Can't Single Step Target Program: Could not single step device, at RxByteCtr=2; )

      Please let me know where am I going wrong.

      I cant use a for or a while loop in the ISR. It will simulate well, but in real hardware scenario, I need to wait for 8 SCL cycles before the TXIFG is set again, unlike the one-step-transfer-complete -TXIFG-set that i see in single stepping. 

      I also tried to use the TI's sample code from slaa382.zip. I cant read any values from that code either.

      Thanks in anticipation,

      Deepika

      I2C USCIABxTX_VECTOR Master Transmitter to Master Receiver
      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 Mar 28 2012 10:56 AM
      Verified Answer
      Verified by Deepika Ranade86842
      Guru140650 points

      Deepika Ranade86842
            UC1IFG &= ~UCB1TXIFG;        

      Writing to TXBUF has already cleared it.

      However, you should not set UCTXSTP after writing to TXBUF, you should set it instead. When TXIFG is set, the previous byte is stills ending and your writ eto TXBUF is jsu tbuffered. Immediately settign UCSTP then will finishe the transfer of teh byte that's jsut sending, but will not send the byte that's waiting in TXBUF.

      So do it this way:

      if (UC1IFG & UCB1TXIFG)
        {
            if (TxByteCtr)
            {
              UCB1TXBUF = DataToBeTx[TxByteCtr--];  // send byte and decrement byte counter
            }
            else
            {
              UCB1CTL1 |= UCTXSTP;  
               __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
            }
        }

      However, you should also handle the NACKIFG case, or else you might enter a deadlock if the slave doesn't respond.
      TXIFG is set as soon as you set UCTXSTT (and in case of a NACK, the content of TXBUF is discarded). And if you don't write to TXBUF, the USCI will stall the bus while reading the slaves ACK, until you either do or set UCTXSTP.

      _____________________________________
      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.
    • Deepika Ranade86842
      Posted by Deepika Ranade86842
      on Mar 28 2012 14:36 PM
      Prodigy100 points

      As soon as I start to Transmit, I get a NACK, and am stuck in the NACK loop. But otherwise I could read the temperatures (Master in Receive mode, works fine).

      Tried a slave_present test too. I am stuck in NACK. I do not have a CRO/ Logic analyzer to check the waveforms.

      I cross checked that ADD0 is connected to Ground. So I am using 0x48 as slave address. (1001000 for Ao connected to Ground).

      The other thing is USSCLLOW is set too (Because it is expecting data in TXBUF?). (I have 10K pull-up resistors connected, There is no other slave connected. )

      The only other connection apart from these is that the ALERT pin of TMP102 is connected to P5.0/ UCB1STE/UCA1CLK + a pull-up resistor.

      slave_present test:

      // from http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/t/19585.aspx#138376
      # include <msp430f249.h>
      void main(void)
      {
        WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
       
        P5SEL |= 0x06;                            // Assign I2C pins to USCI_B1
        UCB1CTL1 |= UCSWRST;                      // Enable SW reset
        UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
        UCB1CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
        UCB1BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
        UCB1BR1 = 0;
        UCB1I2CSA = 0x48;                         // Remember to change the slave device address here if needed
      UCB1CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
       UC1IE &= ~(UCB1TXIE + UCB1RXIE);              // no RX or TX interrupts
        __disable_interrupt();
        UCB1CTL1 |= UCTR + UCTXSTT;       // I2C TX, start condition
        while (UCB1CTL1 & UCTXSTT);
        UCB1CTL1 |= UCTXSTP;
        while (UCB1CTL1 & UCTXSTP);                 // wait for STOP condition

      while(1);

      }

      I2C NACK TMP102
      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 Mar 29 2012 11:21 AM
      Verified Answer
      Verified by Deepika Ranade86842
      Guru140650 points

      Deepika Ranade86842
      The other thing is USSCLLOW is set too (Because it is expecting data in TXBUF?).

      I'd say yes.

      Actually, I didn't ever use I2C on the USCI in a productivity project. The 1611 we use in most of our projects did have an USART. And after a dew experiments, I found the USART I2C to be much too complex for practical use. A single, long background transfer is done nicely, but for short, busy-waiting transfers with changing direction, the handling was causing too much overhead, so I wrote my I2C in plain software.
      And the hardware development based on new 5438 with USCI has been stopped over a year ago in favor of vast improvements of out PC frontend software.
      So while I did some successful starting experiments with I2C on the USCI, my practical experience, especially with possible error ocnditions) is rather limited.

      However, I'd expect NACKIFG not being set before the end of the ACK cycle. And with USCLLOW, the ACK cycle of the address send is not finished (until you write to TXBUF or set UCTXSTP).

      But for your original code, I have an idea what might be wrong: TxByteCtr. You should add the volatile addtribute to it.
      You set it to 3, but since it is just a global variable that is set and never used again in main, the compiler may place the actual assignment of this value somewhere else in the code for size or speed optimization reasons.
      Maybe it is still 0 when you start the transfer, and the ISR ends the transfer before it has begun. Just an idea.
      Adding the volatile attribute tells the compiler to do the job where it is written, even if it doesn't seem to make sense (the compiler does not know about interrupts and ISRs)

      _____________________________________
      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.
    • Deepika Ranade86842
      Posted by Deepika Ranade86842
      on Mar 29 2012 14:56 PM
      Prodigy100 points

      Is there any way to see cycle-by-cyle (cycle with respect to SCL) values? I am using stepping in CCS v4, I can only see the end result due to a line of code.

      I could manage to see waveforms on a Logic Analyzer though. The D0 is SDA and D1 is SCL.Marker A= start, marker B= end of address sending. After address is set, SCL is not toggled at all. I see now what you meant by ACK cycle never being finished.

      Ok, so as I understand: data has to be in TXBUF before end of START sequence, so that SCL will keep toggling.

      So, should I start the code with __bis_SR_register(GIE) ? Tried to single step through this version, I still get a NACK and UCSCLLOW=1. But I could read the POR values of the Config. Register (Not the values that I wrote.) I think I am nearly there now. Not sure now exactly whats wrong.


      # include <msp430f249.h>
      volatile unsigned char RxByteCtr, TxByteCtr, array_index;
      unsigned int RxWord;
      unsigned char DataToBeTx[3]={0x01, 0xE1, 0xA0};

      void main(void)
      {

      --code to initialize USCB1 Master mode , SMCLK, with prescale= 12. (code not pasted here)

      /// ################### Write Pointer Register =0x01, Config Register byte 1 = E1 for OS + SD, byte 2=A0 ################
        TxByteCtr = 3;               // Load TX byte counter
        array_index=0;
       
        __bis_SR_register(GIE);
       
        UCB1CTL1 |= UCTR + UCTXSTT;                    // I2C start condition
                                                        //here when UCB1TXIFG=1 indicates that data should be placed in TXBUF, (In ISR)                                         
        while ( UCB1CTL1  & UCTXSTT);
        while (UCB1STAT & UCNACKIFG){                 // send STOP if slave sends NACK. Restart.
          UCB1CTL1 |= UCTXSTP;
          UCB1STAT &= ~UCNACKIFG;
          while (UCB1CTL1 & UCTXSTP);            
          UCB1CTL1 |= UCTXSTT;
          while ( UCB1CTL1  & UCTXSTT);
        }

                              
          // ################### Read config. Register to check if write was successful ###############
        while (1)
        {
                 --code from msp430x24x_uscib0_i2c_01.c
        }
      }



      #pragma vector = TIMERA0_VECTOR
      __interrupt void TA0_ISR(void)
      {
        __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
      }

      #pragma vector = USCIAB1TX_VECTOR
      __interrupt void USCIAB1TX_ISR(void)
      {

        if (UC1IFG & UCB1RXIFG)
        {    
            RxByteCtr--;                              // Decrement RX byte counter

            if (RxByteCtr)
            {
              RxWord = (unsigned int)UCB1RXBUF << 8;    // Get received byte
              if (RxByteCtr == 1)                       // Only one byte left?
                    UCB1CTL1 |= UCTXSTP;                  // Generate I2C stop condition
            }
            else
            {
              RxWord |= UCB1RXBUF;                    // Get final received byte,
                                                      // Combine MSB and LSB
                 __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
            }
        }

        if (UC1IFG & UCB1TXIFG)
        {
            if (TxByteCtr)
            {
              UCB1TXBUF = DataToBeTx[array_index];  // send byte and decrement byte counter

              array_index++;
              TxByteCtr--;
            }
            else
            {
              UCB1CTL1 |= UCTXSTP; 
              __disable_interrupt();
            }
        }
      }

      Sorry for the repeated questions. I can read off the TMP102, but really have to write to it too to send it to Low Power mode.

      Thanks

      I2C NACK TMP102
      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 Apr 12 2012 12:04 PM
      Guru140650 points

      As soon as you set UCTXSTT, the TX ISR is called. If a NACK is received then, teh byte already in TXBUF is discarded. So on a NACK, you'll have to reset the byte counter before you start again. Else after the 3rd unsuccessful attempt, the TX function will send a stop immediately after you set UCTXSTT.
      However, __disable_interrupt() inside an ISR is a NOP. Interrupts are disabled during ISR execution anyway (or else the ISR would interrupt itself infinitely), and on ISR exit, th eold state is restored.
      There are special intrinsics such as __bic_SR_register_on_exit() to clear the GIE bit (or the LPM bits) from the saved content of the status register that is restored on ISR exit. You already use it in the RX ISR code.

      Looking at the analyzer output I see, it seems that there are two problems.
      After SCL goes low the 9th time, the MSP should release SDA (and most liekly does). Since it stays low, the slave is pullling it low. So the slave obviously issues an ACK. However, the ACK cycle doesn't complete. Most likely because nothing is written to TXBUF.

      This should have been done by the ISR at this point. If not, it means that the TX ISR already has written all the three bytes. In three previous attempts to address the slave.

      So the quesiton is: were there three unsuccessful attempts to address the slave? If so, why? If not, there should be 'bytes left' even with the code that does nto reset the counter on a NCKK (as there were no NACK). And then the question is: why did the ISR not write to TXBUF?

      _____________________________________
      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