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.

MSP430G2252 I2C slave configuration - SCL not released

Other Parts Discussed in Thread: MSP430G2252

Hi all,
I'm working on MSP430G2252  to configure an I2C slave. I can't avoid that SCL line is held low by my slave : that cause a later answer of my slave 

I tried different options but none works. Here below are two different codes, and after than an images of I2c bus transaction. (First SCL line, below SDA line)

thaks in advance

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;            // Stop watchdog
  if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
  {
    while(1);                          // If calibration constants erased
                                       // do not load, trap CPU!!
  }
  BCSCTL1 = CALBC1_1MHZ;               // Set DCO
  DCOCTL = CALDCO_1MHZ;
  P1OUT = 0xC0;                        // P1.6 & P1.7 Pullups
  //P1REN |= 0xC0;                       // P1.6 & P1.7 Pullups
  P1DIR = 0xFF;                        // Unused pins as outputs
  P2DIR = 0xFF;                        // Unused pins as outputs
  USICTL0 = USIPE6+USIPE7+USISWRST;    // Port & USI mode setup
  USICTL1 = USII2C+USIIE+USISTTIE;     // Enable I2C mode & USI interrupts
  USICKCTL = USICKPL;                  // Setup clock polarity
  USICNT |= USIIFGCC;                  // Disable automatic clear control
  USICTL0 &= ~USISWRST;                // Enable USI
  USICTL1 &= ~USIIFG;                  // Clear pending flag
  __enable_interrupt();                // Enable interrupts.
  while(1)
  {
   }
}
//******************************************************
// USI interrupt service routine
//******************************************************
#pragma vector = USI_VECTOR
__interrupt void USI_TXRX (void)
{
  if (USICTL1 & USISTTIFG)             // Start entry?
  {

 P1OUT ^= LED1;    // Toggle P1.0 using exclusive-OR
     I2C_State = 2;                     // Enter 1st state on start
  }

  switch(I2C_State)
    {
      case 0: //Idle, should not get here
              break;

      case 2: //RX Address
              USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, RX Address
              USICTL1 &= ~USISTTIFG;   // Clear start flag
              I2C_State = 4;           // Go to next state: check address
              break;
        
      ..........................
     ......................... 
  
    }

  USICTL1 &= ~USIIFG;                  // Clear pending flags
}

--------------  other code

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;            // Stop watchdog
  if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
  {
    while(1);                          // If calibration constants erased
                                       // do not load, trap CPU!!
  }
  BCSCTL1 = CALBC1_1MHZ;               // Set DCO
  DCOCTL = CALDCO_1MHZ;
  P1SEL |= 0xC0;                  // I2C
  P1OUT = 0x80;                        // P1.6 & P1.7 Pullups
  P1REN |= 0x80;                       // P1.6 & P1.7 Pullups
  P1DIR = 0x80;                        // Unused pins as outputs
  P2DIR = 0xFF;                        // Unused pins as outputs
  USICTL0 = USIPE6+USIPE7+USISWRST;    // Port & USI mode setup
  USICTL1 = USII2C+USIIE+USISTTIE;     // Enable I2C mode & USI interrupts
  USICKCTL = USICKPL;                  // Setup clock polarity
  USICNT |= USIIFGCC + USISCLREL;      // Disable automatic clear control -- release SCL line
  USICTL0 &= ~USISWRST;                // Enable USI
  USICTL1 &= ~USIIFG;                  // Clear pending flag
  __enable_interrupt();                // Enable interrupts.
  while(1)
  {
  }
}

//******************************************************
// USI interrupt service routine
//******************************************************
#pragma vector = USI_VECTOR
__interrupt void USI_TXRX (void)
{
  if (USICTL1 & USISTTIFG)             // Start entry?
  {
      USICTL1 &= ~USISTTIFG;   // Clear start flag
      USICNT |= 0x08;
      USICNT |= USISCLREL; // Bit counter = 8, RX Address
      I2C_State = 4;
  }

  switch(I2C_State)
    {

      case 4: // Process Address and send (N)Ack
           dato = USISRL;
              USICTL0 |= USIOE;        // SDA = output
              USISRL = 0x00;         // Send Ack
              USICNT = (USICNT & 0xE0) + 0x01; // Bit counter = 8, RX Address
              //USICNT |= 0x01;          // Bit counter = 1, send (N)Ack bit
              //I2C_State = 6;         // just for address test
              I2C_State = 8;         // just for address test
              break;

       ...............

    }

  USICTL1 &= ~USIIFG;                  // Clear pending flags
}

 

 

 

  • Hi Gianpiero,

    your issue is generate from DCO clock setting, I viewed in your image that master probably work 400Kbps, but with DCO slave setting to 1MHz is too slow for do interrupt routine.

    You can try put DCO to 16MHz, and issue should be resolved.

    You know me of result.

    Bye

    Paolo Z.

**Attention** This is a public forum