Part Number: MSP430G2553
Hello,
I was trying to interface a BM180 module with MSP430 value line launchpad which is running on MSP430G2553 chip. The BM180 module has the pull ups installed so I did not use additional pullups. Since BM180 powers up between 1.8V to 3.6V, I connected the Vcc of launchpad to Vcc of BM180. Connected P1.6 of launchpad to SCL of BM180 and P1.7 to SDA of BM180. I used the code examples from msp430g2xx3_uscib0_i2c_8.c and msp430g2xx3_uscib0_i2c_10.c and combined them to write following code. My first step is to get an interrupt at Rx and check the buffer in debugger (if that happens, rest is easier to achieve). The below code does not work and when I debug, I see that I get a Tx interrupt only once and then it always stays in TransmitI2C(). This means the stop bit wasn't sent and then I do not get Rx interrupt. I am stuck here for past two days. Can you please help me how I could move on? Please point out at any obvious mistakes that could be doing.
#include <msp430.h>
int RXByteCtr, RPT_Flag = 0; // enables repeated start when 1
volatile unsigned char RxBuffer[64]; // Allocate 128 byte of RAM
unsigned char TxBuffer[64];
unsigned char *PRxData; // Pointer to RX data
unsigned char TXByteCtr, RX = 0;
unsigned char *PTxData; // Pointer to TX data
unsigned char TXByteCtr;
int I2C_Init(int slaveaddr)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7; // 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 = 12; // fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = slaveaddr; // Slave Address is 048h
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
IE2 |= UCB0TXIE; // Enable TX interrupt
IE2 |= UCB0RXIE; // Enable RX interrupt
return 0;
}
int TransmitI2C(unsigned char *TxData, int TxData_size)
{
PTxData = (unsigned char *)TxData; // TX array start address
TXByteCtr = TxData_size; // Load TX byte counter
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
// Remain in LPM0 until all data
// is TX'd
return 0;
}
int ReceiveI2C(int RxData_size)
{
PRxData = (unsigned char *)RxBuffer; // Start of RX buffer
RXByteCtr = RxData_size; // Load RX byte counter
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 &= ~UCTR; // Set to slave mode
UCB0CTL1 |= UCTXSTT; // I2C start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
// Remain in LPM0 until all data
// is RX'd
__no_operation(); // Set breakpoint >>here<< and
return 0;
}
int main()
{
I2C_Init(0x77);
TxBuffer[0] = 0xAA;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
TxBuffer[0] = 0xAC;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
TxBuffer[0] = 0xAE;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
TxBuffer[0] = 0xB0;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
TxBuffer[0] = 0xB2;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
TxBuffer[0] = 0xB4;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
TxBuffer[0] = 0xB6;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
TxBuffer[0] = 0xB8;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
TxBuffer[0] = 0xBA;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
TxBuffer[0] = 0xBC;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
TxBuffer[0] = 0xBE;
TransmitI2C((unsigned char *)TxBuffer, 1);
ReceiveI2C(2);
return 0;
}
//------------------------------------------------------------------------------
// 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 = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if (TXByteCtr) // Check TX byte counter
{
UCB0TXBUF = *PTxData++; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter
}
else
{
UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
//-------------------------------------------------------------------------------
// 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
// any 2+ number of bytes by pre-loading RXByteCtr with the byte count.
//-------------------------------------------------------------------------------
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
RXByteCtr--; // Decrement RX byte counter
if (RXByteCtr)
{
*PRxData++ = UCB0RXBUF; // Move RX data to address PRxData
if (RXByteCtr == 1) // Only one byte left?
UCB0CTL1 |= UCTXSTP; // Generate I2C stop condition
}
else
{
*PRxData = UCB0RXBUF; // Move final RX data to PRxData
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}