OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11392|回复: 4

LIS3DH 三轴加速度传感器使用流程及示例

[复制链接]

1

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2017-9-24
在线时间
16 小时
发表于 2020-10-12 13:57:06 | 显示全部楼层 |阅读模式
本帖最后由 殇乱之秋 于 2020-10-12 13:56 编辑

LIS3DH是一个三轴加速度传感器,可用于检测X、Y、Z轴上的加速度,以及设置阈值,在加速度超出阈值时触发中断。
支持SPI和IIC读写。
下面主要是IIC方式读写:
一、寄存器读写流程

首先硬件连接会决定该模块的IIC地址
如果SAO脚接地,IIC地址为0X30(不包含最低位).
如果接V3.3,则IIC地址为0X32(不包含最低位).
​
这个器件地址很重要,因为读写寄存器都是要先写一下对应的器件地址,然后再写命令的
注意先发送的器件地址只是前7位,最后一位决定的是读写位,0是写寄存器,1为读寄存器,所以写寄存器时是写“LIS_ADDR|0x00”,读的时候则是“LIS_ADDR|0x01”
a、主机向从机写一个字节,下表是通过IIC向LIS3DH寄存器写一个字节的流程。简单来说就是先写1个字节的写命令+IIC地址,再写一个字节的你要写的寄存器地址,最后写一个字节你要写入寄存器的内容
​
示例:
  1. //IIC写一个字节
  2. //reg:寄存器地址
  3. //data:数据
  4. //返回值:0,正常
  5. //其他,错误代码
  6. uint8_t LIS_Write_Byte(uint8_t reg,uint8_t data)
  7. {
  8.           IIC_Start();
  9.         IIC_Send_Byte(LIS_ADDR|0x00);//发送器件地址+写命令
  10.         if(IIC_Wait_Ack())        //等待应答
  11.         {
  12.                 IIC_Stop();                 
  13.                 return 1;               
  14.         }
  15.         IIC_Send_Byte(reg|0x00);                //写寄存器地址  D7位为低用于单字节传输
  16.         IIC_Wait_Ack();                                        //等待应答
  17.         IIC_Send_Byte(data);                        //发送数据
  18.         if(IIC_Wait_Ack())                                //等待ACK
  19.         {
  20.                 IIC_Stop();
  21.                 return 1;
  22.         }
  23.         IIC_Stop();       
  24.         AP_interface->ol_Sleep(5000);
  25.         return 0;
  26. }
复制代码

b、LIS3DH读寄存器一个字节
流程:先写1个字节的写命令+IIC地址,再写你要读的寄存器。然后写1个字节的读命令+IIC地址,最后读一个字节的数据
​
示例:
  1. //IIC读一个字节
  2. //reg:寄存器地址
  3. //返回值:读到的数据
  4. uint8_t LIS_Read_Byte(uint8_t reg)
  5. {
  6.         uint8_t res=0x00;

  7.           IIC_Start();
  8.         IIC_Send_Byte(LIS_ADDR|0x00);//发送器件地址+写命令       
  9.         if(IIC_Wait_Ack())                //等待ACK
  10.         {
  11.                 IIC_Stop();         
  12.                 return 1;                 
  13.         }
  14.         IIC_Send_Byte(reg);        //写寄存器地址
  15.         IIC_Wait_Ack();                //等待应答
  16.         IIC_Start();
  17.         IIC_Send_Byte(LIS_ADDR|0x01);        //发送器件地址+读命令       
  18.         IIC_Wait_Ack();                                        //等待应答
  19.         res = IIC_Read_Byte(0);                        //读取数据,发送nACK
  20.         IIC_Stop();                                                //产生一个停止条件
  21.         return res;
  22. }
复制代码

c、IIC连续写寄存器:
​
示例:
  1. //IIC连续写
  2. //addr:器件地址
  3. //reg:寄存器地址
  4. //len:写入长度
  5. //buf:数据区
  6. //返回值:0,正常
  7. //        其他,错误代码
  8. uint8_t LIS_Write_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
  9. {
  10.         uint8_t i;
  11.   IIC_Start();
  12.         IIC_Send_Byte(LIS_ADDR|0x00);//发送器件地址+写命令
  13.         if(IIC_Wait_Ack())        //等待应答
  14.         {
  15.                 IIC_Stop();                 
  16.                 return 1;               
  17.         }
  18.     IIC_Send_Byte(reg|0x80);        //写寄存器地址  D7位为高用于多字节传输
  19.     IIC_Wait_Ack();                //等待应答
  20.         for(i=0;i<len;i++)
  21.         {
  22.                 IIC_Send_Byte(buf[i]);        //发送数据
  23.                 if(IIC_Wait_Ack())                //等待ACK
  24.                 {
  25.                         IIC_Stop();         
  26.                         return 1;                 
  27.                 }               
  28.         }   
  29.     IIC_Stop();
  30.         return 0;       
  31. }
复制代码

