最近在调试lis3dh加速度计,网上一搜能找到很多资料,但是描述正确的,感觉不是很多,所以这里我来总结一下,也是在网友博客的基础上将正确的地方集中整理一下。

1.   首先说驱动,驱动网上流传的基本上就是一份,.h.c文件随便一搜就能下载到lis3dh的驱动,由于我的是公司电脑,文件是加密,就不上传驱动了,大家可以自行搜索其他的资源下载,驱动下载下来后,用户需要完成的就是底层SPI(这里我用的是SPI读写方法,IIC的没用过)的读写寄存器的函数,我把自己写的粘贴出来,大家参考一下,用的而是HAL函数,这里有一点需要说明一下,就是SPI的速率配置,开始我配置的6M,读取WHO_AM_I寄存器以及任何寄存器读出来都是0x88,检查很多地方都找不出原因来,后来偶然的情况下改成了3M,竟然读取ID成功了0x33, LIS3DH datasheet上写的最大支持spi速率是10MHz.看来实际支持不了这么大的速率。

另外,对于下载的驱动还有一点说明,要注意里面函数返回值的定义,原有驱动是:

typedef enum {
    MEMS_SUCCESS                =        0x01,
    MEMS_ERROR                =        0x00,  
} status_t;

为了适应HAL库驱动,我给改成了:

typedef enum {
    MEMS_SUCCESS                =        0x00,
    MEMS_ERROR                =        0x01    
} status_t;

另外驱动里面的每个函数返回值的判断是 :

if( !LIS3DH_ReadReg(LIS3DH_FIFO_CTRL_REG, &value) )
        return MEMS_ERROR;

我改成了:

if( LIS3DH_ReadReg(LIS3DH_FIFO_CTRL_REG, &value) ) //为了适应返回0就是成功,返回非0是失败。
        return MEMS_ERROR;

/*注意:lis3dh波特率设置为3M可以读取正确,设置为8分频6M就不行*/
extern SPI_HandleTypeDef hspi2;
uint8_t LIS3DHInit(void)//SPI初始化
{ LIS3DH_CS_DISABLE; 取消片选  MX_SPI2_Init();return HAL_OK;
}
/*******************************************************************************
* Function Name                : LIS3DH_ReadReg
* Description                : Generic Reading function. It must be fullfilled with either
*                        : I2C or SPI reading functions
* Input                        : Register Address
* Output                : Data REad
* Return                : None
*******************************************************************************/
uint8_t LIS3DH_ReadReg(uint8_t Reg, uint8_t* Data) {uint8_t ret;uint8_t txdata;/* Start SPI transmission */LIS3DH_CS_ENABLE;/* Add read bit */Reg |= 0x80; /* Send address */HAL_SPI_Transmit(&hspi2,&Reg,1,100);/* Receive data */txdata = LIS302DL_LIS3DSH_DUMMY_BYTE;ret = HAL_SPI_TransmitReceive(&hspi2,&txdata,Data,1,100);       /* Stop SPI transmission */LIS3DH_CS_DISABLE;return ret;
}/*******************************************************************************
* Function Name                : LIS3DH_WriteReg
* Description                : Generic Writing function. It must be fullfilled with either
*                        : I2C or SPI writing function
* Input                        : Register Address, Data to be written
* Output                : None
* Return                : None
*******************************************************************************/
uint8_t LIS3DH_WriteReg(uint8_t WriteAddr, uint8_t Data)
{ uint8_t txdata[2],ret;txdata[0] = WriteAddr;txdata[1] = Data;/* Start SPI transmission */LIS3DH_CS_ENABLE;    /* Send address */ret = HAL_SPI_Transmit(&hspi2,txdata,2,100);/* Stop SPI transmission */LIS3DH_CS_DISABLE;return ret;
}
uint8_t LIS3DH_MultiRead(uint8_t start_addr,uint8_t len,uint8_t *data)//连续读读寄存器
{uint8_t ret,txdata;/* Add read bit and autoincrement bit */start_addr |= 0xC0;txdata = start_addr;/* Start SPI transmission */LIS3DH_CS_ENABLE;/* Send address */HAL_SPI_Transmit(&hspi2,&txdata,1,100);    /* Receive data */ret = HAL_SPI_TransmitReceive(&hspi2,data,data,len,1000);    /* Stop SPI transmission */LIS3DH_CS_DISABLE;return ret;
}

