//****************************************************************************** // MSP430F54x Demo - USCI_B0 I2C Master RX multiple bytes from MSP430 Slave // // Description: This demo connects two MSP430's via the I2C bus. The slave // transmits to the master. This is the MASTER CODE. It continuously // receives an array of data and demonstrates how to implement an I2C // master receiver receiving multiple bytes using the USCI_B0 TX interrupt. // ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.045MHz // // /|\ /|\ // MSP430F5438 10k 10k MSP430F5438 // slave | | master // ----------------- | | ----------------- // -|XIN P3.1/UCB0SDA|<-|----+->|P3.1/UCB0SDA XIN|- // | | | | | // -|XOUT | | | XOUT|- // | P3.2/UCB0SCL|<-+------>|P3.2/UCB0SCL | // | | | | // // M Smertneck / W. Goh // Texas Instruments Inc. // September 2008 // Built with CCE Version: 3.2.2 and IAR Embedded Workbench Version: 4.11B //****************************************************************************** #include "msp430x54x.h" char temp_Rx=0; unsigned char *PTxData; // Pointer to TX data unsigned char TXByteCtr; const unsigned char TxData[] = // Table of data to transmit { 0xff, 0xff, }; int flag =0; int count = 0; void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P3SEL |= 0x06; // Assign I2C pins to USCI_B0 while(1) { start: //Mater mode UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC+ UCMM; // I2C Master, synchronous mode UCB0I2COA = 0x24; UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz UCB0BR1 = 0; UCB0I2CSA = 0x09; // Slave Address is 048h UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation __delay_cycles(50); #if 1 // Writing register adress PTxData = (unsigned char *)TxData; // TX array start address // Place breakpoint here to see each // transmit operation. TXByteCtr = sizeof TxData; // Load TX byte counter UCB0IE|=UCTXIE+UCALIE+UCNACKIE+UCSTPIE+UCSTTIE; UCB0CTL1 |= UCTR + UCTXSTT; __bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts __no_operation(); // Remain in LPM0 until all data count =0; do{ count++; if(count > 20) { goto start; } }while (UCB0CTL1 & UCTXSTP); #endif // Reading data from register UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC+ UCMM; // I2C Master, synchronous mode UCB0I2COA = 0x24; UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz UCB0BR1 = 0; UCB0I2CSA = 0x09; // Slave Address is 048h UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation __delay_cycles(50); UCB0IE|=UCRXIE + UCALIE+UCNACKIE+UCSTPIE+UCSTTIE; UCB0CTL1 &= ~UCTR; count =0; do{ count++; if(count > 20) { goto start; } }while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent UCB0CTL1 |= UCTXSTT; // I2C start condition count =0; do{ count++; if(count > 20) { goto start; } }while (UCB0CTL1 & UCTXSTT); // Start condition sent? __bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts __no_operation(); // For debugger __delay_cycles(300); // Delay required between transaction } } //------------------------------------------------------------------------------ // 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. Also, TXData // points to the next byte to transmit. //------------------------------------------------------------------------------ #pragma vector = USCI_B0_VECTOR __interrupt void USCI_B0_ISR(void) { switch(__even_in_range(UCB0IV,12)) { case 0: // Vector 0: No interrupts UCB0CTL1 |= UCTXSTP; __bic_SR_register_on_exit(LPM0_bits); break; case 2: // Vector 2: ALIFG UCB0IFG &= ~UCALIFG; UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC+ UCMM; // I2C Master, synchronous mode UCB0I2COA = 0x24; UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz UCB0BR1 = 0; UCB0I2CSA = 0x09; // Slave Address is 048h UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation __delay_cycles(20); // Delay required between transaction UCB0CTL1 |= UCTXSTP; __delay_cycles(20); // Delay required between transaction __bic_SR_register_on_exit(LPM0_bits); break; case 4: // Vector 4: NACKIFG UCB0IFG &= ~UCNACKIFG; UCB0CTL1 |= UCTXSTP; __delay_cycles(20); //UCB0CTL1 |= UCTXSTT; __bic_SR_register_on_exit(LPM0_bits); break; case 6: // Vector 6: STTIFG UCB0CTL1 |= UCTXSTT; UCB0IFG &= ~UCSTTIFG; // Clear start condition int flag __bic_SR_register_on_exit(LPM0_bits); break; case 8: // Vector 8: STPIFG UCB0CTL1 |= UCTXSTP; UCB0IFG &= ~UCSTPIFG; // Clear stop condition int flag __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 if data was transmitted break; case 10: // Vector 10: RXIFG temp_Rx= UCB0RXBUF; UCB0CTL1 |= UCTXSTP; // I2C stop condition UCB0IFG &= ~UCRXIFG; // Clear USCI_B0 TX int flag __bic_SR_register_on_exit(LPM0_bits); break; case 12: // Vector 12: TXIFG if (TXByteCtr) // Check TX byte counter { UCB0TXBUF = *PTxData++; // Load TX buffer TXByteCtr--; // Decrement TX byte counter } else { UCB0CTL1 |= UCTXSTP; // I2C stop condition UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 } break; default: break; } }