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.
Hi,
I am having some real trouble interfacing my ADXL345 accelerometer with my MSP430G2553 launch pad. I have got to the point where I really do not know what to try next and would really appreciate if someone could lend a hand.
At the moment it seams like I am getting a response of 0xFF (or what ever I last send) when I send the device ID code as well as any other code. I was also seeing a receive overrun flag but I have tried again this morning and that is not happening now. I have looked at other posts with this hardware and other SPI posts but none are able to help solve my problems. I have tried changing the clock phase and polarity just to rule that out with no changes.
The datasheet for the accelerometer says that the clock needs to idle high and data is updated on the falling edge and sampled on the rising edge. So I have taken this to mean that UCCKPH = 0 and UCCKPL = 1. I have tried setting UCMSB as well. I am using a master clock of 16 MHz for now, and a sub master clock of 4MHz with the ADXL345 being able to support a maximum of 5Mhz SPI transfer rate.
Here is the code I am using:
#include <msp430g2553.h>
#include "ADXL345.h" //Holds device command definitions
#define SCL BIT4
#define CS BIT3
#define MISO BIT6
#define MOSI BIT7
void clockConfig()
{
// configure the CPU clock (MCLK)
// to run from DCO @ 16MHz and SMCLK = DCO / 4
BCSCTL1 = CALBC1_16MHZ; // Set DCO
DCOCTL = CALDCO_16MHZ;
BCSCTL2= DIVS_2 + DIVM_0; // divider=4 for SMCLK and 1 for MCLK
}
void pinConfig()
{
// set the pin mode 3 for pins 1 2 and 4 of port 1 (USCI mode)
P1SEL = SCL + MOSI + MISO; // low bit = 1 for pin 1 and 2 4. BIT 3 is 0 (CS via GPIO)
P1SEL2 = SCL + MOSI + MISO; // high bit = 1 for pin 1 and 2 4 BIT 3 is 0 (CS via GPIO)
P1DIR |= CS; // p1.3 set to output to drive CS
P1OUT |= CS; // CS high before clock polarity etc is set
}
// USCI
void spiConfig()
{
UCB0CTL0 |= UCMST + UCMODE_0 + UCSYNC + UCMSB; //UCCKPL +
// synchronous (=SPI) master 3 wire SPI, clock polarity High
/*SPI mode is selected when the UCSYNC bit is set and SPI
mode (3-pin or 4-pin) is selected with the UCMODEx bits.*/
//use SMCLK : 4MHz
UCB0CTL1 |= UCSSEL_2;
// set baud rate = SMCLK, no further division
UCB0BR0 = 0;
UCB0BR1 = 0;
//UCA0MCTL = 0; // No modulation
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI **
}
void reset_slave(void)
{
P1OUT &= ~CS;
__delay_cycles(10);
P1OUT |= CS;
}
void slave_on(void)
{
P1OUT ^= ~CS;
__delay_cycles(50);
}
void slave_off(void)
{
P1OUT |= CS;
__delay_cycles(50);
}
// Sends SPI command
char SPI_tx(unsigned char dataOut)
{
slave_on();
while (!(IFG2 & UCB0TXIFG)); // wait for TX buffer ready
UCB0TXBUF = dataOut; // Send command
while (!(IFG2 & UCB0TXIFG)); // wait for TX buffer ready
UCB0TXBUF = 0xFE; // Send dummy to provide clock for RX
while (!(UC0IFG & UCB0RXIFG)) //Wait for RX buffer
; // wait for an rx character?
slave_off();
return UCB0RXBUF; // reading clears RXIFG flag
}
void main(void)
{
// setup
WDTCTL = WDTPW + WDTHOLD;
clockConfig();
pinConfig();
spiConfig();
reset_slave();
__delay_cycles(500000);
char dataRead = 0x95;
// while(1){
dataRead = SPI_tx(DEV_ID);
__delay_cycles(5000000);
//dataRead = SPI_rx();
//}
}
Am I doing something obviously wrong? I am running the ADXL345 from a separate power supply just in case that was a cause of problems; should the grounds be connected? If any more information is needed let me know; I tried to include everything.
Thanks for your time,
Alex
Hey Alex,
Check the following thread:
http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/t/52871.aspx
I have gone through your situation about 2 years ago. That thread contains a lot of good information.
Satbir
Hi Satbir
Thanks for the reply!
I did find your post about a week ago. I had a read through and tried using the advice but without success. I have gone through it all again anyway now that I understand somethings better but it is still not working for me. I always get back 0xFF; what ever I send. I have even tried to copy and paste the bits of code that sets up the clocks and SPI just to make sure if is all exactly the same. No luck.
Could anyone offer any more advice?
Thanks,
Alex
I've been trying to check whats going on with oscilloscopes again and it seams I'm now not getting a clear clock signal. I can't see why not from my code. It seams to be the same setup as other examples.
I made a new project and set up a SMCLK on pin 4 with grace and it worked fine. So I guess it is something to do with the setup, anyone got any clues?
Thanks,
Alex
Alex,
This is my very basic code, without using any TX or RX interrupts.
I used BIT1 of Port 4 for Chip select and BIT2 as power for the ADXL345. The MCLK was running at 8 MHz and the SMCLK at 4 MHz. I had some problems with the ADXL345 ground.
I know it may sound stupid, but try disconnecting the ground from the ADXL345 and read again. This happened to me, the ADXL345 was not working correctly whenever I had ground connected to the MSP430 GND(Might have been an issue with my wiring).
Make adjustments for your chip as this code was written for MSP430F2274.
//******************************************************************************
// ADXL345 -SPI- MSP430F2274//
// 8 bit- resolution //
// Left Justified //
//******************************************************************************
#include "msp430f2274.h"
#define spi_on P4OUT &= ~0x2; // Select the slave device
#define spi_off P4OUT |= 0x2; // Release the slave device
#define wait_tm while ((UCB0STAT & UCBUSY)); // Transmission Done?
#define led_delay __delay_cycles(400000);
#define delay_2 __delay_cycles(10);
#define delay_4 __delay_cycles(200000);
unsigned int i,k,l=0;
char x1,x0,y1,y0,z1,z0;
char tick,ints,devid,dataform,power,fifo,datax,datay,dataz,bufx[60],bufy[60],bufz[60];
void main(void)
{
char read_byte(char byte);
void get_allaxis(char mbyte);
void write_byte(char addr,char data);
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
BCSCTL1 = CALBC1_8MHZ; // Set DCO to 8MHz
DCOCTL = CALDCO_8MHZ;
BCSCTL2 |=0x42; // Set MCLK to 8 MHz and SMCLK to 4Mhz
__bis_SR_register(OSCOFF); // Turn oscilater off
P3SEL |= 0xe; // P3.1,P3.2,P3.3 USCI_B0 option select
P4DIR |= 0x6; // CS P4.1,Power P4.2 to be output
P4OUT &= ~0x6;
// SPI Definations
UCB0CTL1 = UCSWRST; // **Put state machine in reset**
UCB0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master
UCB0CTL0 &= ~UC7BIT;
UCB0CTL1 |= UCSSEL_2; // Select SMCLK as CLK
UCB0BR0 |= 0x02;
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
P4OUT |= BIT2;
led_delay;
P4OUT &= ~BIT2;
led_delay;
P4OUT |= BIT2;
delay_3;
// Read the ID//
spi_on;
devid = read_byte(0x80);
spi_off;
delay_2;
// write to the data format//
spi_on;
write_byte(0x31,0x07);
spi_off;
delay_2;
// make sure write worked//
spi_on;
dataform = read_byte(0xb1);
spi_off;
delay_2;
// write to the power ctl//
spi_on;
write_byte(0x2d,0x08);
spi_off;
delay_2;
//read the power ctl//
spi_on;
power = read_byte(0xad);
spi_off;
delay_2;
//write to the fifo ctl//
spi_on;
write_byte(0x38,0x80);
spi_off;
delay_2;
// make sure write worked//
spi_on;
fifo = read_byte(0xb8);
spi_off;
delay_2;
// Write 1 to Thresh Tap//
spi_on;
write_byte(0x1d,0x01);
spi_off;
delay_2;
// Write 625us to DUR//
spi_on;
write_byte(0x21,0x01);
spi_off;
delay_2;
// Select z as tap axis//
spi_on;
write_byte(0x2a,0x01);
spi_off;
delay_2;
// Enable the single tap int//
spi_on;
write_byte(0x2e,0x40);
spi_off;
delay_2;
P1REN |= BIT2; // Enable pull up/down resistor
P1OUT &= ~BIT2; // pull down the pin
P1IFG &= ~BIT2; // clear the Int. flag
P1IE |= BIT2; // Enable the Int.
P1IES &= ~BIT2; // Low to high transition
__bis_SR_register(GIE); // Enter interrupt
for(;;); // Infinite For loop
}
char read_byte(char byte)
{
IFG2 &= ~UCB0TXIFG;
wait_tm;
UCB0TXBUF = byte; // Adress to be read
wait_tm; // Transmission Done?
UCB0TXBUF = 0xff; // Dummy write
wait_tm;
return UCB0RXBUF;
}
void get_allaxis(char mbyte)
{
IFG2 &= ~UCB0TXIFG;
wait_tm;
UCB0TXBUF = mbyte; // Starting Adress to be read
wait_tm; // Transmission Done?
UCB0TXBUF = 0xff; // Dummy write
wait_tm;
x0 = UCB0RXBUF;
UCB0TXBUF = 0xff;
wait_tm;
x1 = UCB0RXBUF;
UCB0TXBUF = 0xff;
wait_tm;
y0 = UCB0RXBUF;
UCB0TXBUF = 0xff;
wait_tm;
y1 = UCB0RXBUF;
UCB0TXBUF = 0xff;
wait_tm;
z0 = UCB0RXBUF;
UCB0TXBUF = 0xff;
wait_tm;
z1 = UCB0RXBUF;
}
void write_byte(char addr,char data)
{
wait_tm;
IFG2 &= ~UCB0TXIFG;
UCB0TXBUF = addr; // Read Dev ID
wait_tm; // Transmission Done?
UCB0TXBUF = data; // write
wait_tm;
}
// Port 1 GPIO interrupt service routine
#pragma vector = PORT1_VECTOR
__interrupt void port_1 (void)
{
P1IFG &= ~BIT2; // clear the Int. flag
// read the int source to clear the flag//
spi_on;
ints = read_byte(0xb0);
spi_off;
delay_2;
tick++;
__bis_SR_register(GIE); // Enter interrupt
// read all the axis//
for(;;)
{
spi_on;
delay_4;
get_allaxis(0xf2);
spi_off;
delay_4;
}
}
Hi Satbir,
Thanks very much for showing me your code. I think I was doing something wrong with my pin setups. I was able to reliably read the device ID on friday and the other setup registers. I have been trying to format the output into a form that is useful to me. Still trying to do that but I should be able to figure it out.
I didn't seam to have any grounding issues though I have been using an external power supply. Might your grounding problems have been with your choice of pin to power the ADXL345? I mean there is a dedicated VCC on the launchpad and I think you were using one of the I/O pins? Just a thought, anyway thanks again!
Cheers,
Alex
Good to know that you got it working.
I also think that the choice of power supply could have been the reason of my problems.
Satbir
**Attention** This is a public forum