In my first trial with accelerometers, I just want to get a "Hello World" from an MMA8652 via I2C mastered from a MSP430G2553 which is into the ti launchpad (not Arduino). I've searched for information in the web and tried lots of examples but never got a response from the accelerometer.
In particular I took the examples for I2C communication that come with the Code Composer Studio, changing the slave address to the WHO_AM_I address (UCB0I2CSA = 0x0d) and I've also tried to read several other adresses.
Many blogs mention i2c.h library, but I couldn find it specifically for G2553 microprocessor, the examples into CCS don't use it. I've also read about wire.h, but I understand it is for Arduino board.
I've tried Mr. Kerry Wong examples, etc, etc, etc ...
I used two accelerometers in two different boards and nothing, I don't actually know if they are alive.
Please I'm asking for a very basic working code example which gets a response from the accelerometer.
You can see into the image how I've connected the accelerometer to the launchpad (it is ok VCC=3.56V ?)
On the other hand I know that MSP430G2553 is working ok because I succesfully communicated it via i2c with other MSP430G2553.
Thanks.
Pedro
已解决! 转到解答。
Hi Pedro,
Do you have a logic analyzer or an oscilloscope to see what is going on on the I2C bus?
A single byte read from the WHO_AM_I register 0x0D looks like this:
A common problem with the read operation is sending a stop condition (a low to high transition of SDA while SCL is high) after the second byte (in this case 0x0D). The correct way is to release the SDA line (so that it transitiones to high) before the SCL line goes high.
And here is an example of a single byte write operation which writes the value 0x3D to the CTRL_REG1 register 0x2A:
You might also find useful my sample code here.
I hope it helps.
Regards,
Tomas
PS: If my answer helps to solve your question, please mark it as "Correct" or “Helpful”. Thank you.
Hi Pedro,
Do you have a logic analyzer or an oscilloscope to see what is going on on the I2C bus?
A single byte read from the WHO_AM_I register 0x0D looks like this:
A common problem with the read operation is sending a stop condition (a low to high transition of SDA while SCL is high) after the second byte (in this case 0x0D). The correct way is to release the SDA line (so that it transitiones to high) before the SCL line goes high.
And here is an example of a single byte write operation which writes the value 0x3D to the CTRL_REG1 register 0x2A:
You might also find useful my sample code here.
I hope it helps.
Regards,
Tomas
PS: If my answer helps to solve your question, please mark it as "Correct" or “Helpful”. Thank you.
Hi Tomas,
I'm still fighting with this. I remind you I have a MMA8652, a MSP430G2553 MCU and I use Code Composer Studio.
Today I know that the hardware is ok, because it worked fine with a Energia code example.
But it has been imposible to me to find, adapt or write a native code for a MSP430G2553. I know you are not TI technical representative, but would ask you if you have a basic example (read who_am_i) for this microprocessor.
I case you don't, I'll ask you please to send me the example for whatever MCU you use, and I'll try to translate it.
I've been taking a look to the "Bare metal example project", but i prefer to start with an ultra basic example if possible.
_________________________________________________________________________________________________
This is a trial, I've adapted it from a code example in the web. It executes until the end apparently ok, but the reading result "PRxData" is always 0x00. I tried different variations over this code but nothing. I feel it is quite close, but something is still wrong. Do I need to initialize ctrl_reg1 before reading WHO_AM_I register?
#include <msp430g2553.h>
int ctrl_reg1 = 0x2A;
int lcount = 0;
int TXByteCtr;
unsigned char palout;
unsigned char PRxData;
int Rx = 0;
char WHO_AM_I = 0x0D; //WHO_AM_I register address
char itgAddress = 0x1D;
void init_I2C(void);
void Transmit(void);
void Receive(void);
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
init_I2C();
// while(1){
//Transmit process
Rx = 0;
TXByteCtr = 1;
palout= ctrl_reg1;
Transmit();
_delay_cycles(100);
//Transmit process
Rx = 0;
TXByteCtr = 1;
palout= 0x01;
Transmit();
_delay_cycles(100);
//Transmit process
Rx = 0;
TXByteCtr = 1;
palout= WHO_AM_I;
Transmit();
_delay_cycles(100);
//Receive process
Rx = 1;
Receive();
lcount++;
while(1);
//}
}
//-------------------------------------------------------------------------------
// 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
lcount++;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
else{ // Master Transmit
if (TXByteCtr) // Check TX byte counter
{
UCB0TXBUF = palout; // 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
}
}
}
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 069h
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
IE2 |= UCB0RXIE + UCB0TXIE; //Enable RX and TX interrupt
}
void Transmit(void){
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 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
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
}
Hi Pedro,
Are you seeing any traffic on the I2C bus? If yes, could you please post here scope shots illustrating both read and write operations?
Unfortunately I do not have any I2C examples for the TI MSP430G2553, but you might find useful my example code for the Kinetis KL25Z and MMA8652FC. If you donwload the source code, you can find the I2C routines in the I2C.c file within the Sources folder.
The MMA8652FC uses a well known I2C combined format that looks as follows:
Reading from the MMA8652FC:
1. Send a start sequence
2. Send 0x3A // slave address with the R/W bit low or 0x1D << 1
3. Send internal address of the register you want to read from
4. Send a repeated start
5. Send 0x3B // slave address with the R/W bit high or (0x1D << 1 ) | 0x01
6. Read data byte from MMA8652FC
7. [Optionally, read any further data bytes]
8. Send NAK and a stop sequence.
Writing to the MMA8652FC:
1. Send a start sequence
2. Send 0x3A // slave address with the R/W bit low or 0x1D << 1
3. Send the internal register number you want to write to
4. Send the data byte
5. [Optionally, send any further data bytes]
6. Send a stop sequence.
I hope that helps.
Regards,
Tomas
Hi Tomas, thank you for the answer.
Yes I have connected an oscilloscope to the SCL and SDA lines, expecting to see some pulses but... nothing happens, SCL remains low and SDA remains high.
Please confirm if launchpad's VCC=3.56 is ok for MMA8652, I know the limit is 3.6V.
I will try now with you example and I will mount a third MMA8652 in another board.
I'll tell you later.
Thanks.
Pedro