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.

CC2540 and STM LIS3DH

Other Parts Discussed in Thread: CC2540

Good Morning,

it's the frist time for me in programming for this kind of devices and i'm stuck on what i thought to be a simple task, interfacing the LIS3DH accelerometer ( ) . The device is connected to usart1 alternative location 2. I used the code from the cma3000 included in the keyfob as a guide but i still can't read a thing.

Here is my code

#include <ioCC2540.h>
#include "lis3dh.h"

//***********************************************************************************
// Defines

//USART 1 Aternative 2 - PERCFG.U1CFG = 1
#define CS              P1_4//SSN
#define SCK             P1_5
#define MOSI            P1_6
#define MISO            P1_7



#define INT1            P1_1
#define INT2            P1_0


#define CS_DISABLED     1
#define CS_ENABLED      0


//***********************************************************************************
// Function prototypes
void spiWriteByte(uint8 write);
void spiReadByte(uint8 *read, uint8 write);

void spiWriteByte(uint8 write)
{
        U1CSR &= ~0x02;                 // Clear TX_BYTE
        U1DBUF = write;
        while (!(U1CSR & 0x02));        // Wait for TX_BYTE to be set
}

/** \brief    Read one byte from SPI interface
*
* Read one byte from SPI interface
*
* \param[in]       read
*     Read out value
* \param[in]       write
*     Value to write
*/
void spiReadByte(uint8 *read, uint8 write)
{
        U1CSR &= ~0x02;                 // Clear TX_BYTE
        U1DBUF = write;
        while (!(U1CSR & 0x02));        // Wait for TX_BYTE to be set
        *read = U1DBUF;
}

void accWriteReg(uint8 reg, uint8 val)
{
    CS = CS_ENABLED;
    //spiWriteByte(reg|0x02);//
    spiWriteByte(reg);
    spiWriteByte(val);
    CS = CS_DISABLED;
}


/** \brief    Read one byte from a sensor register
*
* Read one byte from a sensor register
*
* \param[in]       reg
*     Register address
* \param[in]       *pVal
*     Pointer to variable to put read out value
*/
void accReadReg(uint8 reg, uint8 *pVal)
{
    CS = CS_ENABLED;
    spiWriteByte(reg|0x80);
    //spiReadByte(pVal, 0xFF);
    spiReadByte(pVal, 0xFF);
    CS = CS_DISABLED;
}


void initSpi(void)
{
  P0_2 = 1;
  // Set Peripheral Config for USART1 alternative location 1
  PERCFG |= 0x02;// PERCFG.U1CFG = 1
  //Configure Port1 GPIO pins
  P1SEL |= 0xE0;// P1_7, P1_6, and P1_5 are peripherals
  //P1SEL &= ~0x10;// P1_4 is GPIO (SSN)
  P1DIR |= 0x10;// SSN is set as output
 
  // Slave Mode
  //PERCFG |=0x02;// PERCFG.U1CFG = 1
  //P1SEL |= 0xF0;// P1_7, P1_6, P1_5, and P1_4 are peripherals
  /*--------------------------------------------------------------------------------
     Master            Slave
  -------------          -------------
  |           |          |           |
  |P1_4    SSN|--------->|SSN    P1_4|
  |           |          |           |
  |P1_5    SCK|--------->|SCK    P1_5|
  |           |          |           |
  |P1_6   MOSI|--------->|MOSI   P1_6|
  |           |          |           |
  |P1_7   MISO|<---------|MISO   P1_7|
  |           |          |           |
  -------------          -------------
  --------------------------------------------------------------------------------*/
  // SPI Master Mode
  //U1CSR &= ~0xA0;
  U1CSR = 0;
 
  //CPOL = 1 Positive Clock Polarity ( SCK high when idle)
  //CPHA = 1: Data is output on MOSI when SCK goes from CPOL to CPOL inverted, and data input
  //          is sampled on MISO when SCK goes from CPOL inverted to CPOL.
  U1GCR |= 0xC0;
 
  // MSB first
  U1GCR |= 0x20;
 
  /*
  Forumula per calcolo frequenza clock spi
 
                BAUD_M        BAUD_E
  Fsck = (256 + U1BAUD) * 2^U1GCR.BAUD_E * SystemClock  / 2^28
  480KHz (256 + 236) * 2^13 * 32Mhz / 2^28
  10Mhz =(256 + 64) * 2^18 * 32Mhz / 2^28
  */
  // SCK frequency = 480.5kHz
  U1GCR |= 0x0D;
  U1BAUD = 0xEC;
 
 
 
  //sck frequency = 10MHz
  //U1GCR |= 0x12;//BAUD_M
  //U1BAUD = 0x40;//BAUD_E
 
  CS = CS_DISABLED;
  SCK = CS_DISABLED;
 
  uint8 stat_whoami;
  P0_3 = 1;
  do{
    accReadReg(WHO_AM_I,&stat_whoami);
    WAIT_1_3US(80);
    }while(stat_whoami != 0x33);
 
  //P0 |= 0x08;  
  P0_3 = 0;
  accStop();//per essere sicuri che l'accelerometro sia spento una volta inizializzta l'spi
}