2. 初始化以及参数配置:

LIS3DHInit(); //1.中代码有这个函数的实现,主要是SPI初始化以及片选信号拉高
    Reset_LIS3DH(); //复位各个寄存器
    ret = gsensor_init(); //配置参数
    if(ret != RT_EOK){
        rt_kprintf("gsensor_init failed:%d.\r\n",ret);
        ret = -RT_ERROR;
        return ret;
    }
    gsensor_set_threshold(44,1);//中断阈值设置,这里主要设置产生中断的阈值,当加速度达到这个值后就会触发中断1.

下面给出各个函数的具体实现:

void Reset_LIS3DH(void)
{LIS3DH_WriteReg(LIS3DH_TEMP_CFG_REG,0x00); LIS3DH_WriteReg(LIS3DH_CTRL_REG1,0x07); //XYZ轴使能LIS3DH_WriteReg(LIS3DH_CTRL_REG2,0x00);LIS3DH_WriteReg(LIS3DH_CTRL_REG3,0x00);LIS3DH_WriteReg(LIS3DH_CTRL_REG4,0x00);LIS3DH_WriteReg(LIS3DH_CTRL_REG5,0x00);LIS3DH_WriteReg(LIS3DH_CTRL_REG6,0x00); LIS3DH_WriteReg(LIS3DH_REFERENCE_REG,0x00);LIS3DH_WriteReg(LIS3DH_FIFO_CTRL_REG,0x00);LIS3DH_WriteReg(LIS3DH_INT1_CFG,0x00);    LIS3DH_WriteReg(LIS3DH_INT1_THS,0x00);  LIS3DH_WriteReg(LIS3DH_INT1_DURATION,0x00);LIS3DH_WriteReg(LIS3DH_CLICK_CFG,0x00);  LIS3DH_WriteReg(LIS3DH_CLICK_THS,0x00); LIS3DH_WriteReg(LIS3DH_TIME_LIMIT,0x00);    LIS3DH_WriteReg(LIS3DH_TIME_LATENCY,0x00);  LIS3DH_WriteReg(LIS3DH_TIME_WINDOW,0x00);
}
int gsensor_init(void)
{uint8_t response = 0;response |= LIS3DH_SetODR(LIS3DH_ODR_100Hz);//设置数据输出频率response  = response << 1;response |= LIS3DH_SetMode(LIS3DH_NORMAL);//设置正常模式response  = response << 1;response |= LIS3DH_SetFullScale(LIS3DH_FULLSCALE_2);//设置量程为±2g, BIT6:DATA LSBresponse  = response << 1;response |= LIS3DH_SetAxis(LIS3DH_X_ENABLE | LIS3DH_Y_ENABLE | LIS3DH_Z_ENABLE);//使能三轴数据输出response  = response << 1;return response;
}
uint8_t gsensor_set_threshold(uint8_t threshold_value,uint8_t interrupt_ID)
{/*1 LSb = 16 mg @ FS = ±2 g1 LSb = 32 mg @ FS = ±4 g1 LSb = 62 mg @ FS = ±8 g1 LSb = 186 mg @ FS = ±16 g*/uint8_t response = 0;if(interrupt_ID == 1){LIS3DH_HPFAOI1Enable(MEMS_DISABLE);//High pass filter enabled for AOI function on interrupt 1,response|= LIS3DH_SetIntConfiguration(LIS3DH_INT1_ZHIE_ENABLE|LIS3DH_INT1_ZLIE_ENABLE|LIS3DH_INT1_YHIE_ENABLE|LIS3DH_INT1_YLIE_ENABLE|LIS3DH_INT1_XHIE_ENABLE|LIS3DH_INT1_XLIE_ENABLE);//INT1_CFG中enableresponse|= LIS3DH_SetInt6D4DConfiguration(LIS3DH_INT1_6D_ENABLE);response|= LIS3DH_SetIntMode(LIS3DH_INT_MODE_6D_POSITION);response|= LIS3DH_SetInt1Threshold(threshold_value);//16 * 16mg == 256mgresponse|= LIS3DH_SetInt1Pin(LIS3DH_I1_INT1_ON_PIN_INT1_ENABLE);}
}

3. 数据采集及计算,有两种方法:

1)通过公式计算得到:

首先调用LIS3DH_GetAccAxesRaw()获得xyz三个方向的寄存器值,然后通过公式计算。参考文章是这篇:

https://blog.csdn.net/sinat_23338865/article/details/51612872

首先在2中参数配置里,配置了fullsacle满量程是±2g, LIS3DH是16bit的data output,其中有一bit是符号位,所以还剩15bit的数据值,2^15 = 32768,2g = 2000mg,精度为2g/2^15= 2000mg/32768 =0.061mg,所以可以计算三个方向的值为:

X = X * 2000 /32768; 单位:mg

Y= Y * 2000 /32768; 单位:mg

Z = Z * 2000 /32768; 单位:mg

2)通过移位的方式获得:

void LIS3DH_Get_AccRaw(int16_t* pdata)
{uint8_t i = 0;uint8_t regValue[6] = {0, 0, 0, 0, 0, 0};int16_t symbol[3] = {0,0,0};for(i=0;i<6;i++){LIS3DH_ReadReg(LIS3DH_OUT_X_L+i, regValue+i);            }/* Format the data. */for(i=0;i<3;i++){if(regValue[2*i+1] & 0x80) symbol[i] = 0xF000;else symbol[i] = 0x0000;                }pdata[0] =symbol[0]  | ((( ( ( int16_t )regValue[1] ) << 8 ) + ( int16_t )regValue[0] ) >> 4);pdata[1] =symbol[1]  | ((( ( ( int16_t )regValue[3] ) << 8 ) + ( int16_t )regValue[2] ) >> 4);pdata[2] =symbol[2]  | ((( ( ( int16_t )regValue[5] ) << 8 ) + ( int16_t )regValue[4] ) >> 4);}
/*
*function:LIS3DH_Get_Sensitivity
*作用:读取满量程值:(00: +/- 2G; 01: +/- 4G; 10: +/- 8G; 11: +/- 16G)
*/
static void LIS3DH_Get_Sensitivity(uint8_t* sensitivity)
{uint8_t fullscale = 0;    LIS3DH_ReadReg(LIS3DH_CTRL_REG4,&fullscale);fullscale    = (fullscale & 0x30) >> 4; //0x30:0011 0000switch (fullscale){case 0:*sensitivity = 1;break;case 1:*sensitivity = 2;break;case 2:*sensitivity = 4;break;case 3:*sensitivity = 12;break;default : break;}
}void LIS3DH_Get_AccValue(AxesRaw_t *pdata)
{int16_t dataRaw[3];uint8_t sensitivity = 0;LIS3DH_Get_AccRaw(dataRaw);//获取3个方向的加速度值,LIS3DH_Get_Sensitivity(&sensitivity);pdata->AXIS_X  =  ( int32_t )( dataRaw[0] * sensitivity );pdata->AXIS_Y  =  ( int32_t )( dataRaw[1] * sensitivity );pdata->AXIS_Z  =  ( int32_t )( dataRaw[2] * sensitivity );
}

讲解一下移位方法的理解:最高位bit16是符号位,所以数据位是15bit=32768,那么1个值是多少个mg就是2000mg/32768=1/16mg,就是读取出来的寄存器值需要除以16,除以16就是右移4bit,(2^4 = 16). 相对第一种方法,这种方法算出来的更准确一些应该,因为没有小数的运算。

方法2参考文章:https://www.pianshen.com/article/2045248726/

