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.

CCS/MSP430FR5994: How to use LMP0 in I2C communication?

Part Number: MSP430FR5994

Tool/software: Code Composer Studio

Hello Everyone,

I am implementing I2C communication. First, I am transmitting 5 bytes of data to my slave device. and after that I am receiving the response.

I already know the response, so I can compare the results. I am getting the expected response from the slave device.

My transmit function is working properly. i.e  START--slaveAddress--Write--Ack--data1--Ack--data2--Ack--data3--Ack--data4--Ack--data5--Ack--STOP


But,

In my receive function, I am having problem that I can't stop this communication, I have written the stop I2C command, but it is not actually going to that command.

Let suppose I am expecting 3 bytes in response from the slave device. Then I am getting the following result.

START--SlaveAddress--READ--Acq--Data1--Acq--Data2--Acq--Data3--Acq--Unknown

 

I am checking the results in logic analyzer. I got to know from some other forum that I am not using LMP correctly.

I am attaching my code below, I shall be very thankful if someone can help.

Thank you

#include <msp430.h>


char TXData[5] = { 0x5A, 0xCF, 0x00 };        //APDU initialization
volatile unsigned char RXData[3];                                     // To save the received data
unsigned char SlaveAddress = 0x48;                          // slave address
volatile unsigned char TXByteCtr;
volatile unsigned char TxByteCnt = 0;
volatile unsigned char RxByteCnt = 0;
unsigned char Rx;                                                 // To enable reception
void Transmit(void);
void Recieve(void);
short crc_ret;
//short final;
unsigned short crc16_x25(char* pData, int length)
{
    int i;
    unsigned short wCrc = 0xffff;
    while (length--) {
        wCrc ^= *(unsigned char *)pData++ << 0;
        for (i=0; i < 8; i++)
            wCrc = wCrc & 0x0001 ? (wCrc >> 1) ^ 0x8408 : wCrc >> 1;
    }
    return wCrc ^ 0xffff;
}
int main(void)
{

    WDTCTL = WDTPW | WDTHOLD;
    //while(1);
    // Configure GPIO
    P8OUT |= BIT0;                                          // Clear P8.0 output latch
    P8DIR |= BIT0;
    P7SEL0 |= BIT0 | BIT1;
    P7SEL1 &= ~(BIT0 | BIT1);


    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    // Configure USCI_B2 for I2C mode
    UCB2CTLW0 |= UCSWRST;                                        // put eUSCI_B in reset state
    UCB2CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK;              // I2C master mode, SMCLK
    UCB2BRW = 0x8;                                              // baudrate = SMCLK / 8
    UCB2CTLW0 &= ~UCSWRST;                                      // clear reset register
    UCB2IE |= UCTXIE0 | UCNACKIE | UCRXIE0;                     // transmit, Receive and NACK interrupt enable

    crc_ret = crc16_x25(TXData, (sizeof(TXData) - 2));   // Calling CRC function

    TXData[3] = (char)crc_ret;
    TXData[4] = (char)((crc_ret&0xFF00)>>8);

    while(1)
    {
       __delay_cycles(2000);                                    // Delay between transmissions
        UCB2I2CSA = SlaveAddress;                               // configure slave address
        TXByteCtr = 1;                                          // Load TX byte counter
        Transmit();                                             //Implementing the transmit function
        __delay_cycles(2000);
        Rx = 1;
        Recieve();                                              //Implementing the receive function
        __delay_cycles(2000);

    }
}

#pragma vector = EUSCI_B2_VECTOR
__interrupt void USCI_B2_ISR(void)

