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.
Hello,
I have been trying to transmit a 2 bytes of the data to ADXL345 for last two days. But i still stuck in the same place.I have shared my whole code here. Go through it and let me know your suggestions
#include <msp430.h> #include <stdio.h> #define MAX30100_DEVICE 0x57 /** * main.c */ int i=0; char Data_In=0; char packet[]={0x2D, 0x08,0x00}; int idx_cnt=0; int main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer //---Setup B0 for I2C UCB2CTLW0 |= UCSWRST; // put in SW RST UCB2CTLW0 |= UCSSEL_3 ; // Choose SMCLK UCB2BRW = 10; // set prescalar to 100 UCB2CTLW0 |= UCMODE_3; // Put into I2C UCB2CTLW0 |= UCMST; // Set as master UCB2I2CSA = MAX30100_DEVICE; //Set slave address 0x57 UCB2TBCNT =sizeof(packet); // Count = 1 byte UCB2CTLW1 |= UCASTP_2; //auto STOP mode //--setup ports P7SEL1 &= ~BIT1; //P7.1 = SCL P7SEL0 |= BIT1; P7SEL1 &= ~BIT0; //P7.0 = SDA P7SEL0 |= BIT0; PM5CTL0 &= ~LOCKLPM5; // Turn on I/O UCB2CTLW0 &= ~UCSWRST; //take out of in SW RST //-----Enable IRQ UCB2IE |=UCRXIE0 ; // local enable for RX0 UCB2IE |=UCTXIE0 ; //local enable for TX0 __enable_interrupt(); while(1) { //Transmit reg addr with Write message UCB2CTLW0 |=UCTR; //Put into TX mode UCB2CTLW0 |=UCTXSTT; //Gen START while((UCB2IFG & UCTXIFG0) == 0) { printf("Stop on 1st while\n"); } UCB2IFG &= ~UCSTPIFG; //Clear the STOP Flag UCB2CTLW0 &=~UCTR; //Put into RX Mode UCB2CTLW0 |=UCTXSTT; //Gen START while((UCB2IFG & UCSTPIFG) == 0) { printf("Stop on second while\n"); } UCB2IFG &= ~UCSTPIFG; //Clear STOP FLAG } } //---------------------------------------------------------- // ISR //----------------------------------------------------------- #pragma vector = EUSCI_B2_VECTOR __interrupt void EUSCI_B2_I2C_ISR(void) { switch(UCB2IV) { case 0x16: //ID 16:RXIFG0 Data_In=UCB2RXBUF; printf("%d",Data_In); break; case 0x18: //ID 16:TXIFG0 while(idx_cnt<=sizeof(packet-1)) { UCB2TXBUF = packet[idx_cnt]; printf("case 2"); idx_cnt++; } break; default: break; } }
How do you detect if TXIFG is set? A breakpoint in the ISR? Or your polling loop in main()?
If your ISR is working properly it is improbable that main() will see a TXIFG, since the ISR will "absorb" it.
That said, you should set TXBUF (only) once for each TXIFG. I think this is working by accident due to the printf().
while((UCB2IFG & UCTXIFG0) == 0) { printf("Stop on 1st while\n"); }
I am using the above polling loop to check the TXIFG.You're pretty correct that the ISR will absirb it before the main loop see it.But the issue is that ISR is not absorbing it as it should be,The TXIFG is not set for the ISR to get trigger.So program got stuck in the while loop itself.
This is a case where a scope is really handy.
If the TXIFG after STT is really never being presented, that suggests that the bus is stuck. This can mean (a) the pullups aren't right or (b) the slave is holding SCL and/or SDA low (probably due to some debugging history).
For (a): Try enabling the internal pullups -- this might help
For (b): Have you power-cycled the ADXL345? When I use one of the ADXLs, I usually power it with a port pin so I can do this under program control.
[Edit: I just noticed:
>#define MAX30100_DEVICE 0x57
Per ADXL345 data sheet (RevE) page 18, the address is either 0x1D or 0x53, depending on the ALT_ADDRESS pin. You should still get the initial TXIFG.]
Hi Bruce,
Thanks for your reply,
Thank you,
1/2) Yes, just unplug the 3.3V (or VIN if you're using that) and plug it back in.
3) If the slave is holding SCL low, the only thing you can really do is reset it. [Ref I2C Spec (UM10204-R6) Sec 3.2.13]. Since the ADXL345 doesn't have a Reset pin, that means power-cycling it. The master needs control of SCL (and SDA) to generate a Start.
You don't enable the internal pullups nor do you mention external resistors. What value of resistor is being used to pull up SDA and SCL?
Hi Bruce,
Now, SDA and SCL lines are working fine. but the value I am sending is 0x2D, But it transmits 0x25. What is would be the issue here?
Thanks,
I tried with 10k and 4.7k. and I make sure, I didn't enable the internal pullups.
What does your code look like now? Are you still writing all the TXBUF bytes at once in the ISR?
case USCI_I2C_UCTXIFG0: // TXIFG0 transmit_initiated = 1; UCB2TXBUF = *txBuffer++; break;
Hey bruce thanks for your reply.This is how i implemented by the Transmission now. I am trying to write the Transmission bytes one by one.
Are you resetting txBuffer between transactions?
I know of no mechanism which would alter data you write to TXBUF, so my first guess is that you're not writing what you think you are.
Hey Bruce,
Whatever I transmit is well and good. I can see the TXBUF value on register. So there is no problem in that. But the issue is i am not able to receive data from the sensor. I have checked both the SDA and SCL line on oscilloscope and master/slave is not holding the line low. But i still couldn't able to find the reason why i am not getting the RX data. I have used the same code with another slave and it is working fine.
In adafruit ADXL345 breakout board already the 10K pull up resistors are available. So should i have to add an external pull up resistor for I2C communication or onboard resistors is enough to do the job?
What does "not able to receive" mean precisely? (a) transaction hangs? (b) unexpected result value? (c) other?
Your code as posted above (1) writes to registers 0x2D-0x2E, then (2) reads from register 0x2F (INT_MAP), which is probably 0x00.
If your goal is to read DATAX0-Z1, you should first write a single byte of 0x32 (DATAX0 address) then read 6 bytes. [Ref data sheet (revE) Table 19]
As a quick check, you could change your program to read (3+6) starting (as now) from 0x2F, and just ignore the first 3 bytes.
**Attention** This is a public forum