后记,现在明白了这种移位的方法了,加速度值在寄存器中是以补码的形式存在的,上面LIS3DH_Get_AccRaw()是获取数据的补码的实现方法:

举例:regvalue[2] = 0xF0, regvalue[3] = 0xFB;

那么,if(regValue[2*i+1] & 0x80) symbol[i] = 0xF000; /*假如是负数,高4位保留(因为移位4位后,数据是0x0XXX的形式,补码需要数值前面符号位后面都是1,所以这里是0xF000),取补码,负数是以补码的形式输出*/

symbol[1]  | ( ( ( ((int16_t)regValue[3]) << 8 ) + (int16_t)regValue[2] ) >> 4);执行后,结果是0xF000 | 0xFBF = 0xFFBF;

0xFFBF的二进制是 1111 1111 1011 1111

减一:1111 1111 1011 1110, 取反:0000 0000 0100 0001

它的原码是 0000 0000 0100 0001,换成10进制是65,加上负号就是-65,

4,测试结果:

void cmd_lis3dh_test(char *args){rt_device_t lis3dh_dev;int8_t ret;AxesRaw_t acc,acc1;int32_t x,y,z;lis3dh_dev =  n_device_find("lis3dh");//基于RTTthrea的方式实现的代码if(lis3dh_dev == NULL){cmd_printf("lis3dh not find.\r\n");}ret = n_device_open(lis3dh_dev,RT_DEVICE_FLAG_RDWR);if(ret != HAL_OK)cmd_printf("lis3dh open failed!.\r\n");uint8_t lis_id;n_device_control(lis3dh_dev,N_LIS3DH_CTRL_ID,&lis_id);rt_kprintf("data= 0x%x\r\n",lis_id);LIS3DH_GetAccAxesRaw(&acc);//方法1)cmd_printf("LIS3DH read Acceleration adval, x:%d, y:%d, z:%d.\r\n",acc.AXIS_X,acc.AXIS_Y,acc.AXIS_Z);acc.AXIS_X = acc.AXIS_X * 2000 / 32768;acc.AXIS_Y = acc.AXIS_Y * 2000 / 32768;acc.AXIS_Z = acc.AXIS_Z * 2000 / 32768;cmd_printf("LIS3DH read Acceleration mg, x:%d, y:%d, z:%d.\r\n",acc.AXIS_X,acc.AXIS_Y,acc.AXIS_Z);LIS3DH_Get_AccValue(&acc1); //方法2)cmd_printf("LIS3DH read Acceleration g, x:%d, y:%d, z:%d.\r\n",acc1.AXIS_X,acc1.AXIS_Y,acc1.AXIS_Z);    cmd_printf("LIS3DH read INT1 Level: %d\r\n ",n_gpio_readpin(GPIOE,GPIO_PIN_13));//显示加速度计中断n_device_close(lis3dh_dev);
}

5,测试结果:

0x33是lis3dh的ID。

adval是寄存器中的值; mg是方法1算出来的结果,应该是0.992g(第一行),g是方法2算出来的结果1.017g,单位标的不对。

看lis3dh知道,如果加速度计在水平放置时,在z轴方向上是1个g,x或y方向垂直放时,在x或y方向是1个g,其他两个方向应该是0,但是实际中不可能完全是0,会有微小的值存在。

