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.

CCS/EK-TM4C123GXL: I am having trouble reading ADXL345 data through spi

Part Number: EK-TM4C123GXL

Tool/software: Code Composer Studio

I am not getting any reading from the peripheral (ADXL345)

I tried reading device ID(which should be 0xe5), but it returns 0. All the data values I get is 0.

Here's my code:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

#define READ    0x8000

// Register Codes
#define DEVID           0x00
#define THRESH_TAP      0x1D
#define OFSX            0x1E
#define OFSY            0x1F
#define OFSZ            0x20
#define DUR             0x21
#define LATENT          0x22
#define WINDOW          0x23
#define THRESH_ACT      0x24
#define THRESH_INACT    0x25
#define TIME_INACT      0x26
#define ACT_INACT_CTL   0x27
#define THRESH_FF       0x28
#define TIME_FF         0x29
#define TAP_AXES        0x2A
#define ACT_TAP_STATUS  0x2B
#define BW_RATE         0x2C
#define POWER_CTL       0x2D
#define INT_ENABLE      0x2E
#define INT_MAP         0x2F
#define INT_SOURCE      0x30
#define DATA_FORMAT     0x31
#define DATAX0          0x32
#define DATAX1          0x33
#define DATAY0          0x34
#define DATAY1          0x35
#define DATAZ0          0x36
#define DATAZ1          0x37
#define FIFO_CTL        0x38
#define FIFO_STATUS     0x39
//Power Control Register Bits
#define WU_0        (1<<0)    //Wake Up Mode - Bit 0
#define WU_1        (1<<1)    //Wake Up mode - Bit 1
#define SLEEP       (1<<2)    //Sleep Mode
#define MEASURE     (1<<3)    //Measurement Mode
#define AUTO_SLP    (1<<4)    //Auto Sleep Mode bit
#define LINK        (1<<5)    //Link bit

//Interrupt Enable/Interrupt Map/Interrupt Source Register Bits
#define OVERRUN     (1<<0)
#define WATERMARK   (1<<1)
#define FREE_FALL   (1<<2)
#define INACTIVITY  (1<<3)
#define ACTIVITY    (1<<4)
#define DOUBLE_TAP  (1<<5)
#define SINGLE_TAP  (1<<6)
#define DATA_READY  (1<<7)

//Data Format Bits
#define RANGE_0     (1<<0)
#define RANGE_1     (1<<1)
#define JUSTIFY     (1<<2)
#define FULL_RES    (1<<3)

#define INT_INVERT  (1<<5)
#define SPI         (1<<6)
#define SELF_TEST   (1<<7)

#define PIN_LOW 0x00
#define PIN_HIGH 0xFF
int i=0;
void InitConsole(void) {
    // Enable GPIO port A which is used for UART0 pins.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    // Configure the pin muxing for UART0 functions on port A0 and A1.
    // This step is not necessary if your part does not support pin muxing.
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    // Enable UART0 so that we can configure the clock.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    // Use the internal 16MHz oscillator as the UART clock source.
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

    // Select the alternate (UART) function for these pins.
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    // Initialize the UART for console I/O.
    UARTStdioConfig(0, 115200, 16000000);
}

void InitSPI(void) {
    // The SSI2 peripheral must be enabled for use.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);

    // Enable Port B
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    // SETUP SPI CS Pin (to output)
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_5);

    // Set SPI CS to HIGH (active-low)
    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_6, 0xFF);

    // Configure the pin muxing for SSI2 functions on port B4, B5, B6, and B7.
    GPIOPinConfigure(GPIO_PB4_SSI2CLK);
    GPIOPinConfigure(GPIO_PB5_SSI2FSS);
    GPIOPinConfigure(GPIO_PB6_SSI2RX);
    GPIOPinConfigure(GPIO_PB7_SSI2TX);

    // Configure the GPIO settings for the SSI pins.
    GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);

    // Configure and enable the SSI port for SPI master mode.  Use SSI2,
    // system clock supply, idle clock level low and active low clock in
    // freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data.
    // For SPI mode, you can set the polarity of the SSI clock when the SSI
    // unit is idle.  You can also configure what clock edge you want to
    // capture data on.  Please reference the datasheet for more information on
    // the different SPI modes.
    SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 1000000, 8);

    // Enable the SSI2 module.
    SSIEnable(SSI2_BASE);

    // Read any residual data from the SSI port.  This makes sure the receive
    // FIFOs are empty, so we don't read any unwanted junk.  This is done here
    // because the SPI SSI mode is full-duplex, which allows you to send and
    // receive at the same time.  The SSIDataGetNonBlocking function returns
    // "true" when data was returned, and "false" when no data was returned.
    // The "non-blocking" function checks if there is any data in the receive
    // FIFO and does not "hang" if there isn't.
    uint32_t scrap;
    while(SSIDataGetNonBlocking(SSI2_BASE, &scrap));
}


