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.

MSP430FR5849: I2C Transmit and receive with interrupts

Part Number: MSP430FR5849

Hi,
I am trying to build some simple routines upon the Driverlib library to send and receive data over I2C channel using interrupts.

The available examples are for transmit or receive only, so I attempted a merge of the interrupt routines, without full success.

It looks like the Tx portion works well, but I cannot manage to make the receive portion wrok as well.

Here is my interrupt routine:

#pragma vector=USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
{
  switch(__even_in_range(UCB0IV, 0x1E))
  {
  case 0x00: break;     // Vector 0: No interrupts break;
  case 0x02: break;     // Vector 2: ALIFG break;
  case 0x04:            // Vector 4: NACKIFG break;
    EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
    Ptr = 0;
    break;
  case 0x06: break;     // Vector 6: STT IFG break;
  case 0x08: break;     // Vector 8: STPIFG break;
  case 0x0a: break;     // Vector 10: RXIFG3 break;
  case 0x0c: break;     // Vector 14: TXIFG3 break;
  case 0x0e: break;     // Vector 16: RXIFG2 break;
  case 0x10: break;     // Vector 18: TXIFG2 break;
  case 0x12: break;     // Vector 20: RXIFG1 break;
  case 0x14: break;     // Vector 22: TXIFG1 break;
  case 0x16:            // Vector 24: RXIFG0 break;
    if(Ptr)
    {
      *Ptr++ = EUSCI_B_I2C_masterReceiveSingle(EUSCI_B0_BASE);   // Get RX data
      if(--Cnt == 0)
      {
        EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B0_BASE);
        Ptr = 0;
      }
    }
    break;
  case 0x18:            // Vector 26: TXIFG0 break;
    if(Cnt)                           // Check TX byte counter
    {
      EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B0_BASE, *Ptr++);
      Cnt--;                        // Decrement TX byte counter
    }
    else
    {
      EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
      Ptr = 0;
    }
    break;
  case 0x1c: break;     // Vector 30: clock low timeout break;
  case 0x1e: break;     // Vector 32: 9th bit break;
  default:
    break;
  }
}

The code to start a reception is:

void I2C_Sen_Read(int len, char * buf)
{
  EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, addr);
  EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);
  EUSCI_B_I2C_enable(EUSCI_B0_BASE);
  Cnt = len;
  Ptr = buf;
  EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT);
  EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT);
  EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
}

The Ptr variable is used to point to the buffer but also as an indication that the reception (or transmission) is complete.

The problem is that I see with a scope a train of clock pulses corresponding to one byte more than expected (i.e. I see two 8 bit+ack pulses if I ask for one byte read.

But the major problem is that the SDA and SCL lines remain low. It looks like the EUSCI_B_I2C_masterReceiveMultiByteStop is doing nothing.

Can someone help me?

Thank you.
Regards.
Mau.

  • Hi Maurizio
    When the SDA and SCL lines remain low? What's the slave device? Can you show me all the configuration code of the I2C?
  • Thanks for your answer.
    The initialization code is:

    void I2C_Sen_Init(void)
    {
      EUSCI_B_I2C_initMasterParam param;
      param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
      param.i2cClk = CS_getSMCLK();
      param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS;
      param.byteCounterThreshold = 0;
      param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
      EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, &param);
    }
    

    In the meanwhile I found an example that looked a little different and I changed my interrupt as:

    #pragma vector=USCI_B0_VECTOR
    __interrupt void USCIB0_ISR(void)
    {
      switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
      {
      case 0x00: break;                    // Vector 0: No interrupts break;
      case USCI_I2C_UCALIFG: break;        // Vector 2: ALIFG break;
      case USCI_I2C_UCNACKIFG:             // Vector 4: NACKIFG break;
        EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
        Ptr = 0;
        break;
      case USCI_I2C_UCSTTIFG: break;       // Vector 6: STT IFG break;
      case USCI_I2C_UCSTPIFG: break;       // Vector 8: STPIFG break;
      case USCI_I2C_UCRXIFG3: break;       // Vector 10: RXIFG3 break;
      case USCI_I2C_UCTXIFG3: break;       // Vector 14: TXIFG3 break;
      case USCI_I2C_UCRXIFG2: break;       // Vector 16: RXIFG2 break;
      case USCI_I2C_UCTXIFG2: break;       // Vector 18: TXIFG2 break;
      case USCI_I2C_UCRXIFG1: break;       // Vector 20: RXIFG1 break;
      case USCI_I2C_UCTXIFG1: break;       // Vector 22: TXIFG1 break;
      case USCI_I2C_UCRXIFG0:              // Vector 24: RXIFG0 break;
        if(--Cnt == 0)
          EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B0_BASE);
        *Ptr++ = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
        if(Cnt == 0)
        {
          EUSCI_B_I2C_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
          Ptr = 0;
        }
        break;
      case USCI_I2C_UCTXIFG0:              // Vector 26: TXIFG0 break;
        if(Cnt)                            // Check TX byte counter
        {
          EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B0_BASE, *Ptr++);
          Cnt--;                           // Decrement TX byte counter
        }
        else
        {
          EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
          success = true;
          Ptr = 0;
        }
        break;
      case USCI_I2C_UCBCNTIFG: break;      // Vector 28:
      case USCI_I2C_UCCLTOIFG: break;      // Vector 30: clock low timeout break;
      case USCI_I2C_UCBIT9IFG: break;      // Vector 32: 9th bit break;
      default:
        break;
      }
    }
    

    The major difference is that the EUSCI_B_I2C_masterReceiveMultiByteStop is called before the last EUSCI_B_I2C_masterReceiveMultiByteNext call.
    So probably it is just a marker to allow send the stop after the last byte.

    I still have the problem that even if I try to read one byte I see on the bus the address phase and two sobsequent byte read, followed by the stop.

    Moreover, I just noticed that if I have to read more bytes (let's say 5) the bus get stuck after the second read and both lines remain low.

    I continue investigating this issues, but any hint or help is really appreciated

  • Hi Maurizio

    Can you test the single read  and write code example on your borad.The examples can be found as below(you just change the device to MSP430FR5849) 

    If the example code works well you can combine them.