Skip to main content
simoneformichella
Associate
September 10, 2016
Question

STM32F4 Discovery and accelerometer

  • September 10, 2016
  • 28 replies
  • 7077 views
Posted on September 10, 2016 at 20:32

Hi everybody,

I'm writing this post to ask if someone, please, can help me resolving a problem with the datas-reading from the accelerometer integrated in the STM32F4 Evaluation Board.

What I want to do it's simply to read the accelerations datas from the sensor, using the SPI interface. I've had a look at a lot of examples but I still don't know why my code doesn't work.

Here the main functions:

void WriteAccelerometer(SPI_HandleTypeDef SPI, uint8_t address, uint8_t data)

{

       HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET); //CS --> Low

           HAL_SPI_Transmit(&SPI,&address,1,50);

           HAL_SPI_Transmit(&SPI,&data,1,50);

           HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET); //CS --> High

uint8_t ReadAccelerometer(SPI_HandleTypeDef SPI, uint8_t address, uint8_t data)

{

 address = address | 0x80;

 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET); //CS --> Low

          HAL_SPI_Transmit(&SPI,&address,1,50);

 HAL_SPI_Receive(&SPI,&data,1,50);

          HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET); //CS --> High

 return data;

}

Here the SPI configuration function:

static void MX_SPI1_Init(void)

{

  

hspi1.Instance = SPI1;

  hspi1.Init.Mode = SPI_MODE_MASTER;

  hspi1.Init.Direction = SPI_DIRECTION_2LINES;

  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

  hspi1.Init.NSS = SPI_NSS_SOFT;

  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;

  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;

  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;

  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

  hspi1.Init.CRCPolynomial = 10;

  if (HAL_SPI_Init(&hspi1) != HAL_OK)

  {

    Error_Handler();

  }

//WriteAccelerometer(hspi1,0x23,0xC9); //reset

//WriteAccelerometer(hspi1,0x21,0x00);

}

I use the two functions reported in this post to configurate and read the accelerometer with this commands:

uint8_t config_address = 0x20;

uint8_t config_data = 0x27; 

uint8_t Address_ACCX = 0x29;

uint8_t Address_ACCY = 0x2B;

uint8_t Address_ACCZ = 0x2D;

WriteAccelerometer(hspi1,config_address,config_data); //config

// read data:

AccX = ReadAccelerometer(hspi1,Address_ACCX,AccX);

AccY = ReadAccelerometer(hspi1,Address_ACCY,AccY);

AccZ = ReadAccelerometer(hspi1,Address_ACCZ,AccZ);

Thank you in advance for the help..