int main(void) {

    // Set the clocking to run directly from the external crystal/oscillator.
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    // Set up UART Serial Output
    InitConsole();

    // Set up SSI2 for SPI Communication
    InitSPI();

    UARTprintf("............................................\n");

    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5, 0x00);
    SSIDataPut(SSI2_BASE, 0x31); // DATA_FORMAT
    while(SSIBusy(SSI2_BASE));
    SSIDataPut(SSI2_BASE, 0x01); // +/- 4g
    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5, 0xFF);

    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5, 0x00);
    SSIDataPut(SSI2_BASE, 0x2D); // POWER_CTL
    while(SSIBusy(SSI2_BASE));
    SSIDataPut(SSI2_BASE, 0x08);
    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5, 0xFF);

    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5, 0x00);
    SSIDataPut(SSI2_BASE, POWER_CTL|MEASURE); //Put the Accelerometer into measurement mode
    while(SSIBusy(SSI2_BASE)){}
    SSIDataPut(SSI2_BASE, 0x08);
    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5, 0xFF);

    uint32_t device_id;
    SSIDataPut(SSI2_BASE, READ|DEVID);
    SSIDataGet(SSI2_BASE, &device_id);
    while(SSIBusy(SSI2_BASE)){}
    UARTprintf("%i\n", device_id);

    while (1) {

        uint32_t values[6];
        int16_t x, y, z;




               SSIDataPut(SSI2_BASE, READ|DATAX0);
               SSIDataGet(SSI2_BASE, &values[0]);
               while(SSIBusy(SSI2_BASE)){}
               SSIDataPut(SSI2_BASE, READ|DATAX1);
               SSIDataGet(SSI2_BASE, &values[1]);
               while(SSIBusy(SSI2_BASE)){}
               x = values[1] | (values[0]>>8);


               SSIDataPut(SSI2_BASE, READ|DATAY0);
               SSIDataGet(SSI2_BASE, &values[2]);
               while(SSIBusy(SSI2_BASE)){}
               SSIDataPut(SSI2_BASE, READ|DATAY1);
               SSIDataGet(SSI2_BASE, &values[3]);
               while(SSIBusy(SSI2_BASE)){}
               y = values[3] | (values[2]>>8);


               SSIDataPut(SSI2_BASE, READ|DATAZ0);
               SSIDataGet(SSI2_BASE, &values[4]);
               while(SSIBusy(SSI2_BASE)){}
               SSIDataPut(SSI2_BASE, READ|DATAZ1);
               SSIDataGet(SSI2_BASE, &values[5]);
               while(SSIBusy(SSI2_BASE)){}
               z = values[5] | (values[4]>>8);

        UARTprintf("%i\t\t%i\t\t%i\n", x, y, z);

        SysCtlDelay(50 * (SysCtlClockGet() /1000 /3));

    }

    return(0); // will never return
}

This is the output I am getting in puTTY:

............................................

0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

0               0               0

These are the warnings I am getting:

What am I missing?

  • I cannot debug your entire code, but there are some things I see. First, it would help you if you put a logic analyzer on your SSI pins and then you can see what the TM4C is sending and what the ADXL345 responds with. Next, look again at the ADXL345 data sheet. Using SPI mode, the transfers are 16 bits between CS low and CS high. You have configured the TM4C to transfer 8 bits and configured PB5 as SSI2FSS. That means it will go low at the start and high at the end of each 8 bit transfer. Your GPIOPinWrite() calls are ignored since you configured the pin as SSI2FSS.

    You have two options,

    1: use 16-bit transfers with SSI2FSS. This is simplest, but does not allow for reading or writing multiple bytes in a single transaction.

    2: You can configure PB5 as a GPIO and use GPIOPinWrite() to toggle it low then high. Easy and flexible, but not very efficient. Set PB5 low then do two 8 bit SSIDataPut() followed by two SSIDataGet(). The data returned from the second SSIDataGet() will contain the response from the ADXL345. Wait until after the second SSIDataGet() returns before raising PB5. (Note: transfers only happen with calls to SSIDataPut(), SSIDataGet() simply returns the data from the FIFO that was captured during a previous SSIDataPut().)