LIS3DH three-axis acceleration sensor use process and examples

 

LIS3DH is a three-axis acceleration sensor that can be used to detect the acceleration on the X, Y, and Z axes, and to set the threshold, and trigger an interrupt when the acceleration exceeds the threshold.
Support SPI and IIC to read and write.

The following is mainly IIC way to read and write:

 

1. Register read and write process


First, the hardware connection will determine the IIC address of the module.
If the SAO pin is grounded, the IIC address is 0X30 (not including the lowest bit).
If it is connected to V3.3, the IIC address is 0X32 (not including the lowest bit).

This device address is very important, because it is necessary to write the corresponding device address first, and then write the command

Note that the device address sent first is only the first 7 bits, the last bit determines the read and write bits, 0 is the register write, and 1 is the read register, so when writing the register, write "LIS_ADDR|0x00", and read "LIS_ADDR" |0x01"

a. The host writes a byte to the slave. The following table shows the flow of writing a byte to the LIS3DH register through IIC. Simply put, first write 1 byte of write command + IIC address, then write one byte of the register address you want to write, and finally write one byte of the contents of the register you want to write

Example:

//IIC写一个字节
//reg:寄存器地址
//data:数据
//返回值:0,正常
//其他,错误代码
uint8_t LIS_Write_Byte(uint8_t reg,uint8_t data)
{
  	IIC_Start(); 
	IIC_Send_Byte(LIS_ADDR|0x00);//发送器件地址+写命令
	if(IIC_Wait_Ack())	//等待应答
	{
		IIC_Stop();		 
		return 1;		
	}
	IIC_Send_Byte(reg|0x00);		//写寄存器地址  D7位为低用于单字节传输
	IIC_Wait_Ack();					//等待应答
	IIC_Send_Byte(data);			//发送数据
	if(IIC_Wait_Ack())				//等待ACK
	{
		IIC_Stop();
		return 1;
	}
	IIC_Stop();	
	AP_interface->ol_Sleep(5000);
	return 0;
}

 

b. LIS3DH reads one byte of the register.
Process: First write a 1-byte write command + IIC address, and then write the register you want to read. Then write 1 byte of read command + IIC address, and finally read one byte of data

Example:

//IIC读一个字节
//reg:寄存器地址
//返回值:读到的数据
uint8_t LIS_Read_Byte(uint8_t reg)
{
	uint8_t res=0x00;

  	IIC_Start();
	IIC_Send_Byte(LIS_ADDR|0x00);//发送器件地址+写命令	
	if(IIC_Wait_Ack())		//等待ACK
	{
		IIC_Stop();	 
		return 1;		 
	}
	IIC_Send_Byte(reg);	//写寄存器地址
	IIC_Wait_Ack();		//等待应答
	IIC_Start();
	IIC_Send_Byte(LIS_ADDR|0x01);	//发送器件地址+读命令	
	IIC_Wait_Ack();					//等待应答 
	res = IIC_Read_Byte(0);			//读取数据,发送nACK
	IIC_Stop();						//产生一个停止条件 
	return res;
}

c. IIC write registers continuously:


Example:

//IIC连续写
//addr:器件地址 
//reg:寄存器地址
//len:写入长度
//buf:数据区
//返回值:0,正常
//	其他,错误代码
uint8_t LIS_Write_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
{
	uint8_t i; 
  IIC_Start();
	IIC_Send_Byte(LIS_ADDR|0x00);//发送器件地址+写命令
	if(IIC_Wait_Ack())	//等待应答
	{
		IIC_Stop();		 
		return 1;		
	}
    IIC_Send_Byte(reg|0x80);	//写寄存器地址  D7位为高用于多字节传输
    IIC_Wait_Ack();		//等待应答
	for(i=0;i<len;i++)
	{
		IIC_Send_Byte(buf[i]);	//发送数据
		if(IIC_Wait_Ack())		//等待ACK
		{
			IIC_Stop();	 
			return 1;		 
		}		
	}    
    IIC_Stop();
	return 0;	
}

d. Continuously read registers in IIC mode. Pay attention to MAK and NMAK.

Example:

//IIC连续读
//addr:器件地址
//reg:要读取的寄存器地址
//len:要读取的长度
//buf:读取到的数据存储区
//返回值:0,正常
//    其他,错误代码
uint8_t LIS_Read_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
{
 	IIC_Start();
	IIC_Send_Byte(LIS_ADDR|0x00);//发送器件地址+写命令
	if(IIC_Wait_Ack())	//等待应答
	{
		IIC_Stop();		 
		return 1;		
	}
    IIC_Send_Byte(reg|0x80);	//写寄存器地址  D7位为高用于多字节传输
    IIC_Wait_Ack();		//等待应答
    IIC_Start();
	IIC_Send_Byte(LIS_ADDR|0x01);//发送器件地址+读命令
    IIC_Wait_Ack();		//等待应答
	while(len)
	{
		if(len==1)*buf=IIC_Read_Byte(0);//读数据,发送nACK 
		else *buf=IIC_Read_Byte(1);		//读数据,发送ACK  
		len--;
		buf++; 
	}    
    IIC_Stop();	//产生一个停止条件 
	return 0;	
}

