LIS3DH是一个三轴加速度传感器,可用于检测X、Y、Z轴上的加速度,以及设置阈值,在加速度超出阈值时触发中断。
支持SPI和IIC读写。
测试
下面主要是IIC方式读写:ui
1、寄存器读写流程
首先硬件链接会决定该模块的IIC地址
若是SAO脚接地,IIC地址为0X30(不包含最低位).
若是接V3.3,则IIC地址为0X32(不包含最低位).
spa
这个器件地址很重要,由于读写寄存器都是要先写一下对应的器件地址,而后再写命令的code
注意先发送的器件地址只是前7位,最后一位决定的是读写位,0是写寄存器,1为读寄存器,因此写寄存器时是写“LIS_ADDR|0x00”,读的时候则是“LIS_ADDR|0x01”blog
a、主机向从机写一个字节,下表是经过IIC向LIS3DH寄存器写一个字节的流程。简单来讲就是先写1个字节的写命令+IIC地址,再写一个字节的你要写的寄存器地址,最后写一个字节你要写入寄存器的内容
事件
示例:it
//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读寄存器一个字节
流程:先写1个字节的写命令+IIC地址,再写你要读的寄存器。而后写1个字节的读命令+IIC地址,最后读一个字节的数据
io
示例:class
//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连续写寄存器:stream
示例:
//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、IIC方式连续读寄存器。注意MAK和NMAK。
示例:
//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、设置阈值震动触发中断应用
首先,经过读取一个叫WHO_AM_I的寄存器,能够用来肯定芯片可用,由于这个寄存器读取的值是恒定的0x33。
设置阈值触发中断示例:
该实例设置了中断锁存。即直到从新读取INT1_SRC寄存器前,中断都不会被清除,引脚会被一直强拉到从新读取INT1_SRC为止。
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);//清除中断位
另外,还能够设置中断触发指定时间,随后引脚会还原。主要经过设置INT1_DURATION (33h)寄存器
这个ODR能够经过GTRL_REG1设置。
最后中断持续时间就是INT1_DURATION/ODR
3、FIFO模式读取X、Y、Z轴方向加速度值
出于高速读写的需求,可能须要使用FIFO方式来进行加速度的读取
LIS3DH的FIFO模式有4种:
一、Bypass mode
中间模式,只有切换模式的时候用获得
二、FIFO mode
数据填充满缓冲区后,中止继续填充
三、Stream mode
数据持续输出,填充满缓冲区后会覆盖旧的数据,数据依次向前推一字节
四、Stream-to-FIFO mode
FIFObuffer开始处于stream模式,等到中断脚选择触发时,切换到FIFO模式。FIFO_CTRL_REG (2Eh)的TR位能够决定是INT1脚仍是INT2脚来进行控制
示例:读取XYZ轴方向的加速度,用Stream mode。
watermark是指配置FSS [4:0]来检查读取的时候数据总量是否超出指定的范围。由于FIFO的缓冲区最多为32级,好比能够设置为20,则读取的时候,若是当时数据超出20个,则FIFO_SRC_REG (2Fh) (WTM)位会被置1,不然为0。
同时FIFO_SRC_REG (2Fh) 的 OVRN_FIFO会被置1,若是32级缓冲区所有满了。
//测试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个方向的数据 } }
数据会不断刷新,因此要定时读取,读取间隔能够经过ODR来控制调整。