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: I2C Data Issue

Part Number: MSP430G2553


Hi Experts,

I have an EEPROM which I'm trying to interface to MSP430G2553. I wrote a driver for I2C, the problem is it has to send data from MSB to LSB but the controller is exactly doing the opposite. And one more thing I would like to mention is that it is coming to RX interrupt but it is checking an if statement and coming out from ISR. It is not executing the code written in RX Interrupt. Can anyone point out the issue which I mentioned here

1) MSB to LSB issue and

2) I2c Rx Interrupt it is not executing any statement just checking if condition and coming out from there.

static inline void init_sysClock(void)
{
BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz
DCOCTL = CALDCO_1MHZ;
BCSCTL3 = LFXT1S_0; // LFXT1 = 32KHz
BCSCTL2 = SELM_0; // select SMCLK = MCLK = DCOCLK
}

void initI2C()
{
// Init Gpio for I2C Bus
P3REN |= BIT6 + BIT7;
I2C_PIN_SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
I2C_PIN_SEL2 |= BIT6 + BIT7; // I2C Pin Configuration

UCB0CTL1 |= UCSWRST;
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC + UCMSB;
UCB0CTL1 = UCSSEL_2 + UCSWRST;
UCB0BR0 = 10; // Our SMCLK = 1MHz. SMCLK/10 = ~100KHz
UCB0BR1 = 0;
UCB0I2CSA = SLAVE_READ_ADDR;
UCB0CTL1 &= ~UCSWRST;
UCB0I2CIE |= UCNACKIE;
}

I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
{
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
UCB0_TxComplete = false;
//Copy register data to TransmitBuffer
CopyArray(reg_data, TransmitBuffer, count);

TXByteCtr = count;
RXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;

/* Initialize slave address and interrupts */
UCB0I2CSA = dev_addr;
IFG2 &= ~(UCB0TXIFG + UCB0RXIFG); // Clear any pending interrupts
IE2 &= ~UCB0RXIE; // Disable RX interrupt
IE2 |= UCB0TXIE; // Enable TX interrupt

UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
while(!UCB0_TxComplete);
return MasterMode;
}

I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count)
{
/* Initialize state machine */
UCB0_RxComplete =false;
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
RXByteCtr = count;
TXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;

/* Initialize slave address and interrupts */
UCB0I2CSA = dev_addr;
IFG2 &= ~(UCB0TXIFG + UCB0RXIFG); // Clear any pending interrupts
IE2 &= ~UCB0RXIE; // Disable RX interrupt
IE2 |= UCB0RXIE; // Enable RX interrupt

UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
while(!UCB0_RxComplete);
return MasterMode;

}

void main(void)
{
WDTCTL = WDTPW + WDTHOLD;

init_system();

initI2C();

I2C_Master_ReadReg(SLAVE_READ_ADDR, 0x00, 1);

while(1)

{

__no_operation();
}
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR (void)
#else
#error Compiler not supported!
#endif
{
if (IFG2 & UCB0TXIFG) // Transmit Data Interrupt
{
switch (MasterMode)
{
case TX_REG_ADDRESS_MODE:
UCB0TXBUF = TransmitRegAddr;
if (RXByteCtr)
MasterMode = SWITCH_TO_RX_MODE; // Need to start receiving now
else
MasterMode = TX_DATA_MODE; // Continue to transmision with the data in Transmit Buffer
break;

case SWITCH_TO_RX_MODE:
IE2 |= UCB0RXIE; // Enable RX interrupt
IE2 &= ~UCB0TXIE; // Disable TX interrupt
UCB0CTL1 &= ~UCTR; // Switch to receiver
MasterMode = RX_DATA_MODE; // State state is to receive data
UCB0CTL1 |= UCTXSTT; // Send repeated start
if (RXByteCtr == 1)
{
//Must send stop since this is the N-1 byte
while((UCB0CTL1 & UCTXSTT));
UCB0CTL1 |= UCTXSTP; // Send stop condition
}
break;

case TX_DATA_MODE:
if (TXByteCtr)
{
UCB0TXBUF = TransmitBuffer[TransmitIndex++];
TXByteCtr--;
}
else
{
//Done with transmission
UCB0_TxComplete = true;
UCB0CTL1 |= UCTXSTP; // Send stop condition
MasterMode = IDLE_MODE;
IE2 &= ~UCB0TXIE; // disable TX interrupt
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;

default:
__no_operation();
break;
}
}
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCIAB0RX_ISR (void)
#else
#error Compiler not supported!
#endif
{
if (IFG2 & UCB0RXIFG) // Receive Data Interrupt
{
//Must read from UCB0RXBUF
uint8_t rx_val = UCB0RXBUF;

if (RXByteCtr)
{
ReceiveBuffer[ReceiveIndex++] = rx_val;
RXByteCtr--;
}

if (RXByteCtr == 1)
{
UCB0CTL1 |= UCTXSTP;
UCB0_RxComplete = true;
}
else if (RXByteCtr == 0)
{
IE2 &= ~UCB0RXIE;
MasterMode = IDLE_MODE;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
}

  • UCMSB refers to the Most Significant Bit in a byte, which the I2C definition says you need.

    If your EEPROM is larger than 256 bytes, you need to send the address as multiple bytes, which (on the memory devices I'm familiar with) is sent Most Significant Byte first. You have to do this when you send the address, by breaking it into bytes. 

    On I2C memory devices the address is equivalent to the "register number" for (most) other I2C devices. As I read this code, it assumes that the register number (memory address in your case) is only one byte wide (TransmitRegAddr). What you need to do is extend this value to accommodate the wider address, mostly in the TX_REG_ADDRESS_MODE case in the ISR.

  • Hi Bruce,

    As per your your suggestion I removed UCMSB bits from the I2c Init process, did you find any other issue in my code or it should work ?

  • You should not remove UCMSB, since the I2C specification requires it.

    You should extend the width of your "register number" (memory address) to however many bytes your EEPROM needs, which depends on how big the EEPROM is. What EEPROM device are you using?

**Attention** This is a public forum