cancel
Showing results for 
Search instead for 
Did you mean: 

LIS3MDL always output magnetic data 0 wrongly

PFeng.1
Associate

Hello, support team.

In my design, I use 4-wire spi to transfer data between STM32F407 and LIS3MDL.

Here is my configuration to LIS3MDL.

CTRL_REG2 0x40 //Full-scale selection ±12 Gauss

CTRL_REG1 0x02 //XY low-power mode ODR 1000Hz

CTRL_REG4 0x00 //Z low-power mode ODR 1000Hz

CTRL_REG3 0x00 //Continuous-conversion mode

CTRL_REG5 0x40 //block data update for magnetic data.

The questions are as follows.

1.In the main function, firstly, I check the data from WHO_AM_I register. The output data is not 0x3D(default) but 0xFF. I don't know the reason. Does that affect anything?

2.Then, I write data CTRL_REG2_SOFT_RST(0x04) to CTRL_REG2 to reset the register. The output data from CTRL_REG2 to CTRL_REG5 are the same as the default data. ButI wonder why the output data from CTRL_REG1 is 0x18 (default data is 0x10). Does that affect anything?

3.After 2, I initialize the register as the data and order listed above. The data output by 4-wire SPI is the same as what I wirte.

4.Finally, I use the STATUS_REG register to help the data collecting (as the DoclD027014 AN4602 Application note). However, the detecting manegtic data result is totally wrong! It output data "0" of X,Y and Z continulsy, which is absolutely wrong. I don't know what happened cause I wrote the accurate configuration data to the register.

Here is my code.

How can I read magnetic data accurately at 1kHz speed?

Hope for your early reply. Thanks

Penghao

int main(void)
{	
  unsigned char STATUS,flag;
	//help the STATUS_REG
	float *Data;
        Debug_USART_Config();
	SPI3_Init();
	printf("%x\n",READ_DATA_SPI(ADD_WHO_AM_I_R));
	WRITE_DATA_SPI(ADD_CTRL_REG2_W,CTRL_REG2_SOFT_RST);
 
	printf("%x %x %x %x %x\n",READ_DATA_SPI(ADD_CTRL_REG1_R),READ_DATA_SPI(ADD_CTRL_REG2_R),READ_DATA_SPI(ADD_CTRL_REG3_R),READ_DATA_SPI(ADD_CTRL_REG4_R),READ_DATA_SPI(ADD_CTRL_REG5_R));
	LIS3MDL_init(CTRL_REG1_1000,CTRL_REG2_12,CTRL_REG3_CM,CTRL_REG4_1000,CTRL_REG5_BDU);
	printf("%x %x %x %x %x\n",READ_DATA_SPI(ADD_CTRL_REG1_R),READ_DATA_SPI(ADD_CTRL_REG2_R),READ_DATA_SPI(ADD_CTRL_REG3_R),READ_DATA_SPI(ADD_CTRL_REG4_R),READ_DATA_SPI(ADD_CTRL_REG5_R));
// 02 40 00 00 40
	
	while(1)
  {
	
		STATUS = READ_DATA_SPI(ADD_STATUS_REG_R);
 
		flag = STATUS & ((uint8_t)0x08);
		if (flag == ((uint8_t)0x08))
		{
			while(1)
			{
				STATUS = READ_DATA_SPI(ADD_STATUS_REG_R);
			  flag = STATUS & ((uint8_t)0x80); 
				if(flag == ((uint8_t)0x80))
				{
			    break;
				}
			}
			LIS3MDL_read(Data);
			printf("%x=%f=%f=%f\n",READ_DATA_SPI(ADD_CTRL_REG2_R),Data[0],Data[1],Data[2]);			
		}
    
	}
 
}
void LIS3MDL_read(float *Data)
{
	unsigned char buffer[6] = {0};
 
	unsigned char f; 
	unsigned int Sensitivity = 0; 
 
	int i,j = 0;
	int16_t cen = 0,ge,shi,bai,qian,wan; 
	
	buffer[0] = READ_DATA_SPI(ADD_OUT_X_H);
	buffer[1] = READ_DATA_SPI(ADD_OUT_X_L);
	buffer[2] = READ_DATA_SPI(ADD_OUT_Y_H);
	buffer[3] = READ_DATA_SPI(ADD_OUT_Y_L);
	buffer[4] = READ_DATA_SPI(ADD_OUT_Z_H);
	buffer[5] = READ_DATA_SPI(ADD_OUT_Z_L);
	
	f = READ_DATA_SPI(ADD_CTRL_REG2_R);
	
	switch(f)
	{
		case CTRL_REG2_4:
			Sensitivity = 6842;
		  break;
		case CTRL_REG2_8:
			Sensitivity = 3421;
		  break;
		case CTRL_REG2_12:
			Sensitivity = 2281;
		  break;
		case CTRL_REG2_16:
			Sensitivity = 1711;
		  break;
	}
	
	for(i = 0;i < 5;i = i+2)
	{
		cen = (int16_t)((((uint16_t)buffer[i]) << 8) + buffer[i+1]);
		wan = cen / 10000;
		qian = (cen - wan*10000) / 1000;
		bai = (cen - wan*10000 - qian*1000) / 100;
		shi = (cen - wan*10000 - qian*1000 - bai*100) / 10;
		ge = cen - wan*10000 - qian*1000 - bai*100 - shi*10;
		Data[j] = wan*10000 + qian*1000 + bai*100 + shi*10 + ge;
		Data[j] = Data[j] / Sensitivity;
		j++;
	}
	
}

@Eleon BORLINI (ST Employee)

@Miroslav BATEK (ST Employee)

1 REPLY 1
Eleon BORLINI
ST Employee

Hi Penghao @PFeng.1​ ,

>> 1. In the main function, firstly, I check the data from WHO_AM_I register. The output data is not 0x3D(default) but 0xFF. I don't know the reason. Does that affect anything?

No, it's not normal: 0xFF is a typical signal that something in the SPI communication is wrong... are you correctly initializing the peripheral (SPI Mode 3, 16bits)? Is the device directly connected with the STM32F4? And which Vdd are you using?

>> 2. Then, I write data CTRL_REG2_SOFT_RST(0x04) to CTRL_REG2 to reset the register. The output data from CTRL_REG2 to CTRL_REG5 are the same as the default data. But wonder why the output data from CTRL_REG1 is 0x18 (default data is 0x10). Does that affect anything?

The "soft reset" bit reinitializes all the volatile registers to the default configuration. Can you read back the register value you just write inside the registers?

I also suggest you to check initialization C code on Github and compare it with your configuration --> lis3mdl_read_data_polling.c

>> 3. After 2, I initialize the register as the data and order listed above. The data output by 4-wire SPI is the same as what I write.

See above.

>> 4. Finally, I use the STATUS_REG register to help the data collecting (as the DoclD027014 AN4602 Application note). However, the detecting magnetic data result is totally wrong! It output data "0" of X,Y and Z continuously, which is absolutely wrong. I don't know what happened cause I wrote the accurate configuration data to the register.

As specified above, there is probably something in the SPI communication that is failing, resulting in 00h fixed output.

Could you please share the digital scope patterns?

-Eleon