2. Set threshold vibration to trigger interrupt application

 

First, by reading a register called WHO_AM_I, it can be used to determine that the chip is available, because the value read by this register is a constant 0x33.

Example of setting threshold to trigger interrupt:

This example sets an interrupt latch. That is, the interrupt will not be cleared until the INT1_SRC register is read again, and the pin will be forced until the INT1_SRC is read again.

	LIS_Write_Byte(CTRL_REG1,0x3F);			//设置低功耗模式 xyz轴使能 采样频率25HZ
	LIS_Write_Byte(CTRL_REG2,0x09);			//高通滤波正常模式,数据从内部滤波器到输出寄存器 高通滤波器使能到中断1
	LIS_Write_Byte(CTRL_REG3,0x40);			//使能AOI中断1
	LIS_Write_Byte(CTRL_REG4,0x80);			//分辨率为+-2g  则单位为 4000/(2^8)=16mg       仅在LSB和MSB被读时才更新数据
	LIS_Write_Byte(CTRL_REG5,0x08);			//寄存器锁存中断,只有读INT1_SRC可以恢复
	LIS_Write_Byte(INT1_THS,0x10);			//设置阈值 16*16=256 mg
	LIS_Write_Byte(INT1_DURATION,0x00);		//中断持续时间设置,此处设为0,因为不读INT1_SRC中断就一直锁存
	LIS_Read_Byte(REFERENCE);				//读虚寄存器,强制将高通滤波器值加载到当前加速度值,开始比较

	//INT1_CFG使能中断  中断模式为 “OR”组合 只使能xyz轴高事件
	//LIS_Write_Byte(INT1_CFG,0x2A);
	//INT1_CFG使能中断  中断模式6-direction position  使能xyz轴高低事件
	LIS_Write_Byte(INT1_CFG,0xFF);
	LIS_Read_Byte(INT1_SRC);//清除中断位

In addition, you can also set the interrupt to trigger a specified time, and then the pin will be restored. Mainly by setting the INT1_DURATION (33h) register

This ODR can be set through GTRL_REG1.

The last interruption duration is INT1_DURATION/ODR

 

3. FIFO mode to read the acceleration value of X, Y, Z axis direction

 

For high-speed read and write requirements, it may be necessary to use FIFO to read acceleration

There are 4 FIFO modes of LIS3DH:

1、Bypass mode

Intermediate mode, only used when switching modes

2、FIFO mode

After the data fills the buffer, stop filling

3、Stream mode

The data is continuously output, the old data will be overwritten after the buffer is filled, and the data will be pushed forward one byte in turn

4、Stream-to-FIFO mode

FIFObuffer starts to be in stream mode, and when the interrupt pin selection triggers, switch to FIFO mode. The TR bit of FIFO_CTRL_REG (2Eh) can determine whether it is INT1 pin or INT2 pin for control

 

Example: To read the acceleration in the XYZ axis direction, use Stream mode.

Watermark refers to configuring FSS [4:0] to check whether the total amount of data exceeds the specified range when reading. Because the FIFO buffer has up to 32 levels, for example, it can be set to 20. When reading, if the data exceeds 20 at the time, the FIFO_SRC_REG (2Fh) (WTM) bit will be set to 1, otherwise it is 0.

At the same time, the OVRN_FIFO of FIFO_SRC_REG (2Fh) will be set to 1, if the 32-level buffers are all full.

	//测试FIFO
  IIC_WriteByte(LIS3DH_CTRL_REG1,0x80|0x0F);   //0010 0111	低功耗模式
	IIC_WriteByte(LIS3DH_CTRL_REG2,0x00);				//高通滤波关闭

	IIC_WriteByte(LIS3DH_CTRL_REG3,0x06);				//使能FIFO中断    0000 0110
	IIC_WriteByte(LIS3DH_CTRL_REG4,0x00);				//分辨率+-16g 		0011 0000

	IIC_WriteByte(LIS3DH_CTRL_REG5,0x48);					//FIFO使能	0100 1000
	IIC_WriteByte(LIS3DH_FIFO_CTRL,0x80|0x1D);		//0100 1111	配置FIFO模式和水印
	
	IIC_ReadByte(LIS3DH_INT1_SRC);	//清除中断位
	
	collect_LIS_Data();



void collect_LIS_Data(void)
{
		uint16_t  LIS_temp_data[3] = {0,0,0};
		uint8_t data_len,i;

		FIFO_data_len = IIC_ReadByte(LIS3DH_FIFO_SRC);

		FIFO_data_len &= 0x1F;
		for(i=0;i<FIFO_data_len;i++)
		{
			LIS3DH_ReadData(LIS_temp_data);    //读取3个方向的数据
		}
}

The data will be constantly refreshed, so it needs to be read regularly, and the reading interval can be controlled and adjusted by ODR.

 

Guess you like

Origin blog.csdn.net/zhangfls/article/details/109021073