lis3dh调试心得,读取正确的加速度值
最近在调试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调试心得,读取正确的加速度值相关推荐
- LIS3DH 加速度值 读取处理
折腾加速度芯片的过程中的一些记录, 相关数据和依据来源于以下两个官方文档: AD输出位数: 加速度的值经过AD转换后以数字形式输出,这里首先要搞清楚,AD转换后的数据是多少位的,官方英文版的手册给出的 ...
- 使用ESP32驱动QMA7981读取三轴加速度(带例程)
使用ESP32驱动QMA7981读取三轴加速度(带例程) 1.简介 ESP32是国产乐鑫公司生产的32位单片机,双核240MHz,带有蓝牙和wifi功能,本例中使用的是ESP32-S模组.QMA798 ...
- SC7A20获取三轴加速度值
SC7A20获取三轴加速度值(I2C) 1. I2C.h #ifndef __I2C_H #define __I2C_H#include "config.h"sbit I2C_SC ...
- 浅谈四轴PID调试心得
以下内容转自阿莫论坛,写得很详细,是调试大四轴的.小四轴调试也可参照着调. PID调试心得 本人不是自动化出身,也没有受过专业训练,都是自己摸索,在这里浅述一下自己的PID参数整定心得.所言之物皆由实 ...
- Ti ub954/953 Sensor调试心得
Ti ub954/953 Sensor调试心得 前言 TI以及美信的串行器以及接串器是目前车载领域用的比较多的厂家,目前最近一直再用TI的954以及953进行双目sensor的调试,下面就简单记录下调 ...
- 记spi nor flash的调试心得
flash 调试心得 前言 调试目的 调试步骤 检查 驱动 flash操作 改写 复位 访问模式 tips 内核下相关 文件系统 nor和nand的区别 前言 在工作中或者在开发板上或多或少都会遇到n ...
- ST公司 Lis2dh12 三轴加速度传感器,计算加速度值转成角度值
目录 概述 项目上使用了一款Lis2dh12三轴加速度传感器.开发前要准备的工作. 1.原理图: 1.1.创建lis2dh12.c文件 1.2.在此重点说明,如果想调传感器的中断灵敏度,注意:关注1. ...
- 试图运行项目时出错,无法启动调试。没有正确安装调试器,请运行安装程序安装或恢复调试器。...
用Visual Studio.net 2003调试项目时,出现错误对话框,显示如下: 试图运行项目时出错,无法启动调试.没有正确安装调试器,请运行安装程序安装或恢复调试 ...
- AT91RM9200+pcf8563在linux2.6.20下的调试心得
这两天调试了AT91RM9200+pcf8563在linux2.6.20下的驱动,记录一下我的调试过程以及调试心得,呵呵 在linux2.6.20/drivers/rtc目录下面已经有了pc ...
最新文章
- wpf里的menu怎么用_股市里的两市成交量是什么,它反映了什么,我是怎么用它来定投的...
- mysql去掉两个最高分_如何计算去掉一个最高分和一个最低分后的平均分?
- Windows Mobile 6.5.3 Developer Tool Kit
- 『物理社工』五一回家的“小插曲”
- 检测和测试停滞的流– RxJava常见问题解答
- 《MySQL排错指南》——1.9 许可问题
- 调试,是一件有挑战的事情
- 是vans_Vans 的旧海报上原来有这么多学问…
- System.gc()与Object.finalize()的区别
- 微信小程序如何快速生成wxml,wxss,json,js目录文件
- 帮Python找“对象”
- 基于差分整合移动平均自回归模型(ARIMA)的时序数据滚动预测建模与网格调参优化实战
- Length of Last Word
- oracle 安装包_【Oracle监控】-Spotlight On Oracle安装和使用
- AWS——API Gateway
- angular.js 增删改查练习2
- OneBox Technical Support
- 微信小程序背景图真机显示不了
- 学习正则表达式 - 18位身份证号
- 给ACCESS2003加密码和去掉密码
热门文章
- Vector的线程安全问题
- Java基础(9)——final、权限、内部类、引用类型
- 基于vue开发的,车牌输入专用键盘, vue车牌输入键盘,vue车牌输入 vue-license-keyboard
- html文本的背景,HTML---CSS字体,文本,背景和边框属性
- 将dtb反编译成dts
- 安川关节配置 EtherNet/IP 万可WAGO 台达ES2
- html中国家选择,jquery国家选择插件flagstrap
- 【CodeForces - 603E】Pastoral Oddities
- 【渝粤题库】陕西师范大学200501 英国文学
- 计算机毕业设计JAVA售后管理系统mybatis+源码+调试部署+系统+数据库+lw