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.

I2C Communication between 2 MSP430F2272

Other Parts Discussed in Thread: MSP430F2272

Hi,

I am trying to develop the communication between two MSP430F2272. I followed the code example of I2C provide (no 6 and 7). But didn't get the success. Then i followed the user guide and tried to built the code the communication as under

 

Master Code

 

void main(void)

{

  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

  wait();

  wait();  

  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 + UCTR;    // Use SMCLK, keep SW reset,Transmitter

  UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz

  UCB0BR1 = 0;

  UCB0I2CSA = 0x48;                         // Slave Address is 048h

  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation

  IE2 |= UCB0TXIE;                          // Enable TX interrupt

  TXData = 0x00;                            // Holds TX data

 

  while (1)

  {

    TXByteCtr = 1;                          // Load TX byte counter

    while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent

    UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition

     UCB0TXBUF = TXData;                     // Load TX buffer

    IE2 |= UCB0TXIE;                       // Disable USCI_A0 TX interrupt                                   // Remain in LPM0 until all data

     wait();                                       // is TX'd

     wait();  

    TXData++;                               // Increment data byte

  }

}

 

//------------------------------------------------------------------------------

// The USCIAB0TX_ISR is structured such that it can be used to transmit any

// number of bytes by pre-loading TXByteCtr with the byte count.

//------------------------------------------------------------------------------

#pragma vector = USCIAB0TX_VECTOR

__interrupt void USCIB0TX_ISR(void)

{

  if (TXByteCtr)                            // Check TX byte counter

  {  

    TXByteCtr--;                            // Decrement TX byte counter

  }

  else

  {    

  }

}

 

Slave Code

void main()

{

 WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

 BCSCTL1 = CALBC1_8MHZ; 

 DCOCTL = CALDCO_8MHZ;

 UCB0CTL1 |= UCSWRST;                      // Enable SW reset

 UCB0CTL0 = UCMODE_3 + UCSYNC;             // I2C Slave, synchronous mode

 UCB0I2COA = 0x48;                         // Own Address is 048h

  INIT_PORTS(); 

  P3SEL |= 0x06;  

  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation

 IE2 |= UCB0RXIE;                          // Enable RX interrupt

  

Rx_ptr = 0;

while (Rx_ptr <10)

 {    

   strcpy(DisplayStr,"INITIAL   "); //wait till the master is attached to device

display_str(0,10,10);

 }  

   

 Rx_ptr = 0;

 Time_Change = 0;

 while(1)

 {

display_unsigned_Integer(0 ,(unsigned int)Received_data[Rx_ptr] , 10, LEADING_BLANK,10);

  secTimer = 10;

  while(!Time_Change);

  Time_Change = 0;

  Rx_ptr ++;

  if (Rx_ptr >10)

  Rx_ptr=0;

 }

 

}

 

#pragma vector = USCIAB0RX_VECTOR

__interrupt void USCI0RX_ISR(void)

{

  strcpy(DisplayStr,"DATA      "); //wait till the master is attached to device

  display_str(0,10,10);

  RXData = UCB0RXBUF;                       // Get RX data

  Received_data[Rx_ptr] =  RXData;

  Rx_ptr++;

}

 

Where i am stuck is, I can see the data through debugger on the UCB0RXBUF which are coming from Master. But i at the receiver end i have kept a code to displaying "DATA" on the 7 segment LED which is not been displayed anytime. All i am getting the "INITIAL" message which i have displayed in the main loop.

So first thing is that the MSP430 is not getting the Receive interrupt. But as the datasheet and userguide says that the SDA line will be get hold till the UCB0RXBUF has not been read. Hence the next data will not be transmitted. But i can see the data are been incremented and been transmitted !!!! The signal i have seen on the CRO and on the RXBUF also.

Need the help to find where i am missing. Or can anybody can share the running code for the communication between two MSP though I2C.

 

