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.

Constant START condition MSP430 TMP100

Other Parts Discussed in Thread: MSP430F169, TMP175, TMP100

Hello everybody!

Started to work with I2C bus, but something goes wrong with it. First of all there is my source code to msp430f169

//******************************************************************************
//  MSP-FET430P140 Demo - SMBus Master Interface to SMBus Slave TMP175
//
//  Description: I2C/SMBus interface to TMP175 temperature sensor in 9-bit mode.
//  TimerA0 CCR0 interrupt is used as a wake up and to read
//  the TMP175 temperatre register. If the temperature is greater than 28c,
//  P1.0 is set, else reset.  CPU is normally off and used only during TA_ISR.
//  P2.0 is used for responding to the ALERT response from the Slave TMP175.
//  A Slave Alert Response is sent by the master and TMP175 puts its address
//  on the bus.
//  ACLK = n/a, MCLK = SMCLK = TACLK = I2CIN = DCO~ 800k
//  //* MSP430F169 Device Required *//
//
//                           /|\
//         /|\           /|\  |  /|\
//          |   TMP175   10k 10K 10k     MSP430F169          
//          |   -------   |   |   |   -----------------
//          +--|Vcc SDA|<-|---+---|->|P3.1         P1.0|--->LED
//             |       |  |       |  |                 |
//          +-|A2,A1,A0|  |       |  |                 |
//          |  |  ALERT|--|-------+->|P2.0             |
//          +--|Vss SCL|<-+----------|P3.3             |
//         \|/  -------              |                 |    
//
//
//  H. Grewal
//  Texas Instruments Inc.
//  Feb 2005
//  Built with IAR Embedded Workbench Version: 3.21A
//******************************************************************************

#include  <msp430x16x.h>
typedef enum {
             SMBS_MISC               = (unsigned char) 0x4E,
             SMBS_DEVICE_DFLT        = (unsigned char) 0x61,
             SMBS_ALERT_RESPONSE     = (unsigned char) 0x0C,
             SMBS_HOST               = (unsigned char) 0x08,
             SMBS_10BIT_ADD          = (unsigned char) 0x78,
             SMBS_DFLT_ADD           = (unsigned char) 0x37,
             SMBS_ACCESS_HOST        = (unsigned char) 0x28,            
             SMBS_CBUS               = (unsigned char) 0x01,
             SMBS_GCAL               = (unsigned char) 0x00
             }SMBS_Address_t;              
/*---------------------------------------------------------------------------*/

void SMBS_Init (SMBS_Address_t Add_Param,unsigned char Slave_Add);
void setupTMP175 (void);
void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog
  P1DIR |= 0xFF;                            // Set P1.0 to output direction
                                            // unused ports to output
  P3DIR =  0xFF;                                           
  P3SEL |= 0x0A;                            // Assign I2C pins to module
  P4DIR =  0xFF;
  P5DIR =  0xFF;
  P6DIR =  0xFF;
  SMBS_Init (SMBS_MISC,0x4E);               // Slave address configured as 4Eh
  P2DIR = 0xFE;                             // set P2.0 to input 
  P2IES = 0x01;                             // Interrupt edge select for push buttons
  P2IFG = 0;                                // Clear pending P2 interrupts
  P2IE = 0x01;                              // Enable P2.0 interrupt
  setupTMP175();
 
  CCTL0 = CCIE;                             // CCR0 interrupt enabled
  TACTL = TASSEL_2 + MC_2;                  // SMCLK, continuous mode

  _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
}
void SMBS_Init (SMBS_Address_t Add_Param,unsigned char Slave_Add)
{
  U0CTL |= I2C + SYNC + MST;                      // Recommended init procedure
  U0CTL &= ~I2CEN;                          // Recommended init procedure
  I2CTCTL |= I2CSSEL1;                      // SMCLK
  I2CPSC = 0x04;
  I2CSCLH = 0x01;
  I2CSCLL = 0x01;
  //I2CNDAT = 0x01;                           // Read one byte
  U0CTL |= I2CEN;                           // Enable I2C
  if (Add_Param == SMBS_MISC)
  {
      I2CSA = Slave_Add;                    // Slave Address is 048h
  }
  else
      I2CSA = (unsigned char) Add_Param ;
 
  U0CTL |= I2CEN;                           // Enable I2C
}

void setupTMP175(void)
{
  I2CNDAT = 0x03;
  U0CTL |= MST;                             // Master mode
  I2CTCTL |= I2CRM+I2CSTT+I2CTRX;          // Initiate transfer
 
  while ((I2CIFG & TXRDYIFG) == 0);         // Wait for transmitter to be ready
  I2CDRB = I2CSA << 1;                           // Load  Slave address
  while ((I2CIFG & TXRDYIFG) == 0);         // Wait for transmitter to be ready
  I2CDRB = 0x03;                            // Load  Pointer register--T(high)
  while ((I2CIFG & TXRDYIFG) == 0);         // Wait for transmitter to be ready THERE IS PROBLEM
  I2CTCTL |= I2CSTP;
  I2CDRB = 0x18;                            // Load  T(high) register
  while ((I2CTCTL & I2CSTP) == 0x02);       // Check STP condition
 
  U0CTL |= MST;                             // Master mode
  I2CTCTL |= I2CSTT+I2CSTP+I2CTRX;          // Initiate transfer
  while ((I2CIFG & TXRDYIFG) == 0);         // Wait for transmitter to be ready
  I2CDRB = 0x01;                            // Load  Pointer register--Config reg
  while ((I2CIFG & TXRDYIFG) == 0);         // Wait for transmitter to be ready
  I2CDRB = 0x02;                            // Load  Configuration register--TM mode
  while ((I2CTCTL & I2CSTP) == 0x02);       // Check STP condition
 
  I2CNDAT = 0x01;
  U0CTL |= MST;                             // Master mode
  I2CTCTL |= I2CSTT+I2CSTP+I2CTRX;          // Initiate transfer
  while ((I2CIFG & TXRDYIFG) == 0);         // Wait for transmitter to be ready
  I2CDRB = 0x00;                            // Load  Pointer register--Temp Reg
  while ((I2CTCTL & I2CSTP) == 0x02);       // Check STP condition
  I2CTCTL &= ~I2CTRX;                       // Master receiver
}


// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
  if (I2CDRB > 0x20) P1OUT |= 0x01;         // LED on
  else P1OUT &= ~0x01;                      // LED off
  U0CTL |= MST;                             // Master
  I2CTCTL |= I2CSTT + I2CSTP;               // Read, ST, SP (clears MST)
}
#pragma vector=PORT2_VECTOR
__interrupt void p2_isr(void)
{
  P2IFG = 0;
  I2CSA = 0x0C;                             // SMBus Alert response
  U0CTL |= MST;                             // Master
  I2CTCTL |= I2CSTT + I2CSTP;               // Read, ST, SP (clears MST)
  while ((I2CTCTL & I2CSTP) == 0x02);       // If Stop generated
  I2CSA = 0x4E;                             // Slave Address
}

When execution comes to transmit the third data byte, it halts in the final while loop(regardless of the value of I2CNDAT). It seems the bus never gets ready to transmit. When I check I2CTCTL register, the I2CSTT bit is not cleared after start condition. I2CSTP bit is also not cleared any time. I2CTCTL register remains constant. Moreover after start condition is sent, I2CBUSY bit is set but I2CBB bit never gets set. Also When I set MST bit  I2CSCLLOW bit is set. It seems something is going wrong in my initialization procedure but I couldn't figure it out. Could anyone help me with that?

  • The 1xx SPI implementation was so complex weird and clumsy that I implemented I2C in software on this chip. On the 54xx USCI modules, it is way easier to understand, better documented and easier to handle. Anyway...

    If I2CSTT is not cleared, the start condition (including slave address) is never sent. I don't know why. Maybe the slave holds the clock line low (or a missing pullup on the line does so). Maybe the master got a NAK and waits with clearing the STT bit until the NAKIFG bit has been cleared (the NAK situation recognized and handled), I don't know.
    If I2CSTT doesn't complete, I2CSTP obviously cannot be executed and it won't clear too.

    In any case, the transmitter is ready for the first byte as soon as STT bit is set in write mode. It does not mean that this byte will ever be sent. (if the addressing fails, it won't and is discarded at the next start condition)

    Anyway, sending the slave address is part of the start condition operation. No need to send it yourself. The hardware will take the content of the slave address register (don't write the R/W bit there, it is added depending on the I2CTRX bit.). The slave address is sent together with the start condition and STT bit will clear once both are sent.

    I don't know the hardware you're accessing, but it seems to me that the whole slave addressing is messed-up.

     

  • I2CSTT cleared and I2CBB is set, but on the scope I don`t see any clock pulses after that. Interesting thing is that several bytes (according to interrupts) are sent, but no on SCL and SDA lines.

    I am interfacing TMP100 device, but in future will need PCA8574A LCD driver.

  • Dmitrij Zylkov said:
    Interesting thing is that several bytes (according to interrupts) are sent, but no on SCL and SDA lines.

    Several? hmmm, the first interrupt should come immediately, even before the slave has acknowledged its addressing. So the hardware can immediately preoceed sending as soon as the slave has acknowledged the addressing.

    Dmitrij Zylkov said:
    I2CSTT cleared and I2CBB is set, but on the scope I don`t see any clock pulses after that.

    Do you see ANY clock pulses right after setting STT? What is the line state? Maybe it is permanently low? (Did you add a pullup to the line? I2C is open collector. Everyone is driving the line low if required, but nobody is driving it high). If the master releases the clock line but it stays low (for any reason), the master will pause operation until the line goes high again (is released from the slave, so the pullup can pull it high again). It seems that this doesn't happen.

  • I don`t see any slock after STT after wich SDA constantly low and SCL is high.

  • Dmitrij Zylkov said:
    I don`t see any slock after STT after wich SDA constantly low and SCL is high.

    Hmm, there are two possible explanations.

    First, the SDA line is always low for some reason. Then the hardware will detect a bus arbitration problem and won't start at all.
    The other possibility is that the hardware does not get a clock. Without a clock, the transfer stalls after pulling SDA low when SCL is high (start condition) and no further bytes can be sent (or rather, they will be sent with 0Hz).

  • In my opinion second explanation is more probable, because there is only one master.

  • Dmitrij Zylkov said:
    In my opinion second explanation is more probable, because there is only one master.


    Not if you forgot to apply a pullup to the lines. Then the hardware will detect lost arbitration too, even without the second master. I didn't write what is pulling SCL low. A master is one possibility. Without pullup, it's its own 'weight'. Ot a shortcut to GND.

**Attention** This is a public forum