Simone

    This topic has been closed for replies.

    28 replies

    AvaTar
    Senior III
    September 12, 2016
    Posted on September 12, 2016 at 14:40

    I suggest to download the firmware package for the F4 discovery, as found here:

    http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32-standard-peripheral-libraries-expansions/stsw-stm32068.html

    It contains examples for the MEMS devices, for example in the demo application.

    You can adapt or extend it (using the ''old'' SPL), or trying to port the SPL-based MEMS code to Cube. I would expect the latter to be rather painful...

    Not gonna wade through Cube code, perhaps someone else does ...

    simoneformichella
    Associate
    September 12, 2016
    Posted on September 12, 2016 at 23:19

    Hello AvaTar,

    thank you for your reply.

    I've already had a look at the examples, but what I want to understand it's why my code doesn't work, just to understand if I'm doing something wrong because I've controlled that code a lot of times watching also the accelerometer's datasheet and I really can't find the problem.

    Simone

    AvaTar
    Senior III
    September 13, 2016
    Posted on September 13, 2016 at 10:18

    > I've already had a look at the examples, ...

     

     

    So you have at least a working ''fallback'' code you could build on.

    >... but what I want to understand it's why my code doesn't work, just to understand if I'm doing something wrong because I've controlled that code a lot of times watching also the accelerometer's datasheet and I really can't find the problem.

     

    Have you had a ''working'' minimal version, or have you never got that far ?

    In the latter case (I guess a Cube application build from scratch), I strongly suggest a scope (to view the actual bus communication) and the debugger.

    If you don't have a scope at hand, I strongly suggest to revert back to a known-and-working project - like the firmware example. Not sure if there exists a cube-based equivalent. Some way back I decided not to stain myself with this Cube stuff (it doesn't need you to insert bugs, the code generator can do so all alone - just check out this forum ...). I'm having some F3 and F4 discovery projects using the MEMS sensors, all based on the SPL code and examples.

    Have you been able to debug your code ?

    Luke Dempsey
    Visitor II
    October 28, 2017
    Posted on October 28, 2017 at 09:42

    Hi Simone, 

    Did you end up getting it working? I have very similar code to you and I can see the SPI lines on my oscilloscope working as expected, just no reply.

    Thanks,

    Luke
    S.Ma
    Principal
    October 29, 2017
    Posted on October 29, 2017 at 10:19

    Most of ST Mems, when configured in SPI mode (NSS=low) starts in SPI 4 wire mode.

    You need first to write the control register bit of the mem to switch to 3 wire mode to read back data from the sensor.

    Luke Dempsey
    Visitor II
    October 31, 2017
    Posted on October 31, 2017 at 00:32

    Ahh dang it! I don't initialise the MEMS at register 0x20. Sorry, my first time using SPI, I thought I could just send a request for the WHO_AM_I ID (0x0F) to test if it was working.

    I'm at work at the moment, I'll try when I get home and reply here.
    Zek_De
    Senior
    October 30, 2017
    Posted on October 30, 2017 at 21:43

    Is this problem proceding?I have same problem.

    Zek_De
    Senior
    October 31, 2017
    Posted on October 31, 2017 at 10:20

    Hi

    Dempsey.Luke

    ,

    if you send here your simple example,I will be so glad.

    Luke Dempsey
    Visitor II
    October 31, 2017
    Posted on October 31, 2017 at 11:46

    My function definitions are:

    void

    MEMS_write(

    uint8_t

    addr,

    uint8_t

    data){

       

    uint8_t

    send[2] = {addr, data};

       

    HAL_GPIO_WritePin(

    CS_I2C_SPI_GPIO_Port

    , CS_I2C_SPI_Pin, LOW);

       HAL_SPI_Transmit(&hspi1, send, 2, 5000);

       

    HAL_GPIO_WritePin(CS_I2C_SPI_GPIO_Port, CS_I2C_SPI_Pin, HIGH);

       

    return

    ;

    }

    uint8_t

    MEMS_read(

    uint8_t

    addr){

       

    uint8_t

    send[1] = {0x80 | addr};

       

    uint8_t

    out[1] = {0x00};

       

    HAL_GPIO_WritePin(CS_I2C_SPI_GPIO_Port, CS_I2C_SPI_Pin, LOW);

       

    HAL_SPI_TransmitReceive(&hspi1, send, out, 2, 0xFF);

       

    HAL_GPIO_WritePin(CS_I2C_SPI_GPIO_Port, CS_I2C_SPI_Pin, HIGH);

       

    return

    out[1];

    }

    My simplified main is: (omitting non-spi code for readability)

    int main(void){ 

      MEMS_write(0x24, 0b1000000);

    //rebooting the

    mems

    seems to unlock it?

     

    HAL_Delay(100);

     

    MEMS_write(0x20, 0x67); //enable x, y, z axes and ODR

     

    MEMS_write(0x24, 0x01);

    //3 wire

    spi

     

    while

    (1)

     

    {

     

    MEMS_read(0x0F); //request WHO_AM_I

     

    HAL_Delay(10);

     

    }

    }

    Zek_De
    Senior
    October 31, 2017
    Posted on October 31, 2017 at 12:30

    As much as I see I m doing it right but I think my mistake is about CPHA ,adxl345 settings says CPOL=1 and CPHA=1 and I did CPOL = 0 and CPHA = 1 edge ,point I dont know what it '1 edge' is .You can see it in CubeMX .Actually you probably already know it.Also other option is 2 edge

    Luke Dempsey
    Visitor II
    October 31, 2017
    Posted on October 31, 2017 at 13:12

    Ahh you're not using the same MEMS as me. I'm using the LIS3DSH. Google SPI modes, and have a look what mode matches your ADXL datasheet and set your CPOL and CPHA accordingly.

    Also as you are using a different ic, you will probably have different register addresses.

    Zek_De
    Senior
    October 31, 2017
    Posted on October 31, 2017 at 13:39

    Actually I tried to use the 

    LIS3DSH but no getting value.Maybe interested cpol and cpha now I have come home,I will look it and try.

    Zek_De
    Senior
    October 31, 2017
    Posted on October 31, 2017 at 13:57

    Again no value ,Ok I am sending some code maybe you can understand my mistake.

    if(HAL_SPI_GetState(hspi) == HAL_SPI_STATE_READY )

    {

    a = BW_RATE;

    b = 0x0D;

    HAL_GPIO_WritePin(ADXL345_CS_GPIO_Port,ADXL345_CS_Pin, GPIO_PIN_RESET);

    HAL_SPI_Transmit(hspi,&a,1,100);//800Hz ODR , Normal mode

    HAL_SPI_Transmit(hspi,&b,1,100);

    HAL_GPIO_WritePin(ADXL345_CS_GPIO_Port,ADXL345_CS_Pin, GPIO_PIN_SET);

    a = POWER_CTL;

    b = 0x08;

    HAL_GPIO_WritePin(ADXL345_CS_GPIO_Port,ADXL345_CS_Pin, GPIO_PIN_RESET);

    HAL_SPI_Transmit(hspi,&a,1,100);////Measurement mode

    HAL_SPI_Transmit(hspi,&b,1,100);

    HAL_GPIO_WritePin(ADXL345_CS_GPIO_Port,ADXL345_CS_Pin, GPIO_PIN_SET);

    }

    else

    above codes are to set.

    below codes are to get values

    do

    {

    adress = INT_SOURCE | 0x80;

    HAL_GPIO_WritePin(ADXL345_CS_GPIO_Port,ADXL345_CS_Pin, GPIO_PIN_RESET);

    HAL_SPI_Transmit(hspi,&adress,1,100);

    HAL_SPI_Receive(hspi,&temp,1,100);

    HAL_GPIO_WritePin(ADXL345_CS_GPIO_Port,ADXL345_CS_Pin, GPIO_PIN_SET);

    }while((temp & 0x80) == 0);

    moving is stucking in loop.Am I wrong in this step ' 

    adress = INT_SOURCE | 0x80; '

    As much as I know this is a way to get value with SPI related 0x80.

    Luke Dempsey
    Visitor II
    October 31, 2017
    Posted on October 31, 2017 at 22:11

    What are the values of BW_RATE, POWER_CTL

    and INT_SRC?

    Zek_De
    Senior
    October 31, 2017
    Posted on October 31, 2017 at 22:13

    #define DATA_FORMAT (uint8_t)0x31 

    #define BW_RATE (uint8_t)0x2C

    #define POWER_CTL (uint8_t)0x2D

    #define FIFO_CTL (uint8_t)0x38

    #define DATAXL (uint8_t)0x32

    #define DATAXH (uint8_t)0x33

    #define DATAYL (uint8_t)0x34

    #define DATAYH (uint8_t)0x35

    #define DATAZL (uint8_t)0x36

    #define DATAZH (uint8_t)0x37

    #define OFSX (uint8_t)0x1E

    #define OFSY (uint8_t)0x1F

    #define OFSZ (uint8_t)0x20

    #define INT_ENABLE (uint8_t)0x2E 

    #define INT_SOURCE (uint8_t)0x30