Thanks and Regards

Vikas

 

  • Hi Vikas,

    as far as I remember there should be an example for RX/TX multiple bytes via I2C (master and slave code) present in http://www.ti.com/lit/zip/slac123 - this were the code examples for MSP430F22x2 and MSP430F22x4 series.

    Rgds
    aBUGSworstnightmare

  •  

    Yes i have followed the same example as been given in the example code provided at the link.

    But then too i am unable to get the communication bridge to be established between two MSP's

     

    Regards

    Vikas

  • Well, your master code doesn't make much sense.

    You wait for the stop condition to be sent (which one? you never send one), set the tx counter, then you send a start condition and load the first byte into the TX buffer. Then you enable (not disable) the TX interrupt. And you do not remain in LPM as you never enter LPM. Your comments do not match the code.

    Next is that you wait (for what) and wait again (for what) and increment the data byte. This makes no obvious sense but still may be correct, depending on your wait() function.

    Now you start over the loop. You reset the byte counter (what was it for?) wait for the STOP bit being sent (which one? You still never sent one) now you send another start condition. At this point your ISR is called, since the TXIE bit is still set. And you write to TXBUF (what is your TX ISR for if you manually write to TXBUF?) and everything starts over.

    But there's something even worse: when in the first run of the loop th efirst data byte is sent and the TX interrupt comes, you do NOTHING to server the interrupt. Well, you increment the byte counter, but that's nothing tha twill satisfy the I2C hardware. If you leave the ISR, there's still nothing written to TXBUF and the TXIFG flag is still set. Th ethe MCU enters the ISR immediately again. And again. And again. And eternally again. Properly incrementing the counter. But there's nobody who could ever notice as no other code is ever running again except the TX ISR.

    On the slave side, things are confusing too. I'm not sure how the 2272 I2C works. Normally, it should trigger an interrupt if it detects that the master has sent a start conditionwith its own slave address. There you can react and decide whether to take the call or not.

    But here is the next pitfall: If using I2C, the RX vector is used for state change interrupts, while the TX vector is used for RX and TX interrupts. So teh 'byte received' interrupt calls the TX vector while you expect it on the RX vector.
    The proper RXIFG and TXIFG flags need to be used to decide whether you got something or have to send something.

    This is a bit unusual, as RX and TX vectors are used for RY and TX respectively on UART and SPI. But then, on SPI are no error conditions and on UART, all error conditions are RX related, so they are triggering the RX interrupt too (either you got a byte otr an error). With I2C, however, the state change interrupts are neither TX nor RX related (or related to both) and are no error conditions at all. Therefore the separation. Ignore any state messages and jsut reacto to the TX vector for both RX and TX, or use both vectors and handle the state changes in the RX vector.
    Also, the RX and TX vectors are shared between USCI-A and USCI-B module.

    On later devices, the USCI has a combined RX/TX interrupt that handles the state changes and errors too (there is an interrupt vector register that tells you the highest-priority reason) but A and B module have their own interrupt vector and do not share it anymore.

    So on the bottom line, the Slave gets its RX ISR called by detecting the start condition (actualyl is not called at all since you didn't activate the STT IE bit), but has no ISR for the interrupt that announces the incoming byte. Change the name and vector of your RX ISR (which in fact is an RXTX ISR) to TX and you'll get exactly one data byte, the first.

    By the way, on EACH call of the RX ISR, you assemble the data message for the display. This is HIGHLY ineffective. Even if it would work at all. Also, you don't need to wait until the master is attached to the device. And at any rate you should move you 'initial' string out of this waiting loop, as it immediately overwrites the 'data' message of the first (and only,unless you rewrite the master code) data bytes you'll get (actually the first 10 if there were 10).

  • Hi Vikas,

    In case you have not solved your problem yet, I could provide you code for I2C master and slave on MSP430F2272. Just let me know.

    Guenther

**Attention** This is a public forum