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.

Problem with I2c interfacing of MSP430

Other Parts Discussed in Thread: MSP430F5529, MSP430F5436

During the interfacing of MSP430 with the slave DS2764 (battery protection IC), the device is unable to send a START bit to the slave. The SCL and SDA lines are held line constantly but the SCL is pulled low after the Start condition execution step and it remains low.   

Below is the code written for the same;

#include <msp430.h>

int i=0,mcnt=0,flag=0;
unsigned char Maddr= 0x0C ;
int a[2];

/*..............................................................................
// Transmit Initialization function
// arguments :
slave_add= This is the 7 bit slave address of DS2764
prescale = pass 0x12 as this argument for 100kHz clock

Hardware connections:

SDA - Pin 3.1 - Board pin number 34
SCL - Pin 3.2 - Board pin number 35

//............................................................................*/
void tx_init(unsigned char slave_add,unsigned char prescale)
{
P3SEL |= 0x06; // Assign I2C pins to USCI_B0
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = prescale; // fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = slave_add; // Slave Address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCB0IE |= UCTXIE+UCRXIE; // Enable TX and RX interrupt
}

/*..............................................................................
// Read begin function
// arguments :
None. However, define Maddr as a gloabl unsigned char where Maddr= Memory address of DS to be read.
Also, make global int mcnt=0

Hardware connections:

SDA - Pin 3.1 - Board pin number 34
SCL - Pin 3.2 - Board pin number 35

//............................................................................*/
void read_begin()
{

while(UCB0CTL1 & UCTXSTP); //Ensure that the STOP condition got sent.
UCB0CTL1 |= UCTR + UCTXSTT; //Enable transmission and generate START condition.
mcnt=1; // To generate Maddr out on SDA line (inside interrupt)
}

void main()
{
WDTCTL=WDTPW+WDTHOLD;
float volt=0.0;
tx_init(0x34, 12);
a[0]=a[1]=0;
read_begin();

while(!flag);

// a[1] is Voltage LSB and a[0] is voltage MSB;
// store it in an integer called volt (defined above)
volt += (float)((long)(a[0] & 0x7F) << 3) * 0.00488;
volt += (float)(a[1] >> 5) * 0.00488;

//volt=volt*1000;
//printf("%d", volt); #FUC*_IAR

__no_operation();
}

