cancel
Showing results for 
Search instead for 
Did you mean: 

Reading bad data from LIS2MDL using 3-wire SPI

Cfaya.1
Associate II

Sensor: LI2MDL

MCU: STML072

I am trying to read the who_am_I register (register 0xAF) with the 3-wire SPI setup, but it is returning the wrong data.

Below is a screenshot of the transmission and the return from the LIS2MDL. The transmission's first bit is SET to indicate that it is a READ operation. The return data should be 0x40, however, the first byte is 0x00, and then comes a second byte of data. 

Cfaya1_1-1690604682247.png

Here's the code to read the data:

nBytesToRead == 1

 

uint8_t Sensor_IO_Read( void *handle, uint8_t ReadAddr, uint8_t *pBuffer, uint16_t nBytesToRead )
{
   //NSS = 0;
    HW_GPIO_Write( MAGNETOMETER_NSS_PORT, MAGNETOMETER_NSS_PIN, 0 );

    uint8_t txData = (ReadAddr | 0x80); // Need to set first bit high for reading 
    HAL_StatusTypeDef status = HAL_SPI_Transmit( &hspi2, &txData,  1, HAL_MAX_DELAY);	
  
    if (status != HAL_OK)
    {
      PRINTF("SPI read transmit failed status: %d\n", status);
      return 1;
    }
    
    status = HAL_SPI_Receive( &hspi2, pBuffer, nBytesToRead, HAL_MAX_DELAY);
    
    if (status != HAL_OK)
    {
      PRINTF("SPI read receive status: %d\n", status);
      return 1;
    }

    //NSS = 1;
    HW_GPIO_Write( MAGNETOMETER_NSS_PORT, MAGNETOMETER_NSS_PIN, 1 );	
    return 0;
}

 

The SPI settings init config is below:

 

  hspi2.Instance = SPI2;
  hspi2.Init.BaudRatePrescaler = SpiFrequency( 1000000 ); 
  hspi2.Init.Direction      = SPI_DIRECTION_1LINE; // SPI 3 wire for LI2MDL
  hspi2.Init.Mode           = SPI_MODE_MASTER;
  hspi2.Init.CLKPolarity    = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase       = SPI_PHASE_1EDGE;
  
  hspi2.Init.DataSize       = SPI_DATASIZE_8BIT;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;  
  hspi2.Init.FirstBit       = SPI_FIRSTBIT_MSB;
  hspi2.Init.NSS            = SPI_NSS_SOFT; //Hardware
  hspi2.Init.TIMode         = SPI_TIMODE_DISABLE;

 

 

I've tried everything I can think of but cannot figure it out. I looked at other registers too, and found that they were also wrong.

When I switch on I2C instead of SPI, everything works fine. I'm trying to use SPI for power savings and speed.

2 REPLIES 2
TDK
Guru

This spike would lead me to believe the device is trying to set SDO high, but it's being pulled down by something else, perhaps the STM32.

TDK_0-1690644409376.png

It's also odd how the data and clock lines seem to rest at values other than 0 and 3.3V at various points, which indicate maybe multiple devices are trying to drive those pins.

TDK_1-1690644622142.png

 

If you can, I would remove the LIS chip, enable an internal pullup on the data line and verify that it gets pulled high when the LIS chip should be outputting to it, then switch it to a pulldown and verify it goes low. My guess is that test will fail.

If you feel a post has answered your question, please click "Accept as Solution".
niccolò
ST Employee

Hi @Cfaya.1,

I wonder if CS stays low for the whole duration of the communication or not, maybe it is driven high by something else? can you share also that screen?
also, can you confirm you write the 4WSPI bit of registerCFG_REG_C (62h) to set the SPI 3 wire?

the suggestion of TDK seems reasonable to me, investigating the comm lines is the best way to tackle the problem =)

If this answers your question, please, mark this as "best answer", by clicking on the "accept as solution" to help the other users of the community

Niccolò