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 Not Receiving Data from ADXL345 I2C

Other Parts Discussed in Thread: MSP430G2253

I'm trying to collect data on my MSP430G2253 from an ADXL345 Accelerometer in I2C mode. I've found that I can transmit data to the ADXL345 to set the configuration registers just fine, but I can't receive any data from it. When the receive function is called, it enters the ISR but then skips over the part where data is supposed to be loaded into the receive buffer.

I think the problem is that I may not be requesting for data correctly from the slave. I understand it has something to do with transmitting to the data register in quesiton (which is 0x32 on the ADXL in this case) and having a repeated start signal but the process was a little confusing. I think because I'm not requesting data correctly, the receive flag on the MSP430 never gets set and so once the receive function calls the ISR, the ISR skips over moving data into the receive buffer because the flag wasn't set.

Can anyone provide some guidance on this? Below is my code:

#include <msp430.h>
#include <stdarg.h>
#include "TI_USCI_I2C.h"


#define NUM_BYTES_TX 2 // How many bytes?
#define NUM_BYTES_RX 6
#define ADXL_345 0x53
int RXByteCtr0; // enables repeated start when 1
int x1,y1,z1 = 0;
volatile int RxBuffer[6]; // Allocate 6 byte of RAM
unsigned char *PRxData; // Pointer to RX data
unsigned char TXByteCtr;
unsigned char MSData[3];
unsigned char storage[6];
unsigned char *TI_receive_field;

void Transmit(unsigned char,unsigned char);
void RPT_Transmit(unsigned char,unsigned char);
//void Receive(void);
void printf(char *,...);
void initUART(void);
void sendByte(unsigned char);

int main(void)

{
initUART();
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1DIR |= BIT0;

TXByteCtr = 0;
RX = 0;

while(1){

// Init sequence for ADXL345

//Transmit process

TI_USCI_I2C_init(ADXL_345, 12);

Transmit(0x31,0x0B);
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent

//Transmit process

Transmit(0x2D,0x08);
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent

//Transmit process

Transmit(0x2E,0x80);
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent

//Receive process

Transmit(0x32,0xFE);
while (UCB0CTL1 & UCTXSTP);

TI_USCI_I2C_receive(6,storage);
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent


x1 = (((int)RxBuffer[1]) << 8) | RxBuffer[0];

y1 = (((int)RxBuffer[3]) << 8) | RxBuffer[2];

z1 = (((int)RxBuffer[5]) << 8) | RxBuffer[4];

printf("%i",x1);
printf("%i",y1);
printf("%i",z1);


if ((x1 > 128) || (y1 > 128) || (x1 < -128) || (y1 < -128))
{
P1OUT |= BIT0; // red led on
}


else
{
P1OUT &= BIT0; // red led off
}

__delay_cycles(10000); // sample rate ~100 samples/sec

}

}

void initUART(void) {
P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD

UCA0CTL1 |= UCSSEL_1; // CLK = ACLK
UCA0BR0 = 0x03; // 32kHz/9600 = 3.41
UCA0BR1 = 0x00;
UCA0MCTL = UCBRS1 + UCBRS0; // Modulation UCBRSx = 3
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
}


void puts(char *s) {
char c;

// Loops through each character in string 's'
while (c = *s++) {
sendByte(c);
}
}
/**
* puts() is used by printf() to display or send a character. This function
* determines where printf prints to. For this case it sends a character
* out over UART.
**/
void putc(unsigned b) {
sendByte(b);
}

void sendByte(unsigned char byte )
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = byte; // TX -> RXed character
}

#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if (IFG2 & UCB0RXIFG) {
if (RXByteCtr == 0) {
UCB0CTL1 |= UCTXSTP; // I2C stop condition
}
*TI_receive_field = UCB0RXBUF;
TI_receive_field++;
RXByteCtr--;
}
else
if (IFG2 & UCB0TXIFG) {
if (TXByteCtr){
UCB0TXBUF = MSData[TXByteCtr]; // Load TX buffer
TXByteCtr--;
}
else{
UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}


}
}

void Transmit(unsigned char Reg_ADD,unsigned char Reg_DAT){

RX = 0;
MSData[2]= Reg_ADD;
MSData[1]= Reg_DAT;
TXByteCtr = NUM_BYTES_TX; // 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

}

void TI_USCI_I2C_receive(unsigned char byteCount,unsigned char *field) {

TI_receive_field = field;
if ( byteCount == 1 ){
RXByteCtr = 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 ) {
RXByteCtr = byteCount - 2 ;
UCB0CTL1 |= UCTXSTT; // I2C start condition
} else
while(1); // illegal parameter
}

  • Pearce Herchenrader said:
    I think because I'm not requesting data correctly, the receive flag on the MSP430 never gets set and so once the receive function calls the ISR, the ISR skips over moving data into the receive buffer because the flag wasn't set.

    The ISR isn't called if there is no incoming data. ISRs are called by an event, that's their purpose. And the event is 'data received'.

    It shouldn't make much of a difference whether you do a repeated start or a  stop/start. Sure, besides the saved time for the unnecessary stop, another master could pick the bus right after the stop, causing arbitration loss and maybe rendering the config data you sent useless (by accessing the same slave).
    But If there is only one master, it normally makes no difference (few I2C slaces abort an ongoing write/read combo because of a stop between them)

    What does TI_USCI_I2C_init do? Maybe it doesn't enable the RX interrupt?

**Attention** This is a public forum