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.

msp430G2553 USCI I2C Communication not working

Other Parts Discussed in Thread: MSP430G2553

I am trying to set up a I2C communication with a I2C Display. Since I am a beginner I am struggling with the I2C interface.

My new Launch Pad and a PCB are already working fine. I have had a working communication via I2C to the same Display with other Hardware and the USI interface of a different MSP430 model. However, the MSP430G2553 does not have USI so that I had to reprogramm my software to the USCI Communication.

The Problem is, that the SCL and SDA are both going up to high state as soon as I activate the 4.5 k Ohm Pull up resistors.

However, the scope shows that they both never come back to low state anymore.

There is something wrong with my USCI Code but I can not find the error.

I found other users with similar Questions about USCI in this Forum but non of the proposed Solutions seems to fix my problem.

What did I do wrong? I would really appreciate your Help.

Here is my code. It uses the TI USCI communication library without DMA with my slight modifications.

 

#include "msp430G2553.h"
#include "TI_USCI_I2C_master.h"

unsigned char InitDisplayUSCI[] =
     {
       0x38, 0x80,        // Function Set : Interface=8bit Lines=2 DoubleHight=0 InstructionTable(IS)=0,  Command C0 RS 000000: CO=1 RS=0
       0x39, 0x80,        // Function Set : Interface=8bit Lines=2 DoubleHight=0 InstructionTable(IS)=0,  Command C0 RS 000000: CO=1 RS=0
       0x1C, 0x80,        // Internal OSC freq: Bias=1/4 Frequency=4,  Command C0 RS 000000: CO=1 RS=0
       0x7F, 0x80,        // Contrast Set: Displayspannung=78 0x70 bis 0x7F,  Command C0 RS 000000: CO=1 RS=0
       0x5E, 0x80,        // Pwr/ICON/Contrast Set: Icons=1 Booster=1 Contrast=2,  Command C0 RS 000000: CO=1 RS=0
       0x6B, 0x80,        // Follower Control: Follower=1 Verstaerkung=2 (6A) (0-7),  Command C0 RS 000000: CO=1 RS=0
       // Wait 200 ms for Power Stable before Display ON... (clear unused icons instead)
       0x40, 0xC0,        // Set Antenna Icon Address
       0x00, 0x80,        // Clear Antenna Icon
      
       0x42, 0xC0,        // Set Phone Icon Address
       0x00, 0x80,        // Clear Phone Icon
      
       0x44, 0xC0,        // Set Alarm Icon Address
       0x00, 0x80,        // Clear Alarm Icon

       0x4B, 0xC0,        // Set NoSound Icon Address
       0x00, 0x80,        // Clear NoSound Icon
      
       0x4F, 0xC0,        // Set Money Icon Address
       0x00, 0x80,        // Clear Money Icon  
       // Wait time is over now, Switch Display On
       0x0F               // Display On: DisplayOn=1 CursorOn=1 CursorPos=1

     };


int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer
 
  // Beschleunigungssensor und I2C Stromversorgung
  P3DIR |= 0x20;                      // Setzte P3.5 in Output Richtung
  P3OUT |= 0x20;                      // I2C Stromversorgung einschalten auf P3.5
 
  // Display Stromversorgung
  P3DIR |= 0x80;         // Set P3.7 to output direction
  P3OUT |= 0x80;         // Turn on Display on P3.7
   
  BCSCTL1 = CALBC1_1MHZ;                // Set DCO
  DCOCTL = CALDCO_1MHZ;

  _EINT();
  //__enable_interrupt();

  TI_USCI_I2C_transmitinit(0x7C,0x08);    // init transmitting with USCI

  while ( TI_USCI_I2C_notready() );       // wait for bus to be free

  TI_USCI_I2C_transmit(0x20,InitDisplayUSCI); // transmit Init Display Command 

// The code runs thru to here but there is no communication on the SDA and SCL pins.

// If I set the breakpoint on the LPM3 line it is triggered. Therefore the hole code is executed...

  LPM3;
}

 

 

Then there is the modified I2C Library. My changes are marked in Red.

TI_USCI_I2C_master.h

#define SDA_PIN 0x80                                    // msp430G2553 UCB0SDA pin
#define SCL_PIN 0x40                                    // msp430G2553 UCB0SCL pin

void TI_USCI_I2C_receiveinit(unsigned char slave_address, unsigned char prescale);
void TI_USCI_I2C_transmitinit(unsigned char slave_address, unsigned char prescale);


void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field);
void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field);


unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address);
unsigned char TI_USCI_I2C_notready();

 

The code of the I2C Library has also been altered slightly to fit the Device.

TI_USCI_I2C_master.c

#include "msp430G2553.h"                        // device specific header
#include "TI_USCI_I2C_master.h"

signed char byteCtr;
unsigned char *TI_receive_field;
unsigned char *TI_transmit_field;

