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.

MSP430F5510 I2C on port 4

I took the TI example for I2C "uscib0_i2c_08 and tried to convert it to use Port 4.  It has a problem where it goes into the interrupt and sets the first bit but after that it hangs (goes back to the main loop and no more interrupts are sent).  Here is the code:


#include <msp430.h>

unsigned char *PTxData;                     // Pointer to TX data
unsigned char TXByteCtr;

const unsigned char TxData[] =              // Table of data to transmit
{
  0x18,  // reg = timer control
  0x2  // data
};

int main(void)
{
  unsigned int i;

  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT


  PJDIR |= 0x02;                             // PJ.1 RTC switch
  PJOUT = 0x0;                                // RTC switch low = RTC on


  P4SEL = 0x06;
  P4DIR  |= 0x06;


  PMAPPWD  = 0x02D52;                        // Enable Write-access to modify port mapping registers
  PMAPCTL |= PMAPRECFG;
  P4MAP1 = PM_UCB1SDA;
  P4MAP2 = PM_UCB1SCL;
  PMAPPWD  = 0;                              // Disable Write-Access to modify port mapping registers





  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 = 0xD2;                         // Slave Address is 0D2h = RTC
  UCB1CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  UCB1IE |= UCTXIE;                         // Enable TX interrupt

  while (1)
  {
    for(i=0;i<10;i++);                      // Delay required between transaction
    PTxData = (unsigned char *)TxData;      // TX array start address
                                            // Place breakpoint here to see each
                                            // transmit operation.
    TXByteCtr = sizeof TxData;              // Load TX byte counter

    UCB1CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
    
     __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0, enable interrupts
    __no_operation();                       // Remain in LPM0 until all data
                                            // is TX'd
    while (UCB1CTL1 & UCTXSTP);             // Ensure stop condition got sent
  }
}

//------------------------------------------------------------------------------
// The USCIAB1TX_ISR is structured such that it can be used to transmit any
// number of bytes by pre-loading TXByteCtr with the byte count. Also, TXData
// points to the next byte to transmit.
//------------------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B1_VECTOR))) USCI_B1_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCB1IV,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: break;                           // Vector 10: RXIFG
  case 12:                                  // Vector 12: TXIFG  
    if (TXByteCtr)                          // Check TX byte counter
    {
      UCB1TXBUF = *PTxData++;               // Load TX buffer
      TXByteCtr--;                          // Decrement TX byte counter
    }
    else
    {
      UCB1CTL1 |= UCTXSTP;                  // I2C stop condition
      UCB1IFG &= ~UCTXIFG;                  // Clear USCI_B1 TX int flag
      __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
    }  
  default: break;
  }
}

  • Hi Alenie,

    I see that you changed the slave address too. Is your slave ACK'ing the address? Try checking the bus with an oscilloscope or a logic analyzer.
    The address 0xD2 is invalid for 7-bit mode since BIT7 is ignored. You are actually sending to address 0x52 and I'm not sure if that's the correct address of your device.
    Some manufacturers align the I2C address to the left (including the R/W bit in BIT0), and in that case you should try changing the address to 0x69.

    As an additional note: you don't need to configure PMAP since the pins have a default PMAP functionality as I2C (although it doesn't hurt to do it and that's not causing any problems). And you don't need to set the pins as outputs.

    Regards,
    Luis R
  • Luis,

    Thanks for responding. I am using an Ambiq RTC and they have the following in their spec sheet "If this address is 0b1101001 (0xD2/3), the AM18X5 is
    selected, the eighth bit indicate a write (RW = 0) or a read (RW = 1)" 

    The TI example seems to have the slave address "preselected" rather than have a a string with the adresss a read/write byte before the data?


    I have an oscope and the only thing that happens is a low to to high transition on the clock and data lines - then it loops in the main forever..

    Does the code look correct?

  • Luis,

    I changed my slave address to 68h . The scope shows the data line going high while the clock line does not toggle.  I have checked the data and clock lines out with toggle the port bits and they are ok - not stuck.

  • Luis,

    Just realized the slave address must be 0x69 and not 0x68. Tried the new slave address but no change in outcome.

  • alenie said:
    data line going high while the clock line does not toggle

    Your lines shouldn’t go to High, both already should be High! And when starting transmission they should give pulses to Low and ending High.

    Do you have adequate Pull-Up resistors?

  • HI Alenie,

    • I didn't find any problems with the code.
    • I see that you are turning on the RTC by setting PJ.1 low (?). How are you connecting this line? Does it turn off/on the RTC completely? Perhaps that's what pulling the line low at the beggining. If so, have you tried adding a delay after turning on the RTC, just to be sure that the I2C lines are idle?
    • I see that there is an RTC version supporting I2C and one supporting SPI. I assume you are 100% sure you are using the I2C version, correct?
    • The slave address of the RTC should be 0x69
    • As Leo mentions, I2C needs external pull-ups. After reset, MSP430 GPIOs are configured as inputs so they should be high due to the pull-ups. After being configured for I2C functionality as "open-drain" the pins will remain high. Only when the MSP430 starts the packet as a Master, it will pull the lines low forcing the Start condition and sending the address. Try some ~1K-3.3K pull-ups. 
    • Even if the RTC is disconnected, the MSP430 should send the Start+address but it won't get ACK. Do you see this behavior if the I2C lines are disconnected from RTC?

    Regards,

    Luis R

  • Luis,

    Thanks for the help.  Your response of wrong salve address was correct. In addition, Leo response also helped - I needed a stronger pull up on the lines. All is good now. I am new to the forum - how do I close this action out?

  • Leo - you were right - my pull ups were too weak. I am now up and running.
  • I'm glad to found the problem.

    alenie said:
    I am new to the forum - how do I close this action out?

    Click the "Verify Answer" button

    LR

**Attention** This is a public forum