Skip to main content
Associate II
February 27, 2025
Question

LIS2MDL SPI 4 Wires

  • February 27, 2025
  • 3 replies
  • 579 views

Hi,

I'm trying to use LIS2MDL magnetometer sensor with 4 wire bus but I'm encountering a problem with the library.

Here is my init function:

AKE1_1-1740668649031.png

lis2mdl.c library screenshot:

AKE1_0-1740668313869.png

On line 122,  my instance is always initialized (is_initialized=1) by the init function (line 113) so it always bypass the line 124 to init the SPI 4 wires.

I resolved the problem by replacing the == by != to force the program to init the 4 wires SPI. 

Is there a mistake in the library or do I do something wrong ? 

3 replies

Andrew Neil
Super User
February 27, 2025

Please see How to insert source code - not as images.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
AKE1Author
Associate II
February 27, 2025

 

/**
 ******************************************************************************
 * @file lis2mdl.c
 * @author MEMS Software Solutions Team
 * @brief LIS2MDL driver file
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2019 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "lis2mdl.h"

/** @addtogroup BSP BSP
 * @{
 */

/** @addtogroup Component Component
 * @{
 */

/** @defgroup LIS2MDL LIS2MDL
 * @{
 */

/** @defgroup LIS2MDL_Exported_Variables LIS2MDL Exported Variables
 * @{
 */

LIS2MDL_CommonDrv_t LIS2MDL_COMMON_Driver =
{
 LIS2MDL_Init,
 LIS2MDL_DeInit,
 LIS2MDL_ReadID,
 LIS2MDL_GetCapabilities,
};

LIS2MDL_MAG_Drv_t LIS2MDL_MAG_Driver =
{
 LIS2MDL_MAG_Enable,
 LIS2MDL_MAG_Disable,
 LIS2MDL_MAG_GetSensitivity,
 LIS2MDL_MAG_GetOutputDataRate,
 LIS2MDL_MAG_SetOutputDataRate,
 LIS2MDL_MAG_GetFullScale,
 LIS2MDL_MAG_SetFullScale,
 LIS2MDL_MAG_GetAxes,
 LIS2MDL_MAG_GetAxesRaw,
};

/**
 * @}
 */

/** @defgroup LIS2MDL_Private_Function_Prototypes LIS2MDL Private Function Prototypes
 * @{
 */
static int32_t ReadMagRegWrap(void *Handle, uint8_t Reg, uint8_t *pData, uint16_t Length);
static int32_t WriteMagRegWrap(void *Handle, uint8_t Reg, uint8_t *pData, uint16_t Length);
static int32_t LSM6DSOX_SENSORHUB_LIS2MDL_ReadShData(LIS2MDL_Object_t *pObj, uint8_t Reg, uint8_t *pData,
 uint16_t Length);
static int32_t LSM6DSOX_SENSORHUB_LIS2MDL_WriteShData(LIS2MDL_Object_t *pObj, uint8_t Reg, uint8_t *pData,
 uint16_t Length);

/**
 * @}
 */

/** @defgroup LIS2MDL_Exported_Functions LIS2MDL Exported Functions
 * @{
 */

/**
 * @brief Register Component Bus IO operations
 * @PAram pObj the device pObj
 * @retval 0 in case of success, an error code otherwise
 */
int32_t LIS2MDL_RegisterBusIO(LIS2MDL_Object_t *pObj, LIS2MDL_IO_t *pIO)
{
 int32_t ret = LIS2MDL_OK;

 if (pObj == NULL)
 {
 ret = LIS2MDL_ERROR;
 }
 else
 {
 pObj->IO.Init = pIO->Init;
 pObj->IO.DeInit = pIO->DeInit;
 pObj->IO.BusType = pIO->BusType;
 pObj->IO.Address = pIO->Address;
 pObj->IO.WriteReg = pIO->WriteReg;
 pObj->IO.ReadReg = pIO->ReadReg;
 pObj->IO.GetTick = pIO->GetTick;

 pObj->Ctx.read_reg = ReadMagRegWrap;
 pObj->Ctx.write_reg = WriteMagRegWrap;
 pObj->Ctx.mdelay = pIO->Delay;
 pObj->Ctx.handle = pObj;

 if (pObj->IO.Init == NULL)
 {
 ret = LIS2MDL_ERROR;
 }
 else if (pObj->IO.Init() != LIS2MDL_OK)
 {
 ret = LIS2MDL_ERROR;
 }
 else
 {
 if (pObj->IO.BusType != LIS2MDL_I2C_BUS) /* If the bus type is not I2C */
 {
 /* Disable I2C interface support and enable eventually SPI 4-Wires only the first time */
 if (pObj->is_initialized == 0U)
 {
 if (pObj->IO.BusType == LIS2MDL_SPI_4WIRES_BUS) /* SPI 4-Wires */
 {
 /* Enable SPI 4-Wires and disable I2C support on the component */
 uint8_t data = 0x34;

 if (LIS2MDL_Write_Reg(pObj, LIS2MDL_CFG_REG_C, data) != LIS2MDL_OK)
 {
 return LIS2MDL_ERROR;
 }
 }
 else if (pObj->IO.BusType == LSM6DSOX_SENSORHUB_LIS2MDL_I2C_BUS) /* LSM6DSOX SensorHub with LIS2MDL example */
 {
 /* Do nothing, just keep I2C support on the component */
 return ret;
 }
 else
 {
 /* Disable I2C interface on the component */
 if (lis2mdl_i2c_interface_set(&(pObj->Ctx), LIS2MDL_I2C_DISABLE) != LIS2MDL_OK)
 {
 return LIS2MDL_ERROR;
 }
 }
 }
 }
 }
 }

 return ret;
}