//------------------------------------------------------------------------------
// void TI_USCI_I2C_receiveinit(unsigned char slave_address,
//                              unsigned char prescale)
//
// This function initializes the USCI module for master-receive operation.
//
// IN:   unsigned char slave_address   =>  Slave Address
//       unsigned char prescale        =>  SCL clock adjustment
//-----------------------------------------------------------------------------
void TI_USCI_I2C_receiveinit(unsigned char slave_address,
                             unsigned char prescale){
P1SEL |= SDA_PIN + SCL_PIN;                 // 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;                         // set prescaler
  UCB0BR1 = 0;
  UCB0I2CSA = slave_address;                  // set slave address
  UCB0CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
  UCB0I2CIE = UCNACKIE;

  IE2 = UCB0RXIE;                            // Enable RX interrupt
}

//------------------------------------------------------------------------------
// void TI_USCI_I2C_transmitinit(unsigned char slave_address,
//                               unsigned char prescale)
//
// This function initializes the USCI module for master-transmit operation.
//
// IN:   unsigned char slave_address   =>  Slave Address
//       unsigned char prescale        =>  SCL clock adjustment
//------------------------------------------------------------------------------
void TI_USCI_I2C_transmitinit(unsigned char slave_address,
                          unsigned char prescale){
  P1SEL |= SDA_PIN + SCL_PIN;                 // 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;                         // set prescaler
  UCB0BR1 = 0;
  UCB0I2CSA = slave_address;                  // Set slave address
  UCB0CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
  UCB0I2CIE = UCNACKIE;
  IE2 = UCB0TXIE;                             // Enable TX ready interrupt
}

//------------------------------------------------------------------------------
// void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field)
//
// This function is used to start an I2C commuincation in master-receiver mode.
//
// IN:   unsigned char byteCount  =>  number of bytes that should be read
//       unsigned char *field     =>  array variable used to store received data
//------------------------------------------------------------------------------
void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field){
  TI_receive_field = field;
  if ( byteCount == 1 ){
    byteCtr = 0 ;
    __disable_interrupt();
    UCB0CTL1 |= UCTXSTT;                      // I2C start condition
    while (UCB0CTL1 & UCTXSTT);               // Start condition sent?
    UCB0CTL1 |= UCTXSTP;                      // I2C stop condition
    __enable_interrupt();
  } else if ( byteCount > 1 ) {
    byteCtr = byteCount - 2 ;
    UCB0CTL1 |= UCTXSTT;                      // I2C start condition
  } else
    while (1);                                // illegal parameter
}

//------------------------------------------------------------------------------
// void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field)
//
// This function is used to start an I2C commuincation in master-transmit mode.
//
// IN:   unsigned char byteCount  =>  number of bytes that should be transmitted
//       unsigned char *field     =>  array variable. Its content will be sent.
//------------------------------------------------------------------------------
void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field){
  TI_transmit_field = field;
  byteCtr = byteCount;
  UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
}

//------------------------------------------------------------------------------
// unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address)
//
// This function is used to look for a slave address on the I2C bus. 
//
// IN:   unsigned char slave_address  =>  Slave Address
// OUT:  unsigned char                =>  0: address was not found,
//                                        1: address found
//------------------------------------------------------------------------------
unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address){
  unsigned char ie2_bak, slaveadr_bak, ucb0i2cie, returnValue;
  ucb0i2cie = UCB0I2CIE;                      // restore old UCB0I2CIE
  ie2_bak = IE2;                              // store IE2 register
  slaveadr_bak = UCB0I2CSA;                   // store old slave address
  UCB0I2CIE &= ~ UCNACKIE;                    // no NACK interrupt
  UCB0I2CSA = slave_address;                  // set slave address
  IE2 &= ~(UCB0TXIE + UCB0RXIE);              // no RX or TX interrupts
  __disable_interrupt();
  UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP;       // I2C TX, start condition
  while (UCB0CTL1 & UCTXSTP);                 // wait for STOP condition
 
  returnValue = !(UCB0STAT & UCNACKIFG);
  __enable_interrupt();
  IE2 = ie2_bak;                              // restore IE2
  UCB0I2CSA = slaveadr_bak;                   // restore old slave address
  UCB0I2CIE = ucb0i2cie;                      // restore old UCB0CTL1
  return returnValue;                         // return whether or not
                                              // a NACK occured
}

//------------------------------------------------------------------------------
// unsigned char TI_USCI_I2C_notready()
//
// This function is used to check if there is commuincation in progress.
//
// OUT:  unsigned char  =>  0: I2C bus is idle,
//                          1: communication is in progress
//------------------------------------------------------------------------------
unsigned char TI_USCI_I2C_notready(){
  return (UCB0STAT & UCBBUSY);
}


#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
  if (UCB0STAT & UCNACKIFG){            // send STOP if slave sends NACK
    UCB0CTL1 |= UCTXSTP;
    UCB0STAT &= ~UCNACKIFG;
  }

}


#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
  if (IFG2 & UCB0RXIFG){
    if ( byteCtr == 0 ){
      UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
      *TI_receive_field = UCB0RXBUF;
      TI_receive_field++;
    }
    else {
      *TI_receive_field = UCB0RXBUF;
      TI_receive_field++;
      byteCtr--;
    }
  }
  else {
    if (byteCtr == 0){
      UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
      IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
    }
    else {
      UCB0TXBUF = *TI_transmit_field;
      TI_transmit_field++;
      byteCtr--;
    }
  }
}

**Attention** This is a public forum