void accStop(void)
{
  accWriteReg(CTRL_REG1,ALL_OFF);
}

void accStart(void)
{
  accWriteReg(CTRL_REG1,ALL_AXIS_ON_50HZ_NP);
}



/** \brief    Read x, y and z acceleration data
*
* Read x, y and z acceleration data in one operation.
* NOTE: No sensor access must be made immidiately following this operation
* without enabling the last Wait call.
*
* \param[in]       *buff
*     Pointer to variable to AxesRaw structure to be filled with data
*/

/*
*/

void accReadAcc(AxesRaw* buff)
{
    int16 value;
    uint8 *valueH = (uint8 *)(&value);
    uint8 *valueL = ((uint8 *)(&value)+1);
    // X
    accReadReg(OUT_X_L, valueL);
    accReadReg(OUT_X_H, valueH);
    buff->AXIS_X = value;
    WAIT_1_3US(80);

    // Y
    accReadReg(OUT_Y_L, valueL);
    accReadReg(OUT_Y_H, valueH);
    buff->AXIS_Y = value;
    WAIT_1_3US(80);

    //Z
    accReadReg(OUT_Z_L, valueL);
    accReadReg(OUT_Z_H, valueH);
    buff->AXIS_Z = value;

    //WAIT_1_3US(80);
}

#ifndef LIS3DH
#define LIS3DH
#endif

#include "hal_types.h"

// LIS3DH addressing space
#define WHO_AM_I        0x0F
#define CTRL_REG1       0x20
#define CTRL_REG3       0x22

#define OUT_X_L         0x28
#define OUT_X_H         0x29
#define OUT_Y_L         0x2A
#define OUT_Y_H         0x2B
#define OUT_Z_L         0x2C
#define OUT_Z_H         0x2D

// CTRL register definitions

#define ALL_OFF         0x00
#define ALL_AXIS_ON_50HZ_NP         0x47
#define ALL_AXIS_ON_50HZ_LP         0x4F
#define ALL_AXIS_ON_10HZ_LP         0x2F



//***********************************************************************************
// Macros

// Wait 1+1/3*t [us]
#define WAIT_1_3US(t)                   \
    do{                                 \
        for (uint8 i = 0; i<t; i++)     \
            asm("NOP");                 \
    }while(0)


typedef struct {
  int16 AXIS_X;
  int16 AXIS_Y;
  int16 AXIS_Z;
} AxesRaw;

void initSpi(void);
void accStart(void);
void accStop(void);
void accWriteReg(uint8 reg, uint8 val);
void accReadReg(uint8 reg, uint8 *pVal);
void accReadAcc(AxesRaw* buff);

The initSpi function is called once during the initialization of the device. Pleas give me an hand, this thing is driving me crazy :P

  • I suggest you using scope to check your SPI signal. You sould make sure CS/SCLK signal is correct first.

  • I will but considering this is the first time for me to code for the 2540 i wanted to be sure that the code is right

  • It will be easier for us to help you if you can use scope to verify SPI signal. If signal is not correct, there might be problem in your code. Otherwise, the problem is on your slave device or interface connection.

  • Hello Andrea,

    I haven't used this device in SPI mode, but the LIS331DH in i2c mode.  Make sure that the CS pin is low when the device is powered, otherwise it will be in i2c mode.

    Thanks,

  • CS has to be low only at startup ? The datasheet says that cs has to go from hi to low during a read or write operation and then back to hi at the end of the r/w.

  • Only at startup.  The data sheet states that in order to set the communication protocol to I2c, CS has to be tied to VCC.  This would imply that if the port pin is high at startup then the device would be in i2c mode and not SPI.  I could be wrong though, as I mentioned in the previous post, I have only used a similar device in i2c mode, not SPI.

    Thanks,

  • Here are some scope data of:

    Write at 0x20 value 0x47 ( first 16bit)

    Rread register 0x0F|0x80 (first bit has to be 1 to read).

    (purple MOSI green MISO)

    Data sent to the accelerometer  seem to be valid but data that are coming back certainly aren't

  • It looks like there are something wrong with the MISO connection between CC2540 and lis3dh. I suggest that you disconnect the MISO of lis3dh from CC2540 and measure the lis3dh MISO first. See if the signal will be correct without connection first.

  • Hello,

    I have exactly the same problems with my LIS3DH device. Did you managed to solve your problem? If yes, how? The thing is I cannot disconnect the MISO line from LIS3DH because is QFN. Maybe I could disconnect from uC.

    Looking forward to get some answers,

    Mircea

  • I come with more details:

    VCC_IO is not connected to anything and the MISO pin from the microcontroller is "on air", so it doesn't influence the output of the LIS3DH initialization.

    The initialization procedure from my code is:

    Cma3000_writeRegister(0x20,0x47);
    ACCEL_CS_HIGH;
    halMcuWaitMs(5);

    Cma3000_writeRegister(0x23,0x82);
    ACCEL_CS_HIGH;
    halMcuWaitMs(5);

    // who am I? expected 0x33
    uint8_t Who_am_I = Cma3000_readRegister(0x0F);

    In write_Register I put CS_LOW and send/receive the data. Could anyone give me some ides?