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 with internal pull-up resistors? (MSP430F2xx)

Other Parts Discussed in Thread: PCF8574, MSP430F2272, MSP430F2274

Hi.

In the MSP430F2xx User Guide, it says that the SDA and SCL lines of the I2C bus "must be connected to a positive supply voltage using a pullup resistor".

My question is: Can the MSP430 internal pull-up resistors (PxREN) be used instead of using external ones? I have tried it, and it seems to work, but I'm asking in case this is not recommended for some reason...

Thanks!

  • Is ur I2C code working fine with those settings what ae you trying to interface

    if  u are interfacing only one slave device then it may be fine but if u r connecting more than one device then I suggest you to connect the External resistors of 10k ohms

    but I recommend you to connect the External pull ups even if u r using one slave device.

    And can you plz paste ur code I wanna take a look at it.

  • I am interfacing only a thermometer.

    Why does it make a difference if I interface more than one device?

    Like I said, everything seems to work fine using the internal pull up resistors, but I want to know if this is not recommended, and why.

    Thank you.

  • Hi,

    The I2C pull-up resistors definitely have an impact on the system. They are calculated as a function of bus capacitance (number of devices, trace length) , supply voltage and input curent.

    Without going into all the details I will say that the rise and fall time are directly affected by the pull-ups and the bus capcitance. If the pull-up is too high the Tr and Tf are large; slowing down the bus, if the pull-up is too small it leads to excess power consumption.

    If you only have one slave on the bus (and short trace lengths) you could probably use the internal pull-ups (~30K) but a more optimized solution would be to use between 5-10K external resistor.

    -Priya

  •  

    From the user manual:

    "Each bit in each PxREN register enables or disables the pullup/pulldown
    resistor of the corresponding I/O pin. The corresponding bit in the PxOUT
    register selects if the pin is pulled up or pulled down."

     

    As you are master, you will be driving the buss most of the time. But with REN enabled, you will be driving the buss with the resistor. If you see it work, you are only getting away with it because you will not be providing a hard sink on the buss. I made the same mistake the first time I wrote a master. One device worked while a second 'mysteriously' did not. And if you are always the master, you don't need a pull up on SCL as you don't release this line. SDA gets traded with you and your device(s) so does need a pullup.

    You will want to treat SDA and SCL differeantly.

    http://lakeweb.net/MSP430/

    Go to May 14, 2009 on the page. You will find I toggle SDA with PxDIR and SCL with PxOUT

     

    Best, Dan.

     

     

    Best, Dan.

     

  • Priya said:

    Hi,

    The I2C pull-up resistors definitely have an impact on the system. They are calculated as a function of bus capacitance (number of devices, trace length) , supply voltage and input curent.

    Without going into all the details I will say that the rise and fall time are directly affected by the pull-ups and the bus capcitance. If the pull-up is too high the Tr and Tf are large; slowing down the bus, if the pull-up is too small it leads to excess power consumption.

    If you only have one slave on the bus (and short trace lengths) you could probably use the internal pull-ups (~30K) but a more optimized solution would be to use between 5-10K external resistor.

    -Priya

    Makes perfect sense. Thank you!

     

    lakeweb said:
    As you are master, you will be driving the buss most of the time. But with REN enabled, you will be driving the buss with the resistor.

    That is not true. The User Guide is misleading. If you look at the Port P3 and P5 pin schematics (in the device-specific datasheet, section "APPLICATION INFORMATION"), you see that if PxSEL.y = 1, then the pin direction is set by the module direction. The only difference when setting PxREN.y = 1 is that you add a pull-up resistor when the I2C module sets the pin direction as input.

    The above is not just theory, I saw in the oscilloscope that the SCL and SDA pins are driven low instantly, and driven high slowly, as if pulled up with a resistor.

  • Nuwanda said:

     

    As you are master, you will be driving the buss most of the time. But with REN enabled, you will be driving the buss with the resistor.

    That is not true. The User Guide is misleading. If you look at the Port P3 and P5 pin schematics (in the device-specific datasheet, section "APPLICATION INFORMATION"), you see that if PxSEL.y = 1, then the pin direction is set by the module direction. The only difference when setting PxREN.y = 1 is that you add a pull-up resistor when the I2C module sets the pin direction as input.

    The above is not just theory, I saw in the oscilloscope that the SCL and SDA pins are driven low instantly, and driven high slowly, as if pulled up with a resistor.

    [/quote]

    Hi,

    Well you didn't say which pins you were using, and this doesn't agree with pin 3. I saw the tail on my scope, it was my hint to dig deeper...

    http://lakeweb.net/MSP430/images/i_o.gif

    Best, Dan.

     

     

  • lakeweb said:
    Well you didn't say which pins you were using

    I did say that I was using the MSP430F2xx's I2C module, which means I am using pins 1 (SDA) and 2 (SCL) of either port 3 (UCB0) or port 5 (UCB1).

    Note that the schematics for ports 3 and 5 are different from the one for port 1 (the image you posted).

  • Nuwanda said:

    Well you didn't say which pins you were using

    I did say that I was using the MSP430F2xx's I2C module...

    [/quote]

    Yes you did, my humblest apology. So, how many machine bytes does it take to do a master with the USI?

    Best, Dan.

     

  • You do need to release SCL. The target device may need extra time and will hold the SCL line low until it can complete the transaction. From the I2C spec:

    Every byte put on the SDA line must be 8-bits long. The number of bytes that can be transmitted per transfer is unrestricted. Each byte has to be followed by an acknowledge bit. Data is transferred with the most significant bit (MSB) first (see Fig.6). If a slave can’t receive or transmit another complete byte of data until it has performed some other function, for example servicing an internal interrupt, it can hold the clock line SCL LOW to force the master into a wait state. Data transfer then continues when the slave is ready for another byte of data and releases clock line SCL.

    You could be lucky and the slave device never needs to hold SCL low.

    BRs
      Paul

  • the_scotsman said:

    You do need to release SCL. The target device may need extra time and will hold the SCL line low ...

    You could be lucky and the slave device never needs to hold SCL low.

    BRs
      Paul

    Hi Paul,

    I have not seen this in the spec of any devices I have used. DS1631, EEPROMS, PCF8574. In fact, they all show SCL as input only and have timing requirments for this line. There may be slave devices out there that output on SCL, but I doubt I'll ever run across them.

    Best, Dan.

     

  • There is only one correct answer to this one: Really don't use the the internal pull-ups for I2C!!!

    You will make the I2C bus high impedant, causing really shitty signal wave forms. Oh yes, you will get away with it as the devices will work in most circumstances (especially one slave and short wires) but what if you enter a noisy environment (switching relays, motors, EMI, EMC, ...)? Yep, the right answer is your high impedant bus will be very sensitive for these and causing latch-ups.

    So conclusion: for a hobby project with no requirements you can do it and it will probably work. If you go for the serious work make sure you select the right external pull-ups conform the I2C specification. What is the cost and extra board space of the two resistors anyway? Don't take the risk of leaving them out.

    PS: the quote in the datasheet is there for a reason ...

    Best Regards,

    Wim

  • Please, can you show your code, i`m trying to use internal pullup in MSP430F2272 or MSP430F2274, and its not working.

  • I don't have a small code that I can copy/paste here, but it's pretty straightforward.

    For instance, if you're using UCBO, you need to set up P3 like this:

    P3OUT |= 0x06;

    P3REN |= 0x06;

    P3DIR |= 0x06;  // this is probably useless

    P3SEL |= 0x06;

    Then, configure the UCB0 module for I2C operation and use as usual.

    Take into account that you need to use a low I2C clock frequency if using internal pull-ups. I used 125 kHz.

    If you still can't figure it out, you should open a new thread providing details about the specifig problem that you are having (starting with what you see in the SDA and SCL pins).

    Good luck!

  • Hi everyone

    I am trying to read buttons from ez430-rf2500 using pull up mode, however I could not read the button correctly, all the time it shows that the button is pressed but it is not pressed. can anyone help me? the program is shown below

    #define I_WANT_TO_CHANGE_DEFAULT_ROM_DEVICE_ADDRESS_PSEUDO_CODE
    #include "bsp.h"
    #include "mrfi.h"
    #include "nwk_types.h"
    #include "nwk_api.h"
    #include "bsp_leds.h"
    #include "bsp_buttons.h"
    #include "vlo_rand.h"

    #ifndef APP_AUTO_ACK
    #error ERROR: Must define the macro APP_AUTO_ACK for this application.
    #endif

    void toggleLED(uint8_t);

    static void linkTo(void);

    static linkID_t sLinkID1 = 0;

    #define SPIN_ABOUT_A_SECOND   NWK_DELAY(1000)
    #define SPIN_ABOUT_A_QUARTER_SECOND   NWK_DELAY(250)

    /* How many times to try a Tx and miss an acknowledge before doing a scan */
    #define MISSES_IN_A_ROW  2

    void createRandomAddress(void);

    volatile int * tempOffset = (int *)0x10F4; // Temperature offset set at production
    char * Flash_Addr = (char *)0x10F0;        // Initialize radio address location

    __interrupt void ADC10_ISR(void);
    __interrupt void Timer_A (void);

    /* work loop semaphores */
    static volatile uint8_t sSelfMeasureSem = 0;

    void main (void)
    {
          addr_t lAddr;

     //WDTCTL = WDTHOLD | WDTPW;
      P2SEL &=0x1F;
      P2DIR &= 0xE0;
      //P2REN|=0x1F;
      P2OUT|=0x1F;  
     
     
     
      P4SEL&=0x38;
      P4DIR &= 0xC7;
      //P4REN|=0x38;
      P4OUT|=0x38;
     
       

     
      BSP_Init();
     
     
     

      if(Flash_Addr[0] == 0xFF && Flash_Addr[1] == 0xFF &&
         Flash_Addr[2] == 0xFF && Flash_Addr[3] == 0xFF )
      {
        createRandomAddress(); // set Random device address at initial startup
      }
      lAddr.addr[0] = Flash_Addr[0];
      lAddr.addr[1] = Flash_Addr[1];
      lAddr.addr[2] = Flash_Addr[2];
      lAddr.addr[3] = Flash_Addr[3];
      SMPL_Ioctl(IOCTL_OBJ_ADDR, IOCTL_ACT_SET, &lAddr);

      /* Keep trying to join (a side effect of successful initialization) until
       * successful. Toggle LEDS to indicate that joining has not occurred.
       */
      while (SMPL_SUCCESS != SMPL_Init(0))
      {
        toggleLED(1);
        toggleLED(2);
        SPIN_ABOUT_A_SECOND;
      }

      /* LEDs on solid to indicate successful join. */
      if (!BSP_LED2_IS_ON())
      {
        toggleLED(2);
      }
      if (!BSP_LED1_IS_ON())
      {
        toggleLED(1);
      }

      BCSCTL3 |= LFXT1S_2;                      // LFXT1 = VLO
      TACCTL0 = CCIE;                           // TACCR0 interrupt enabled
      TACCR0 = 12000;                           // ~ 1 sec
      TACTL = TASSEL_1 + MC_1;                  // ACLK, upmode  
     
      /* Unconditional link to AP which is listening due to successful join. */
      linkTo();

      while (1) ;
    }

    static void linkTo()
    {
        /*
    In order to send the data we need to use the foll      
          
          
          
         */
        uint8_t poi=0;//pointer
        uint8_t pp=0;// check state
        
      uint8_t     msg[1];
      uint8_t     misses, done;
     int results[5];      
          uint8_t      noAck;
          smplStatus_t rc;
            
        
    while(1)
    {

        if (!(P2IN & 0x00))
          {
              poi=0;
              pp=1;
              
          }
          else if (!(P2IN & 0x01))
          {
              poi=1;
              pp=1;
          }
          
          
          if (pp)
          {
     


      /* Keep trying to link... */
      while (SMPL_SUCCESS != SMPL_Link(&sLinkID1))
      {
        toggleLED(1);
        toggleLED(2);
        SPIN_ABOUT_A_SECOND;
      }

      /* Turn off LEDs. */
      if (BSP_LED2_IS_ON())
      {
        toggleLED(2);
      }
      if (BSP_LED1_IS_ON())
      {
        toggleLED(1);
      }

      SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);

     
    /* orginl PROGRAMM
      while (1)
      {
     
        __bis_SR_register(LPM3_bits+GIE);  // LPM3 with interrupts enabled    

        if (sSelfMeasureSem) {
          volatile long temp;
          int degC, volt;
          int results[5];      
          uint8_t      noAck;
          smplStatus_t rc;*/
        
          

          /* get radio ready...awakens in idle state */
          SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);

            results[0]=0x5A;
          results[1]=0x5B;
          results[2]=0x46;
          results[3]=0x47;
          results[4]=0x28;
        
          msg[0]=results[poi];
     
          done = 0;
          while (!done)
          {
            noAck = 0;

            /* Try sending message MISSES_IN_A_ROW times looking for ack */
            for (misses=0; misses < MISSES_IN_A_ROW; ++misses)
            {
              if (SMPL_SUCCESS == (rc=SMPL_SendOpt(sLinkID1, msg, sizeof(msg), SMPL_TXOPTION_ACKREQ)))
              {
                /* Message acked. We're done. Toggle LED 1 to indicate ack received. */
                toggleLED(1);  // Toggle On LED1
                __delay_cycles(2000);
                toggleLED(1);
                break;
              }
              if (SMPL_NO_ACK == rc)
              {
                /* Count ack failures. Could also fail becuase of CCA and
                 * we don't want to scan in this case.
                 */
                noAck++;
              }
            }
            if (MISSES_IN_A_ROW == noAck)
            {
              /* Message not acked. Toggle LED 2. */
              toggleLED(2);  // Turn On LED2
              __delay_cycles(2000);
              toggleLED(2);
    #ifdef FREQUENCY_AGILITY
              /* Assume we're on the wrong channel so look for channel by
               * using the Ping to initiate a scan when it gets no reply. With
               * a successful ping try sending the message again. Otherwise,
               * for any error we get we will wait until the next button
               * press to try again.
               */
              if (SMPL_SUCCESS != SMPL_Ping(sLinkID1))
              {
                done = 1;
              }
    #else
              done = 1;
    #endif  /* FREQUENCY_AGILITY */
            }
            else
            {
              /* Got the ack or we don't care. We're done. */
              done = 1;
            }
          }

          /* radio back to sleep */
          SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
        }
        
     // } this for the while(1)
     
     // }
      pp=0;
    }
    }


    void toggleLED(uint8_t which)
    {
      if (1 == which)
      {
        BSP_TOGGLE_LED1();
      }
      else if (2 == which)
      {
        BSP_TOGGLE_LED2();
      }
      return;
    }

    void createRandomAddress()
    {
      unsigned int rand, rand2;
      do
      {
        rand = TI_getRandomIntegerFromVLO();    // first byte can not be 0x00 of 0xFF
      }
      while( (rand & 0xFF00)==0xFF00 || (rand & 0xFF00)==0x0000 );
      rand2 = TI_getRandomIntegerFromVLO();
     
      BCSCTL1 = CALBC1_1MHZ;                    // Set DCO to 1MHz
      DCOCTL = CALDCO_1MHZ;
      FCTL2 = FWKEY + FSSEL0 + FN1;             // MCLK/3 for Flash Timing Generator
      FCTL3 = FWKEY + LOCKA;                    // Clear LOCK & LOCKA bits
      FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation
     
      Flash_Addr[0]=(rand>>8) & 0xFF;
      Flash_Addr[1]=rand & 0xFF;
      Flash_Addr[2]=(rand2>>8) & 0xFF;
      Flash_Addr[3]=rand2 & 0xFF;
     
      FCTL1 = FWKEY;                            // Clear WRT bit
      FCTL3 = FWKEY + LOCKA + LOCK;             // Set LOCK & LOCKA bit
    }

    /*------------------------------------------------------------------------------
    * ADC10 interrupt service routine
    ------------------------------------------------------------------------------*/
    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR(void)
    {
      __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)
    }

    /*------------------------------------------------------------------------------
    * Timer A0 interrupt service routine
    ------------------------------------------------------------------------------*/
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)
    {
      sSelfMeasureSem = 1;  
      __bic_SR_register_on_exit(LPM3_bits);        // Clear LPM3 bit from 0(SR)
    }

  • This thread is named "I2C with internal pullup resistors". I don't see anything even distantly I2C bus related in your question. And if you had read this thread before posting, you ha dseen that the pullup problem is strictly I2C related too.

    Would you please start a new thread? Or, better, check one of the several other threads that deal with pushbutton usage. You may find your answer there.

    Edit: Apparently you did start a new thread already.

**Attention** This is a public forum