d、IIC方式连续读寄存器。注意MAK和NMAK。
&#8203;
示例:
  1. //IIC连续读
  2. //addr:器件地址
  3. //reg:要读取的寄存器地址
  4. //len:要读取的长度
  5. //buf:读取到的数据存储区
  6. //返回值:0,正常
  7. //    其他,错误代码
  8. uint8_t LIS_Read_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
  9. {
  10.         IIC_Start();
  11.         IIC_Send_Byte(LIS_ADDR|0x00);//发送器件地址+写命令
  12.         if(IIC_Wait_Ack())        //等待应答
  13.         {
  14.                 IIC_Stop();                 
  15.                 return 1;               
  16.         }
  17.     IIC_Send_Byte(reg|0x80);        //写寄存器地址  D7位为高用于多字节传输
  18.     IIC_Wait_Ack();                //等待应答
  19.     IIC_Start();
  20.         IIC_Send_Byte(LIS_ADDR|0x01);//发送器件地址+读命令
  21.     IIC_Wait_Ack();                //等待应答
  22.         while(len)
  23.         {
  24.                 if(len==1)*buf=IIC_Read_Byte(0);//读数据,发送nACK
  25.                 else *buf=IIC_Read_Byte(1);                //读数据,发送ACK  
  26.                 len--;
  27.                 buf++;
  28.         }   
  29.     IIC_Stop();        //产生一个停止条件
  30.         return 0;       
  31. }
复制代码

二、设置阈值震动触发中断应用
首先,通过读取一个叫WHO_AM_I的寄存器,可以用来确定芯片可用,因为这个寄存器读取的值是恒定的0x33。
设置阈值触发中断示例:
该实例设置了中断锁存。即直到重新读取INT1_SRC寄存器前,中断都不会被清除,引脚会被一直强拉到重新读取INT1_SRC为止。
  1. LIS_Write_Byte(CTRL_REG1,0x3F);                        //设置低功耗模式 xyz轴使能 采样频率25HZ
  2.         LIS_Write_Byte(CTRL_REG2,0x09);                        //高通滤波正常模式,数据从内部滤波器到输出寄存器 高通滤波器使能到中断1
  3.         LIS_Write_Byte(CTRL_REG3,0x40);                        //使能AOI中断1
  4.         LIS_Write_Byte(CTRL_REG4,0x80);                        //分辨率为+-2g  则单位为 4000/(2^8)=16mg       仅在LSB和MSB被读时才更新数据
  5.         LIS_Write_Byte(CTRL_REG5,0x08);                        //寄存器锁存中断,只有读INT1_SRC可以恢复
  6.         LIS_Write_Byte(INT1_THS,0x10);                        //设置阈值 16*16=256 mg
  7.         LIS_Write_Byte(INT1_DURATION,0x00);                //中断持续时间设置,此处设为0,因为不读INT1_SRC中断就一直锁存
  8.         LIS_Read_Byte(REFERENCE);                                //读虚寄存器,强制将高通滤波器值加载到当前加速度值,开始比较

  9.         //INT1_CFG使能中断  中断模式为 “OR”组合 只使能xyz轴高事件
  10.         //LIS_Write_Byte(INT1_CFG,0x2A);
  11.         //INT1_CFG使能中断  中断模式6-direction position  使能xyz轴高低事件
  12.         LIS_Write_Byte(INT1_CFG,0xFF);
  13.         LIS_Read_Byte(INT1_SRC);//清除中断位
复制代码

另外,还可以设置中断触发指定时间,随后引脚会还原。主要通过设置INT1_DURATION (33h)寄存器
&#8203;
这个ODR可以通过GTRL_REG1设置。
&#8203;
最后中断持续时间就是INT1_DURATION/ODR

三、FIFO模式读取X、Y、Z轴方向加速度值
出于高速读写的需求,可能需要使用FIFO方式来进行加速度的读取
LIS3DH的FIFO模式有4种:
1、Bypass mode
中间模式,只有切换模式的时候用得到
2、FIFO mode
数据填充满缓冲区后,停止继续填充
3、Stream mode
数据持续输出,填充满缓冲区后会覆盖旧的数据,数据依次向前推一字节
4、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级缓冲区全部满了。
  1. //测试FIFO
  2.   IIC_WriteByte(LIS3DH_CTRL_REG1,0x80|0x0F);   //0010 0111        低功耗模式
  3.         IIC_WriteByte(LIS3DH_CTRL_REG2,0x00);                                //高通滤波关闭

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

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



  12. void collect_LIS_Data(void)
  13. {
  14.                 uint16_t  LIS_temp_data[3] = {0,0,0};
  15.                 uint8_t data_len,i;

  16.                 FIFO_data_len = IIC_ReadByte(LIS3DH_FIFO_SRC);

  17.                 FIFO_data_len &= 0x1F;
  18.                 for(i=0;i<FIFO_data_len;i++)
  19.                 {
  20.                         LIS3DH_ReadData(LIS_temp_data);    //读取3个方向的数据
  21.                 }
  22. }
复制代码

数据会不断刷新,所以要定时读取,读取间隔可以通过ODR来控制调整。


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2021-8-27
在线时间
27 小时
发表于 2021-10-8 10:25:38 | 显示全部楼层
写寄存器时是写“(LIS_ADDR<<1)|0x00”,读的时候则是“(LIS_ADDR<<1)|0x01”
回复 支持 1 反对 0

使用道具 举报

2

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
80
金钱
80
注册时间
2016-8-13
在线时间
14 小时
发表于 2020-10-12 18:28:16 | 显示全部楼层
最近也在使用这个IC,数据一直出不来,楼主,可以发整个工程文档到2663265296@qq.com,谢谢。
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2020-8-26
在线时间
1 小时
发表于 2021-5-20 14:33:52 | 显示全部楼层
楼主由整理SPI方式读取吗
回复 支持 反对

使用道具 举报

2

主题

474

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6084
金钱
6084
注册时间
2018-6-27
在线时间
524 小时
发表于 2022-10-27 11:05:30 | 显示全部楼层
学习学习,学习学习。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 22:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表