//.............................................................................
// Interrupt vector for the USCI_B0 Module
//.............................................................................
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
switch(__even_in_range(UCB0IV,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: // Vector 10: RXIFG

if(i<3)
{
a[i] = UCB0RXBUF;
i++;
}
else
{
UCB0CTL1 |= UCTXSTP; //All Data received (2 bytes). STOP condition generated.
flag=1;
}
break;


case 12: // Vector 12: TXIFG
if(mcnt == 1) // To just send the Maddr to DS2764
{
UCB0CTL1 &= ~UCTR; // Shift to receive mode
UCB0CTL1 |= UCTXSTT; //Generate continuaous start condition for next start
UCB0TXBUF = Maddr; //send Maddr
mcnt=0;

}

break;

default: break;
}
}

  • Setting UCTXSTT along with UCTR immediately sets TXIFG and calls the ISR. Before your code has a chance to set mcnt=1.
    Also, all global vars used in main as well as in an ISR (like mcnt) need to be declared volatile, to ensure access exactly when and as often as they are accessed in the source code. Else the compiler may make optimizations that break your assumed code flow. (the compiler can't know when an interrupt will happen)
  • Thank you so much for your reply.
    I set UCTXSTT and UCTR as different lines of code and made the global variables volatile, still the old results persist. Could there be any other problem in the code?
  • I modified the code. I am now getting the output only if i put break point at the receive mode statement ( UCB0CTL1 &= ~UCTR;) only after a certain wait period. Also the output is shown only sometimes and not at all tries. please do help me out on this.

    Here is the code:


    #include "msp430x54x.h"

    volatile int i=0,flag1=0,b;
    unsigned volatile char Maddr= 0x0C ;
    int a[5]={0};

    void tx_init(unsigned char slave_add,unsigned char prescale)
    {
    P3SEL |= 0x06; // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = prescale; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = slave_add; // Slave Address
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    UCB0IE |= UCTXIE+UCRXIE; // Enable TX and RX interrupt
    }

    void main()
    {
    WDTCTL=WDTPW+WDTHOLD;
    tx_init(0x34, 12);

    //UCB0CTL1 |= UCTR;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;


    __bis_SR_register(GIE +LPM0_bits);
    //__no_operation();

    }


    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    switch(__even_in_range(UCB0IV,12))
    {
    case 0: break; // Vector 0: No interrupts
    case 2: break; // Vector 2: ALIFG
    case 4:
    b=0;

    break; // Vector 4: NACKIFG
    case 6:

    // UCB0IFG &= ~UCSTTIFG;

    break; // Vector 6: STTIFG
    case 8: break; // Vector 8: STPIFG
    case 10: // Vector 10: RXIFG

    // while(!(UCB0IFG&UCRXIFG))
    a[i++] = UCB0RXBUF;


    break;
    case 12: // Vector 12: TXIFG
    if(flag1 == 0)
    { flag1=1;
    UCB0TXBUF = Maddr;
    UCB0CTL1 &= ~UCTR; // receive mode
    UCB0CTL1 |= UCTXSTT; // reapeated start

    }
    break;
    default: break;
    }
    }

     

  • You changed more than just splitting th eUCTR and UCTXSTT into two. Whcih isn't necessary anyway. What I meant was that if UCTR is set (before or at the same time), setting UCTXSTT will instantly set UCTXIFG.
    So what happens isthat you set UCTXSTT, the USCI begins sending the start bit and the iSR is called. In whgich you write to TXBUF (which is good) and clear UCTR and set UCTXSTT (which is bad at this moment, as the start byte hasn't been sent and the data byte has not started sending).

    Change it this way:
    if(!flag)
    { flag = 1; UCB=TXBUF = Maddr;}
    else
    { UCB0CTL1 &=UCTR; UCB0CTL1 |= UCTXSTT;)

    This delays the repeated start until the start byte has been sent and the address byte has started sending, before the repeated start is queued.
    However, you should also check for a NACKIFG, or your code will hang if the slave doesn't answer (no second TX interrupt will be generated and the system will wait forever)
  • Hey thank you very much for your reply. I tried the code you suggested, but the problem still persists. I am reading the voltage data of the battery from the battery protection IC (DS2764) which is interfaced with MSP430. The voltage being read at the MSP registers is different at different times of execution even if the battery voltage has not changed much. Also at every execution the register values are not shown. It shows zero values many times. Is this because of a mistake in the code or due to improper response by DS2764. I would really appreciate if you can help me with this.

    Thank you

    Regards,

    Nanditha 

  • //                                /|\  /|\
    //               MSP430F5529      10k  10k     MSP430F5529
    //                   slave         |    |        master
    //             -----------------   |    |   -----------------
    //           -|XIN  P3.0/UCB0SDA|<-|----+->|P3.0/UCB0SDA  XIN|-
    //            |                 |  |       |                 | 32kHz
    //           -|XOUT             |  |       |             XOUT|-
    //            |     P3.1/UCB0SCL|<-+------>|P3.1/UCB0SCL     |
    //            |                 |          |             P1.0|--> LED
    //

    Nanditha:

    One of the things I have forgotten in the past, was to add the pull-up resistors on the SCL and SDA lines. Above is an example of that on two connected F5529 processors. Do you have pull-ups?

     

     

  •  I have pull up resistance of 4.7K on both the SCL and SDA line. 

  • Can you please let me know if there is any possible error in the code. 

  • Hey. I made a few changes in the code as shown below.

    Now i am able to read the voltage and temperature values when I put a break point at the receive mode stage. During run to cursor execution the clock and data line go low. after a few seconds the data line is pulled up. If i read the value after the data line goes low, junk values are displayed. But if I read the values before the data line goes low,values of the registers are read. This looks like a timing problem between the master (MSP430) and slave (DS2764). Can you please tell me changes I can make to overcome this timing problem. 

    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    switch(__even_in_range(UCB0IV,12))
    {
    case 0: break; // Vector 0: No interrupts
    case 2: break; // Vector 2: ALIFG
    case 4:
    b=0;

    break; // Vector 4: NACKIFG
    case 6:

    // UCB0IFG &= ~UCSTTIFG;

    break; // Vector 6: STTIFG
    case 8: break; // Vector 8: STPIFG
    case 10: // Vector 10: RXIFG

    // while(!(UCB0IFG&UCRXIFG))


    a[i++] = UCB0RXBUF;


    if(i==5)
    {

    UCB0CTL1 |=UCTXNACK; //NACK ganaration
    UCB0CTL1 |= UCTXSTP; // STOP condition.
    UCB0IE &=~ UCTXIE;
    UCB0IE &= ~UCRXIE;

    }

    break;
    case 12: // Vector 12: TXIFG
    if(flag1 == 0)
    { flag1=1;
    UCB0TXBUF = Maddr;
    UCB0CTL1 &= ~UCTR; // receive mode
    UCB0CTL1 |= UCTXSTT; // reapeated start

    }
    break;
    default: break;
    }
    }

    Thank you

  • You should not forget that the debugger, while stopping the CPU and maybe the MSP's internal clocks, it doesn't stop the world turning.
    IN your TX case, you write Maddr to TXBUF but at the same time, you set TXSTT. The first TX interrupt comes when the USCI sends start condition and start byte. So when the start byte has been sent, the USCI doesn't know whether to send Maddr or to do a repeated start. That's why I suggested using the flag: on first TX interrupt (flag=0) Maddr is written to TXBUF, and when the USCI has started sending Maddr and requests the next byte (flag=1) with another ISR call, UCTR is cleared and TXSTT is set instead, so instead of another byte after Maddr, a repeated start ofr a read is sent.
    I didn't find anythign special about the I2C timing, so things should work. One thing to mention is that when you get the RX interrupt for a byte, reception of the next byte has already begun. So if you want to receive n bytes, you need to set TXSTP when you get the interrupt for byte n-1. Else you're getting one excess byte before the stop is sent. This may cause side-effects, enlarge transmission time (even if you can ignore the excess byte) and makes it difficult to receive just a single byte.
    The eUSCI on the newest MSPs provides a counter to pre-define the number of bytes to receive, so NACK and STOP are automatically generated after the requested number of bytes.
    From looking at your code, I don't see what's going wrong. It would be interesting to analyze the actual transfer on the I2C lines.
    First with a scope (to ensure that rising/fall times are met) but then with a logic analyzer. I recommend the "Logic" from www.saleae.com. Unfortunately, their original Logic8 with 8 digital lines is no longer availabe, the Logic4 with 1 analog channel is same price but has 4 channels less. Well, for most experiments, it is still enough, and the analog channel allows for analyzing rise times etc. Well, 6MSPS aren't much for analog, but in many cases you can spare the scope.
  • The code for interfacing the MSP430 with DS2764(Battery protection ic) was successfully running. The code for the same is given below. But after many successful execution, with the same code and  connections, the device is not entering the interrupt.. Please help me with the same.


    #include "msp430x54x.h"

    int i=0,flag=0,b;
    volatile unsigned char Maddr = 0x0C;

    int a[5]={0};

    void tx_init(volatile unsigned char slave_add,volatile unsigned char prescale)
    {
    P3SEL |= 0x06; // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = prescale; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = slave_add; // Slave Address
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    UCB0IE |= UCTXIE + UCRXIE; // Enable TX and RX interrupt
    }

    void main()
    {
    WDTCTL=WDTPW+WDTHOLD;
    tx_init(0x34, 12);



    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;


    __bis_SR_register(GIE +LPM0_bits);
    __no_operation();
    }



    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    switch(__even_in_range(UCB0IV,12))
    {
    case 0: break; // Vector 0: No interrupts
    case 2: break; // Vector 2: ALIFG
    case 4:
    b=0;

    break; // Vector 4: NACKIFG
    case 6:

    // UCB0IFG &= ~UCSTTIFG;

    break; // Vector 6: STTIFG
    case 8: break; // Vector 8: STPIFG
    case 10: // Vector 10: RXIFG


    a[i++] = UCB0RXBUF;




    if(i==6)
    {

    UCB0CTL1 |=UCTXNACK; //NACK ganaration
    UCB0CTL1 |= UCTXSTP; // STOP condition.
    UCB0IE &=~ UCTXIE;
    UCB0IE &= ~UCRXIE;

    }

    break;
    case 12: // Vector 12: TXIFG
    if(!flag)
    {
    flag = 1;
    UCB0TXBUF = Maddr;
    }
    else
    {
    UCB0CTL1 &= ~UCTR;
    UCB0CTL1 |= UCTXSTT;
    }


    break;
    default: break;
    }
    }

  • The code for interfacing the MSP430 with DS2764(Battery protection ic) was successfully running. The code for the same is given below. But after many successful execution, with the same code and connections, the device does not enter the interrupt at all sometimes. Please help me with the same
    Here I am also trying to read the same register continuously by re-initializing the flag to 0, but after reading the first set of data, at i=3 it is not entering the read interrupt.

    #include "msp430x54x.h"

    int i=0,flag=0,b;
    unsigned char Maddr = 0x0C;

    int a[10]={0};

    void tx_init(unsigned char slave_add,unsigned char prescale)
    {
    P3SEL |= 0x06; // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = prescale; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = slave_add; // Slave Address
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    UCB0IE |= UCTXIE + UCRXIE; // Enable TX and RX interrupt
    }

    void main()
    {
    WDTCTL=WDTPW+WDTHOLD;
    tx_init(0x34, 12);
    __bis_SR_register(GIE);

    while(1)
    {

    if(flag==0)
    {
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;
    }

    }

    __no_operation();
    }



    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    switch(__even_in_range(UCB0IV,12))
    {
    case 0: break; // Vector 0: No interrupts
    case 2: break; // Vector 2: ALIFG
    case 4:
    b=1;

    break; // Vector 4: NACKIFG
    case 6:

    // UCB0IFG &= ~UCSTTIFG;

    break; // Vector 6: STTIFG
    case 8: break; // Vector 8: STPIFG
    case 10: // Vector 10: RXIFG


    a[i++] = UCB0RXBUF;


    if(i%2==0 && i>0)
    {

    UCB0CTL1 |=UCTXNACK; //NACK ganaration
    UCB0CTL1 |= UCTXSTP; // STOP condition.
    // UCB0IE &=~ UCTXIE;
    // UCB0IE &= ~UCRXIE;
    flag=0;


    }

    break;
    case 12: // Vector 12: TXIFG
    if(!flag)
    {

    UCB0TXBUF = Maddr;

    flag = 1;

    }

    else
    {
    UCB0CTL1 &= ~UCTR;
    UCB0CTL1 |= UCTXSTT;
    }



    break;
    default: break;
    }
    }
  • Below is the DS2764 code to interface with MSP430. I have used a delay in the interrupt without which the code does not work. Can you please tell me how to get the code to work without this delay. Also this code works sometime and dosent sometime for the same hardware. Could there be any flaw in this code?

    #include "msp430x54x.h"

    int i=0,flag=0,b;
    int flag_type;
    unsigned char Maddr;
    int flag1=0;
    char a[10]={0};
    float voltage[5],current[5],current_acc[50],temp[5];

    void tx_init(unsigned char slave_add,unsigned char prescale)
    {
    P3SEL |= 0x06; // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = prescale; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = slave_add; // Slave Address
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    UCB0IE |= UCTXIE + UCRXIE; // Enable TX and RX interrupt
    flag=0;
    }

    void main()
    {
    WDTCTL=WDTPW+WDTHOLD;

    __bis_SR_register(GIE);

    while(1)
    {
    int j=0;

    while(i<10)
    {
    tx_init(0x34, 12);
    Maddr=0x0C;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 0);

    tx_init(0x34, 12);
    Maddr=0x0D;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 1);

    }
    i=0;

    for(j=0;j<5;j++)
    {
    voltage[j]=0;
    voltage[j] += (float)((unsigned short int)(a[j*2] & 0x7F) << 3) * 0.00488;
    voltage[j] += (float)(a[j*2 + 1] >> 5) * 0.00488;

    }

    while(i<10)
    {
    tx_init(0x34, 12);
    Maddr=0x0E;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 0);

    tx_init(0x34, 12);
    Maddr=0x0F;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 1);

    }
    i=0;
    j=0;
    for(j=0;j<5;j++)
    {
    current[j]=0;
    current[j] += (float)((unsigned short int)(a[j*2] & 0x7F) << 5) * 0.625;
    current[j] += (float)(a[j*2 + 1] >> 3) * 0.625;
    }


    __no_operation();

    }
    }
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    switch(__even_in_range(UCB0IV,12))
    {
    case 10:
    a[i++] = UCB0RXBUF;
    __delay_cycles(100);
    flag=2;
    UCB0IE &=~UCRXIE;
    // UCB0CTL1 |= UCTR;
    break;
    case 12: // Vector 12: TXIFG
    if(flag==0)
    {

    UCB0TXBUF = Maddr;
    flag = 1;
    }

    else if(flag==1)
    {
    UCB0CTL1 &= ~UCTR;
    UCB0CTL1 |= UCTXSTT;
    }
    else if(flag==2)
    {
    UCB0CTL1 |=UCTXNACK; //NACK ganaration
    UCB0CTL1 |= UCTXSTP; // STOP condition.
    //while(UCRXIFG);
    UCB0IE &=~UCTXIE;

    }



    break;
    default: break;
    }
    }

  • Hey,

    Below is the working code interfacing MSP430 with DS2764. But in this code i have used a delay cycle inside the interrupt. Without the delay cycle the code does not run, only the first set of values are obtained. The code does not run till the end.  Can you please help me modify the code such that it can run successfully without the delay too.

    //
    //#include "msp430x54x.h"
    //
    //int i=0,flag=0,b;
    //unsigned char Maddr = 0x0C;
    //int count=1;
    //char a[10]={0};
    //
    //void tx_init(unsigned char slave_add,unsigned char prescale)
    //{
    // P3SEL |= 0x06; // Assign I2C pins to USCI_B0
    // UCB0CTL1 |= UCSWRST; // Enable SW reset
    // UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    // UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    // UCB0BR0 = prescale; // fSCL = SMCLK/12 = ~100kHz
    // UCB0BR1 = 0;
    // UCB0I2CSA = slave_add; // Slave Address
    // UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    // UCB0IE |= UCTXIE + UCRXIE; // Enable TX and RX interrupt
    //}
    //
    //void main()
    //{
    // WDTCTL=WDTPW+WDTHOLD;
    // tx_init(0x38, 12);
    // __bis_SR_register(GIE);
    //
    // // while(1)
    // // {
    //
    // if(flag==0)
    // {
    // while(UCB0CTL1 & UCTXSTP);
    // UCB0CTL1 |= UCTR;
    // UCB0CTL1 |= UCTXSTT;
    // }
    //
    // // }
    //
    // __no_operation();
    // }
    //
    //
    //
    // #pragma vector = USCI_B0_VECTOR
    //__interrupt void USCI_B0_ISR(void)
    //{
    // switch(__even_in_range(UCB0IV,12))
    // {
    // case 0: break; // Vector 0: No interrupts
    // case 2: break; // Vector 2: ALIFG
    // case 4:
    // b=1;
    //
    // break; // Vector 4: NACKIFG
    // case 6:
    //
    // // UCB0IFG &= ~UCSTTIFG;
    //
    // break; // Vector 6: STTIFG
    // case 8: break; // Vector 8: STPIFG
    // case 10: // Vector 10: RXIFG
    //
    // // while(!(UCB0IFG&UCRXIFG))
    // // if (i<3)
    // // {
    // a[i++] = UCB0RXBUF;
    //
    //
    // // }
    // // else
    // // {
    // // UCB0CTL1 |= UCTXSTP; //All Data received. STOP condition generated.
    // // __bic_SR_register_on_exit(LPM0_bits);
    // // }
    //
    // if(i%2==0 && i>0)
    // {
    //
    // UCB0CTL1 |=UCTXNACK; //NACK ganaration
    // UCB0CTL1 |= UCTXSTP; // STOP condition.
    // // UCB0IE |= UCTXIE;
    // flag=0;
    // // count++;
    // // if(count%2==0&&count%4!=0)
    // // Maddr=0x0e;
    // // else
    // // {
    // // if(count%3==0)
    // // Maddr=0x18;
    // // else
    // // Maddr==0x0c;
    // // }
    //
    // // UCB0IE &= ~UCRXIE;
    //
    //
    //
    // }
    //
    // break;
    // case 12: // Vector 12: TXIFG
    // if(!flag)
    // {
    //
    // UCB0TXBUF = Maddr;
    // //UCB0IE |=UCRXIE;
    // flag = 1;
    // // UCB0IE &= ~UCTXIE;
    // }
    //
    // else
    // {
    // UCB0CTL1 &= ~UCTR;
    // UCB0CTL1 |= UCTXSTT;
    // }
    // // if (flag == 0)
    // // {
    // // flag = 1;
    // // UCB0TXBUF = Maddr;
    // // UCB0CTL1 &= ~UCTR; // receive mode
    // // UCB0CTL1 |= UCTXSTT; // reapeated start
    // // }
    // // else
    // // {
    // // UCB0CTL1 |= UCTXSTP; //All Data sent. STOP condition generated.
    // // __bic_SR_register_on_exit(LPM0_bits);
    // // }
    //
    //
    // break;
    // default: break;
    // }
    //}

    #include "msp430x54x.h"
    #include <stdint.h>

    int i=0,flag=0,b;
    int flag_type;
    unsigned char Maddr;
    int count=1;
    char a[10]={0};
    float voltage[5],current[5],current_acc[5],temp[5];

    void tx_init(unsigned char slave_add,unsigned char prescale)
    {
    P3SEL |= 0x06; // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = prescale; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = slave_add; // Slave Address
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    UCB0IE |= UCTXIE + UCRXIE; // Enable TX and RX interrupt
    flag=0;
    }

    void main()
    {
    WDTCTL=WDTPW+WDTHOLD;

    __bis_SR_register(GIE);

    //
    // tx_init(0x38, 12);
    // Maddr=0x0C;
    // while(UCB0CTL1 & UCTXSTP);
    // UCB0CTL1 |= UCTR;
    // UCB0CTL1 |= UCTXSTT;
    //

    while(i<10)
    {
    tx_init(0x38, 12);
    Maddr=0x0C;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 0);

    tx_init(0x38, 12);
    Maddr=0x0D;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 1);

    }
    i=0;
    int j=0;
    for(j=0;j<5;j++)
    {
    voltage[j]=0;
    voltage[j] += (float)((unsigned short int)(a[j*2] & 0x7F) << 3) * 0.00488;
    voltage[j] += (float)(a[j*2 + 1] >> 5) * 0.00488;
    }

    while(i<10)
    {
    tx_init(0x38, 12);
    Maddr=0x0E;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 0);

    tx_init(0x38, 12);
    Maddr=0x0F;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 1);

    }
    i=0;
    j=0;
    for(j=0;j<5;j++)
    {
    current[j]=0;
    uint8_t r2=0;
    uint8_t rx=0;
    uint16_t r1=0;
    r2=a[j*2];
    rx=a[j*2 + 1];


    rx=rx & 0xF8;
    uint8_t t=0;
    t=r2 & 0x80;
    if(t)
    {
    r1=(uint16_t)(rx);
    r1= (r1 ^ 0x00FF)+ 0x0008;
    r2= ~r2;
    rx=~rx + 0x08;

    r1=(r1 & 0x0100)>>8;
    r2+=r1;

    current[j] += -(float)(rx >> 3) * 0.625;
    current[j]+= -(float)((uint16_t)(r2 & 0x7F) << 5) * 0.625;
    }
    else
    {
    current[j] += (float)((unsigned short int)(a[j*2] & 0x7F) << 5) * 0.625;
    current[j] += (float)(a[j*2 + 1] >> 3) * 0.625;
    }
    }


    while(i<10)
    {
    tx_init(0x38, 12);
    Maddr=0x18;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 0);

    tx_init(0x38, 12);
    Maddr=0x19;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 1);

    }
    i=0;
    j=0;
    for(j=0;j<5;j++)
    {
    temp[j]=0;
    temp[j] += (float)((unsigned short int)(a[j*2] & 0x7F) << 3) * 0.125;
    temp[j] += (float)(a[j*2 + 1] >> 5) * 0.125;
    }

    while(i<10)
    {
    tx_init(0x38, 12);
    Maddr=0x10;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 0);

    tx_init(0x38, 12);
    Maddr=0x11;
    while(UCB0CTL1 & UCTXSTP);
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT;

    while(i%2 == 1);

    }
    i=0;
    j=0;
    for(j=0;j<5;j++)
    {
    current_acc[j]=0;
    uint8_t r2=0;
    uint8_t rx=0;
    uint16_t r1=0;
    r2=a[j*2];
    rx=a[j*2 + 1];



    uint8_t t=0;
    t=r2 & 0x80;
    if(t)
    {
    r1=(uint16_t)(rx);
    r1= (r1 ^ 0x00FF)+ 0x0008;
    r2= ~r2;
    rx=~rx + 0x08;

    r1=(r1 & 0x0100)>>8;
    r2+=r1;

    current_acc[j] += -(float)((unsigned short int)(a[j*2] & 0x7F) << 8) * 0.25;
    current_acc[j] += -(float)(a[j*2 + 1]) * 0.25;
    }

    else{
    current_acc[j] += (float)((unsigned short int)(a[j*2] & 0x7F) << 8) * 0.25;
    current_acc[j] += (float)(a[j*2 + 1]) * 0.25;
    }
    }

    while(1);

    }

    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    switch(__even_in_range(UCB0IV,12))
    {
    case 10:
    a[i++] = UCB0RXBUF;
    // __delay_cycles(1000);
    flag=2;
    UCB0IE &=~UCRXIE;
    break;
    case 12: // Vector 12: TXIFG
    if(flag==0)
    {

    UCB0TXBUF = Maddr;
    flag = 1;

    }

    else if(flag==1)
    {
    UCB0CTL1 &= ~UCTR;
    UCB0CTL1 |= UCTXSTT;
    }
    else if(flag==2)
    {
    UCB0CTL1 |=UCTXNACK; //NACK ganaration
    UCB0CTL1 |= UCTXSTP; // STOP condition.
    //while(UCRXIFG);
    UCB0IE &=~UCTXIE;

    }


    break;
    default: break;
    }
    }

  • The code has some racing conditions.
    You start a transfer, then wait for TXSTP to clear. But during the transfer, TXSTP is clear and only set at the end of the transfer. So you don't wait. It's better to check for a flag set in the ISR (indicating that the end is reached and TXSTOP has been set) before proceeding, THEN wait for TXSTP to get cleared.
    flag needs to be declared volatile, when main reads it whiel it is changed by an ISR. (or vice versa).
    The possible reason for your neede delay is: when RXIFG is set, not only one byte has been received, but reception of the next has already started. If you wait, the next byte has already been nearly received (up to 7 of 8 bits) and when you leave the ISR, the last bit and the stop condition are already on its way. If you don't have the delay, it will take some time until the stop is really sent. Since your main code didn't properly wait for the end of the transfer, it will mess-up things then.
    To understand what's going on, make a time table of what is happening in which order. (be detailed and careful and consider the time it takes to complete this or that action) Use two columns, one for the code, one for the USCI, or maybe split the code in to too, one for main, one for the interrupts.
  • The same above code shows successful results when used with MSP430F5436 but does not work with MSP4305438A. The header is "MSP430.h" and prescalar value is 12.  There is no defect in the MSP device or its pins. Can you please guide me with any changes with prescalar value or anything else that can fix this problem.

    Thanking you

  • The biggest difference between the A and non-A versions is that the non-A starts with PMMCOREV=2, which allows up to 18MHz, while the A versions start with PMMCOREV=0, which is power-saving but limits the speed to 8MHz until changed.
    Your
    The other not-backwards-compatible change is the REF module that overrides (by default) the reference controls in the ADC12.

    However, I don't see you initializing the clock system at all, so you're running on 1MHz. Which shouldn't be a problem. And 83kHz (not 100kHz) I2C clock. Which also shouldn't be a problem.
    The only other difference I know of is in the errata list. USCI26 is present on both, but USCI30 is no longer there in the latest revisions of the A devices. But I don't know why this should affect a code that already runs on the non-A with USCI30 erratum.

**Attention** This is a public forum