{

   switch(__even_in_range(UCB2IV, USCI_I2C_UCBIT9IFG))
    {
        case USCI_NONE:          break;                             // Vector 0: No interrupts
        case USCI_I2C_UCALIFG:   break;                                 // Vector 2: ALIFG
        case USCI_I2C_UCNACKIFG:                                    // Vector 4: NACKIFG
            UCB2CTLW0 |= UCTXSTT;                                   // resend start if NACK
            break;
        case USCI_I2C_UCSTTIFG:  break;                                 // Vector 6: STTIFG
        case USCI_I2C_UCSTPIFG:  break;                                 // Vector 8: STPIFG
        case USCI_I2C_UCRXIFG3:  break;                                 // Vector 10: RXIFG3
        case USCI_I2C_UCTXIFG3:  break;                                 // Vector 12: TXIFG3
        case USCI_I2C_UCRXIFG2:  break;                                 // Vector 14: RXIFG2
        case USCI_I2C_UCTXIFG2:  break;                                 // Vector 16: TXIFG2
        case USCI_I2C_UCRXIFG1:  break;                                 // Vector 18: RXIFG1
        case USCI_I2C_UCTXIFG1:  break;                                 // Vector 20: TXIFG1
        case USCI_I2C_UCRXIFG0:                                     // Vector 22: RXIFG0

            if (Rx < 3)                                          // Check RX byte counter
            {
                RXData[RxByteCnt]= UCB2RXBUF;                       // Load TX buffer
                RxByteCnt++;
                Rx++;                                        // Decrement TX byte counter
                __bic_SR_register_on_exit(LPM0_bits);               // Exit LPM0
            }
            else
            {
                UCB2CTLW0 |= UCTXSTP;                               // I2C stop condition
                UCB2IFG &= ~UCRXIFG;                                // Clear USCI_B2 RX int flag
                __bic_SR_register_on_exit(LPM0_bits);               // Exit LPM0
            }
            break;
        case USCI_I2C_UCTXIFG0:                                     // Vector 24: TXIFG0


            if (TXByteCtr < (sizeof(TXData) + 1))                    // Check TX byte counter
            {
                UCB2TXBUF = TXData[TxByteCnt];                       // Load TX buffer
                TxByteCnt++;
                TXByteCtr++;                                        // Decrement TX byte counter
                __bic_SR_register_on_exit(LPM0_bits);               // Exit LPM0
            }
            else
            {
                TxByteCnt = 0;

                UCB2CTLW0 |= UCTXSTP;                               // I2C stop condition
                UCB2IFG &= ~UCTXIFG;                                // Clear USCI_B2 TX int flag
                __bic_SR_register_on_exit(LPM0_bits);               // Exit LPM0
            }
            break;
        case USCI_I2C_UCBCNTIFG: break;                              // Vector 26: BCNTIFG
        case USCI_I2C_UCCLTOIFG: break;                             // Vector 28: clock low timeout
        case USCI_I2C_UCBIT9IFG: break;                             // Vector 30: 9th bit
        default: break;
    }
}


void Transmit(void)
{
    while (UCB2CTLW0 & UCTXSTP);                            // Ensure stop condition got sent
    UCB2CTLW0 |= UCTR | UCTXSTT;                            // I2C TX, start condition
    __bis_SR_register(LMP0 + GIE);                     // Enter LPM0 w/ interrupts
                                                            // Remain in LPM0 until all data
                                                            // is TX'd

}

void Recieve(void)
{

    while (UCB2CTLW0 & UCTXSTP);                            // Ensure stop condition got se
    UCB2CTLW0 &= ~UCTR;
    UCB2CTLW0 |= UCTXSTT;

    __bis_SR_register(LMP0 +GIE);                     // Enter LPM0 w/ interrupts//start condition;
                                                  

  • Hello Raza,

    I'm not able to review your code right now but I wanted to let you know that there is a standard I2C master software example for the MSP430FR5994 here: http://dev.ti.com/tirex/explore/node?node=ABODO-OgEMQt.wyPrGemuw__IOGqZri__LATEST 

    I would compare your code to that example, or even test that example with your slave device and see if it's working and adjust from there.  

    Thanks,

    JD

  • Thank you so much for your reply. I look forward to hear from you. Meanwhile I try to understand the example you sent. Thank you
  • Hey Raza,

    Looking at your code, it looks like you are waking every single time you send or receive even a single byte.  I think you are wanting to only wake after all 3 bytes are sent.  If so, I think you need to remove lines 95 and 112 above.  This way you only wake the MCU once the entire packet has been received.  

    Thanks,

    JD

  • Hi,

    Thank you so much for your reply.

    I did as you said, but the response remains the same.

    If you see at the code (in the transmit section), the program execute the if-else statement. First, it goes into the if section, and send all the bytes and when the condition doesn't satisfy, it goes into the else section and stop the I2C communication (Line 116 to Line 120). But when it comes to Receive section, it goes into the if-section and executes the commands (Line 92 to Line 95), but after that it doesn't go into the else-section (Line 99 to Line 101). That's why the communication doesn't stop and in logic analyzer it shows like this : START-SlaveAddress-Read-ACK-Data1-ACQ-Data2-ACQ-Data3-ACQ but I think it should be like this: START-SlaveAddress-Read-ACK-Data1-ACQ-Data2-ACQ-Data3-NACK-STOP.


    And if I write the stop condition at line 149 instead of line 99. Then the communication stops, but with incomplete data received.


    Thank you

    Raza

  • Hi.

    Thank you so much for your help. The example you mentioned solved my issue. I just had to edit few lines and then it worked. Thank you!

    Best,

    Raza

  • Hey Raza,

    Glad you were able to find the Resource explorer code examples useful and were able to fix the problem.  

    Thanks,

    JD

**Attention** This is a public forum