/**
 * @brief Initialize the LIS2MDL sensor
 * @PAram pObj the device pObj
 * @retval 0 in case of success, an error code otherwise
 */
int32_t LIS2MDL_Init(LIS2MDL_Object_t *pObj)
{
 lis2mdl_cfg_reg_a_t reg_a;
 lis2mdl_cfg_reg_c_t reg_c;

 if (pObj->IO.BusType == LSM6DSOX_SENSORHUB_LIS2MDL_I2C_BUS) /* LSM6DSOX SensorHub with LIS2MDL example */
 {
 /* Read configuration from CFG_REG_C & CFG_REG_A regs */
 if (LSM6DSOX_SENSORHUB_LIS2MDL_ReadShData(pObj, LIS2MDL_CFG_REG_C, (uint8_t *)&reg_c, 1) != LIS2MDL_OK)
 {
 return LIS2MDL_ERROR;
 }
 if (LSM6DSOX_SENSORHUB_LIS2MDL_ReadShData(pObj, LIS2MDL_CFG_REG_A, (uint8_t *)&reg_a, 1) != LIS2MDL_OK)
 {
 return LIS2MDL_ERROR;
 }

 /* Enable BDU */
 reg_c.bdu = PROPERTY_ENABLE;

 /* Self Test disabled. */
 reg_c.self_test = PROPERTY_DISABLE;

 /* Operating mode selection - power down */
 reg_a.md = LIS2MDL_POWER_DOWN;

 /* Output data rate selection */
 reg_a.odr = LIS2MDL_ODR_100Hz;

 /* Write configuration to CFG_REG_C & CFG_REG_A regs */
 if (LSM6DSOX_SENSORHUB_LIS2MDL_WriteShData(pObj, LIS2MDL_CFG_REG_C, (uint8_t *)&reg_c, 1) != LIS2MDL_OK)
 {
 return LIS2MDL_ERROR;
 }
 if (LSM6DSOX_SENSORHUB_LIS2MDL_WriteShData(pObj, LIS2MDL_CFG_REG_A, (uint8_t *)&reg_a, 1) != LIS2MDL_OK)
 {
 return LIS2MDL_ERROR;
 }
 }
 else
 {
 /* Enable BDU */
 if (lis2mdl_block_data_update_set(&(pObj->Ctx), PROPERTY_ENABLE) != LIS2MDL_OK)
 {
 return LIS2MDL_ERROR;
 }

 /* Operating mode selection - power down */
 if (lis2mdl_operating_mode_set(&(pObj->Ctx), LIS2MDL_POWER_DOWN) != LIS2MDL_OK)
 {
 return LIS2MDL_ERROR;
 }

 /* Output data rate selection */
 if (lis2mdl_data_rate_set(&(pObj->Ctx), LIS2MDL_ODR_100Hz) != LIS2MDL_OK)
 {
 return LIS2MDL_ERROR;
 }

 /* Self Test disabled. */
 if (lis2mdl_self_test_set(&(pObj->Ctx), PROPERTY_DISABLE) != LIS2MDL_OK)
 {
 return LIS2MDL_ERROR;
 }
 }

 pObj->is_initialized = 1;

 return LIS2MDL_OK;
}

 

AKE1Author
Associate II
February 27, 2025
void init_MAGNETO(void)
{
	LIS2MDL_IO_t IO_MAGNETO;
	LIS2MDL_Capabilities_t capabilities_MAGNETO;
	uint8_t ID_MAGNETO = 0U;

	IO_MAGNETO.Init = LIS2MDL_Init;
	IO_MAGNETO.DeInit = LIS2MDL_DeInit;
	IO_MAGNETO.BusType = LIS2MDL_SPI_4WIRES_BUS;
	IO_MAGNETO.WriteReg = LIS2MDL_WriteReg_SPI;
	IO_MAGNETO.ReadReg = LIS2MDL_ReadReg_SPI;

	LIS2MDL_RegisterBusIO(&MAGNETO, &IO_MAGNETO);
	LIS2MDL_GetCapabilities(&MAGNETO, &capabilities_MAGNETO);

	HAL_Delay(20);

	LIS2MDL_ReadID(&MAGNETO, &ID_MAGNETO);
	if (ID_MAGNETO != LIS2MDL_ID)
	{
		Error_Handler();
	}

	LIS2MDL_MAG_Enable(&MAGNETO);
}