• TI Thinks Resolved

MSP430G2553: USCIAB0TX_VECTOR working

Prodigy 70 points

Replies: 8

Views: 266

Part Number: MSP430G2553

Hello Everyone,

Currently, I am working on BME280 sensor with has an I2C interface. I have referenced the code from the link: https://electronics.stackexchange.com/questions/67524/msp430-i%C2%B2c-single-write-read-example.

The code is basically on I2C interrupt and it's working fine. I have also tested with Polling method and it works as well. I have some doubts as below regarding both the polling and interrupt methods.

1. With interrupt,the  UCB0RXIE & UCB0TXIE are set for receive & transmit interrupt. so when the data is received and transmit the ISR will call i.e USCIAB0TX_VECTOR. I am confused with USCIAB0TX_VECTOR  triggering. I refer the user guide it mentions that with start condition generated the TXIFG flag will be set and UCTXSTT is cleared once ACK receives from the slave.  On the ISR they haven't cleared the TXFIG flag once the first byte is loaded but cleared on second triggering. I check if the triggering is due to TXIFG so I clear once the first byte is loaded but it triggers again, I also see on second triggering the UCTXSTT  was cleared. I  want to know on what situation the USCIAB0TX_VECTOR ISR will call ?

2. On the polling method, I have polled while(!(UCB0STAT & UCBBUSY)); to check if the bus is busy or idle data transfer. If I poll the while (!(IFG2 & UCA0TXIFG)); it doesn't send the first byte but only send the address and start bit. what I am doing wrong in this case?

Below is code for both Interrupt and Polling. Kindly comment the MACRO #define POLLING for I2C interrupt flow.

#include <msp430g2553.h>


int TXByteCtr;
unsigned char PRxData;
int Rx = 0;
char WHO_AM_I = 0xD0;
char flag = 0;
char itgAddress = 0x77;

void init_I2C(void);
void Transmit(void);
void Receive(void);

//#define POLLING

int main(void)
{
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
   P1DIR |= BIT0;
  P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
  P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
  P1OUT &= ~BIT0;
  init_I2C();

 while(1)

{
  //Transmit process
 Rx = 0;
 TXByteCtr = 1;
 Transmit();
 //Receive process
 Rx = 1;
 Receive();
 while(1);
 // _no_operation();
 }
}

//-------------------------------------------------------------------------------
// The USCI_B0 data ISR is used to move received data from the I2C slave
// to the MSP430 memory. It is structured such that it can be used to receive
//-------------------------------------------------------------------------------
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{

if(Rx == 1){ // Master Recieve?
PRxData = UCB0RXBUF; // Get RX data
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}

else{ // Master Transmit
if (TXByteCtr) // Check TX byte counter
{
P1OUT &= ~BIT0;

UCB0TXBUF = WHO_AM_I; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter
                                                               /*  if used this IFG2 &= ~UCB0TXIFG  API here it triggers again  */
}
else
{

/* comes here even cleared  UCB0TXIFG in above case*/


P1OUT |= BIT0;
UCB0CTL1 |= UCTXSTP; // I2C stop condition
// Clear USCI_B0 TX int flag
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}

}
void init_I2C(void) {
UCB0CTL1 = UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = itgAddress; // Slave Address is 077h
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
#ifndef POLLING
IE2 |= UCB0RXIE + UCB0TXIE; //Enable RX and TX interrupt
#endif
}

void Transmit(void)
{

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

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

#ifdef POLLING
while(!(UCB0STAT & UCBBUSY));  //working   /* with while (!(IFG2 & UCA0TXIFG)); not working */
UCB0TXBUF = WHO_AM_I;
while(!(UCB0STAT & UCBBUSY));                  /* with while (!(IFG2 & UCA0TXIFG)); not working */
while (UCB0CTL1 & UCTXSTT);

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

#else
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
// _no_operation();
#endif
}
void Receive(void){
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 &= ~UCTR ; // Clear UCTR
UCB0CTL1 |= UCTXSTT; // I2C start condition
while (UCB0CTL1 & UCTXSTT); // Start condition sent?
UCB0CTL1 |= UCTXSTP; // I2C stop condition
#ifdef POLLING
while (!( IFG2 & UCB0RXIFG));
PRxData = UCB0RXBUF;
#else
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
#endif
}

Kindly share your views for the same. Any help will be greatly appreciated. 

Regards,

Amit