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.

SPI Question

Other Parts Discussed in Thread: MSP430G2553, MSP430F2274

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