lis3dh调试心得,读取正确的加速度值相关推荐

  1. LIS3DH 加速度值 读取处理

    折腾加速度芯片的过程中的一些记录, 相关数据和依据来源于以下两个官方文档: AD输出位数: 加速度的值经过AD转换后以数字形式输出,这里首先要搞清楚,AD转换后的数据是多少位的,官方英文版的手册给出的 ...

  2. 使用ESP32驱动QMA7981读取三轴加速度(带例程)

    使用ESP32驱动QMA7981读取三轴加速度(带例程) 1.简介 ESP32是国产乐鑫公司生产的32位单片机,双核240MHz,带有蓝牙和wifi功能,本例中使用的是ESP32-S模组.QMA798 ...

  3. SC7A20获取三轴加速度值

    SC7A20获取三轴加速度值(I2C) 1. I2C.h #ifndef __I2C_H #define __I2C_H#include "config.h"sbit I2C_SC ...

  4. 浅谈四轴PID调试心得

    以下内容转自阿莫论坛,写得很详细,是调试大四轴的.小四轴调试也可参照着调. PID调试心得 本人不是自动化出身,也没有受过专业训练,都是自己摸索,在这里浅述一下自己的PID参数整定心得.所言之物皆由实 ...

  5. Ti ub954/953 Sensor调试心得

    Ti ub954/953 Sensor调试心得 前言 TI以及美信的串行器以及接串器是目前车载领域用的比较多的厂家,目前最近一直再用TI的954以及953进行双目sensor的调试,下面就简单记录下调 ...

  6. 记spi nor flash的调试心得

    flash 调试心得 前言 调试目的 调试步骤 检查 驱动 flash操作 改写 复位 访问模式 tips 内核下相关 文件系统 nor和nand的区别 前言 在工作中或者在开发板上或多或少都会遇到n ...

  7. ST公司 Lis2dh12 三轴加速度传感器,计算加速度值转成角度值

    目录 概述 项目上使用了一款Lis2dh12三轴加速度传感器.开发前要准备的工作. 1.原理图: 1.1.创建lis2dh12.c文件 1.2.在此重点说明,如果想调传感器的中断灵敏度,注意:关注1. ...

  8. 试图运行项目时出错,无法启动调试。没有正确安装调试器,请运行安装程序安装或恢复调试器。...

            用Visual Studio.net 2003调试项目时,出现错误对话框,显示如下:         试图运行项目时出错,无法启动调试.没有正确安装调试器,请运行安装程序安装或恢复调试 ...

  9. AT91RM9200+pcf8563在linux2.6.20下的调试心得

    这两天调试了AT91RM9200+pcf8563在linux2.6.20下的驱动,记录一下我的调试过程以及调试心得,呵呵      在linux2.6.20/drivers/rtc目录下面已经有了pc ...

最新文章

  1. wpf里的menu怎么用_股市里的两市成交量是什么,它反映了什么,我是怎么用它来定投的...
  2. mysql去掉两个最高分_如何计算去掉一个最高分和一个最低分后的平均分?
  3. Windows Mobile 6.5.3 Developer Tool Kit
  4. 『物理社工』五一回家的“小插曲”
  5. 检测和测试停滞的流– RxJava常见问题解答
  6. 《MySQL排错指南》——1.9 许可问题
  7. 调试,是一件有挑战的事情
  8. 是vans_Vans 的旧海报上原来有这么多学问…
  9. System.gc()与Object.finalize()的区别
  10. 微信小程序如何快速生成wxml,wxss,json,js目录文件
  11. 帮Python找“对象”
  12. 基于差分整合移动平均自回归模型(ARIMA)的时序数据滚动预测建模与网格调参优化实战
  13. Length of Last Word
  14. oracle 安装包_【Oracle监控】-Spotlight On Oracle安装和使用
  15. AWS——API Gateway
  16. angular.js 增删改查练习2
  17. OneBox Technical Support
  18. 微信小程序背景图真机显示不了
  19. 学习正则表达式 - 18位身份证号
  20. 给ACCESS2003加密码和去掉密码

热门文章

  1. Vector的线程安全问题
  2. Java基础(9)——final、权限、内部类、引用类型
  3. 基于vue开发的,车牌输入专用键盘, vue车牌输入键盘,vue车牌输入 vue-license-keyboard
  4. html文本的背景,HTML---CSS字体,文本,背景和边框属性
  5. 将dtb反编译成dts
  6. 安川关节配置 EtherNet/IP 万可WAGO 台达ES2
  7. html中国家选择,jquery国家选择插件flagstrap
  8. 【CodeForces - 603E】Pastoral Oddities
  9. 【渝粤题库】陕西师范大学200501 英国文学
  10. 计算机毕业设计JAVA售后管理系统mybatis+源码+调试部署+系统+数据库+lw