G-Sensor 8452驱动及相关
8452是一款G-Sensor芯片,采用I2C跟主芯片通讯,采用中断方式跟操作系统协作。通过内部检测XYZ三个方向的加速度,实现各种应用。
(1)原理框图如下:
现在来实现在WINCE中的I2C驱动,读写的时序波形图分别如下:
读:
写:
基础写函数实现如下:
static P_XLLP_OST_T ost_reg = 0;
static XLLP_I2C_T *i2c_reg = NULL;
static XLLP_CLKMGR_T *clk_reg = NULL; //在初始化中要映射
static int OS_I2CMasterWriteData(XLLP_UINT8_T slaveAddr, const XLLP_UINT8_T * bytesBuf, int bytesCount)
{
volatile int status;
XLLP_BOOL_T bSENDSTOP = XLLP_TRUE; //写完之后发停止位
status = XllpCustomI2CWrite((P_XLLP_I2C_T)(i2c_reg), (P_XLLP_OST_T)(ost_reg), slaveAddr, bytesBuf, bytesCount, bSENDSTOP,25);
return status;
}
static int MMA8452_WriteSensorReg( const XLLP_UINT8_T subAddress, XLLP_UINT8_T *bufP )
{
XLLP_UINT8_T buffer[2];
int status;
int lock;
buffer[0] = subAddress;
buffer[1] = *bufP;
gSensorSlaveAddr = 0x1c; //I2C地址
lock = __i2c_acquire_lock();
status = OS_I2CMasterWriteData( gSensorSlaveAddr, buffer, 2);
if (XLLP_STATUS_SUCCESS != status) {
RETAILMSG(1, (TEXT("Failed to write MMA8452_WriteSensorReg./r/n")));
}
__i2c_release_lock(lock);
return status;
}
基础读函数实现如下:
static int OS_I2CMasterWriteData_Read(XLLP_UINT8_T slaveAddr, const XLLP_UINT8_T * bytesBuf, int bytesCount)
{
volatile int status;
XLLP_BOOL_T bSENDSTOP = XLLP_FALSE; //写完后不发停止位
status = XllpCustomI2CWrite((P_XLLP_I2C_T)(i2c_reg), (P_XLLP_OST_T)(ost_reg), slaveAddr, bytesBuf, bytesCount, bSENDSTOP,25);
return status;
}
static int OS_I2CMasterReadData(XLLP_UINT8_T slaveAddr, XLLP_UINT8_T * bytesBuf, int bufLen)
{
volatile int status;
XLLP_BOOL_T bSENDSTOP = XLLP_TRUE; //读完后发停止位
status = XllpCustomI2CRead((P_XLLP_I2C_T)(i2c_reg), (P_XLLP_OST_T)(ost_reg), slaveAddr, bytesBuf, bufLen, bSENDSTOP,25);
return status;
}
static int MMA8452_ReadSensorReg( const XLLP_UINT8_T subAddress, XLLP_UINT8_T *bufP )
{
XLLP_UINT8_T buffer[1];
int status;
int lock;
buffer[0] = subAddress;
*bufP = 0x00;
gSensorSlaveAddr = 0x1c;
lock = __i2c_acquire_lock();
status = OS_I2CMasterWriteData_For_Read( gSensorSlaveAddr, buffer, 1); //写要读的子地址,注意没有停止位
if (XLLP_STATUS_SUCCESS == status)
{
status = OS_I2CMasterReadData( gSensorSlaveAddr, buffer, 1); //重写器件地址并读
*bufP = buffer[0]; //回传数据
}
else
{
RETAILMSG(1, (TEXT("Failed to MMA8452_ReadSensorReg./r/n")));
}
if (XLLP_STATUS_SUCCESS != status) {
RETAILMSG(1, (TEXT("Failed to MMA8452_ReadSensorReg./r/n")));
}
__i2c_release_lock(lock);
return status;
}
(2)唤醒功能的解析
在实际使用中,会用到g-sensor唤醒系统。一般有方向唤醒和点击唤醒两种。两者都是利用XYZ方向轴上的加速度变化,来中断操作系统。在配置睡眠唤醒的时候,一般有若干参数寄存器需要设置合适值。其中,双击唤醒的图示如下(从图中可以看出是默认低电平有效时是高电平):
对于8452,MMA8452_PULSE_THSX、MMA8452_PULSE_THSY、MMA8452_PULSE_THSZ这三个寄存器是用来设置加速度门限,值越大,需要敲击的力度也越大,对唤醒反应越迟钝。MMA8452_PULSE_TMLT是对第一次敲击的响应时间;MMA8452_PULSE_LTCY是第一次敲击后滤波去噪的延迟时间,该参数太小,会造成有可能把第一次敲击的杂波当作第二次敲击,该参数太大,会造成相隔很短的第二次敲击不会被识别;MMA8452_PULSE_WIND则是第二次敲击的识别时间区间,不在这个时间区间内的敲击不会被识别,以免造成误操作。
(3)关于layout的说明
使用图示如下:
参照上图的layout位置图,可以设置具体使用时的方向参数,最终只有一个值是正确的。注意:始终以正常使用手机的方位来看图,0-7的参数由于不同平台的软件不同,也可能意味着是从1-8。
举一个实例,一个四方向旋转的平板整机,当前方向值是1,平放时Z轴为-9.XX,说明Z轴反了,那么决定正确值的范围只能在(4、5、6、7)之间;以屏幕旋转的正确视图为准(X Y轴的指向,跟手机一样类似竖屏。但不以这个为准),发现右旋X是9.XX左旋X是-9.XX,是正确的;但是Y轴的视图上下反了,且从Y的读值看出来也是反的。综合以上,X轴不变Y轴反一下的图示只有5符合要求。从上上图的座标变换表格也可以看出:1对应的是(-y,x,z),把Y轴Z轴都倒的就是(y,x,-z),对应的方向值就是5。
(4)gsensor返回值的说明及gsensor校准
值域范围有正负数之分,正负是方向,以跟重力加速度对比来确定下来;值则以是否动态来说明。静止误差范围在300mg内算正常,也就是说<9.8-0.3,9.8+0.3>,超出该范围内说明GSENSOR的内部出厂校准参数出了偏差,可能原因是温度、运输、贴片所导致,该错误是不可逆的。
出现以上值超限的话,则需要对GSENSOR的工作过程进行校准,这个过程仅仅是对后期上报的数据进行修正,不可能再去纠正GSENSOR的内部属性。一般的过程是,平台放在一个平面上,分别得到GSENSOR的三个方向的校准offset,将其存入NVRAM中,以后再上报数据时读GSENSOR的读出值跟offset进行运算后再上报。由于GSENSOR的内部偏差是固定的,所以该补偿可用于任何工作状态的GSENSOR应用,此过程可采用若干次采样的平均值上报以减少误差。
需要注意的是,该校准仅仅是对出现偏差的现象进行校准,要么偏大要么偏小;如果某个时候GSENSOR读出的值的上限和下限均超出范围,应该考虑是否是其他原因(电压纹波,高采样率)导致的,此时使用offset偏差是解决不了问题的。
(5)Z轴补丁
8452的某些批次芯片本身存在质量问题。Z轴受敲击一旦出现超出范围问题之后达到20或者-20(超出-2g/2g),除非受其他敲击可能恢复的话,绝大部分时候是不会自动恢复的,这是芯片自身的问题,内部物理结构发生变化了。所以,可以采用在SENSOR HAL补丁方式解决这个问题,方法是Z轴出问题之后用XY模拟出Z轴的值,以让上层软件可以使用。以下的PATCH目前是可以保证平放时是9.8。同时芯片厂工程师说明该补丁的缺陷有两个:一是无法判断出手机是正放还是反放,提供的值只能是9.8没有-9.8;二是在手机动态时,模拟出的Z值是有偏差的。
补丁CODE如下:
#define ZCORRECTACTIVE 1 /* switch on /off the z stuck correction code */
#define ONEGCOUNTS 1024 /* 1024 1g counts for MMA8452 */
#define ZLOCKTHRESHOLD 2*ONEGCOUNTS*0.9 /* 10% below 2g stuck counts */
#define ZNORMALDIRECTION 1 /* define the sign of Z axis for normal screen face up operation, supposing the Z sign is positive here */
#define ZTIMEOUTCOUNTS 5 /* Z lock timeout counts, suppose sampling interval is 25Hz,40ms, 5 x 40ms=200ms for timeout delay*/
int zneg_out_counts = 0;
int zpos_out_counts = 0;
在SENSOR HAL的POLL函数内添加
if(sensors_data.data[i].sensor==0) //只针对gsensor处理
{
LOGD("%s:get sensor value,type: %d, value0 %d, value1 %d,value2 %d,updata %d!zhangcheng\r\n", __func__,
sensors_data.data[i].sensor, sensors_data.data[i].values[0], sensors_data.data[i].values[1],
sensors_data.data[i].values[2],sensors_data.data[i].update); //打印出当前读出的gsensor的原始值
xacc = sensors_data.data[i].values[0]*ONEGCOUNTS/9806;
yacc = sensors_data.data[i].values[1]*ONEGCOUNTS/9806;
zacc = sensors_data.data[i].values[2]*ONEGCOUNTS/9806; //转换,将原始重力加速度转换成g系数
if ((ZCORRECTACTIVE == 1))
{
if(zacc >= ZLOCKTHRESHOLD) //正向超限
{
if(zneg_out_counts == 0)
{
zpos_out_counts++;
if (zpos_out_counts >= ZTIMEOUTCOUNTS)
{
zpos_out_counts = ZTIMEOUTCOUNTS;
zacc = ZNORMALDIRECTION *sqrt(abs(ONEGCOUNTS*ONEGCOUNTS-xacc*xacc-yacc*yacc)); //用XY轴模拟Z轴
sensors_data.data[i].values[2] = zacc*9806/ONEGCOUNTS; //反转换后传给上层应用
}
}
else if(zneg_out_counts > 0)
{
zneg_out_counts = 0;
}
}
else if(zacc<= (-1)*ZLOCKTHRESHOLD) //反向超限
{
if ((zpos_out_counts == 0))
{
zneg_out_counts++;
if (zneg_out_counts >= ZTIMEOUTCOUNTS)
{
zneg_out_counts = ZTIMEOUTCOUNTS;
zacc = ZNORMALDIRECTION * sqrt(abs(ONEGCOUNTS*ONEGCOUNTS-xacc*xacc-yacc*yacc)); //用XY轴模拟Z轴
sensors_data.data[i].values[2] = zacc*9806/ONEGCOUNTS; //反转换后传给上层应用
}
}
else if(zpos_out_counts > 0)
{
zpos_out_counts = 0;
}
}
else
{
zpos_out_counts = 0;
zneg_out_counts = 0;
}
}
}
(6)GSENSOR跟陀螺仪的差别
陀螺仪能够测量沿一个轴或几个轴运动的角速度,是补充加速计功能的理想技术。如果组合使用加速计和陀螺仪这两种传感器,系统设计人员可以跟踪并捕捉三维空间的完整运动,为最终用户提供现场感更强的用户使用体验、精确的导航系统以及其它功能。
(7)GSENSOR游戏反应迟钝的分析
很多重力游戏比如摩托车/飞行器/枪击等游戏,依赖于GSENSOR的即时响应来操作,如果GSENSOR的响应不够及时,那么这游戏基本上是很难玩,极大影响用户体验。出现该问题的原因有两种:(1)如果GSENSOR是轮询工作的,轮询的频率很重要;(2)GSENSOR的采样频率,影响到即时响应。
曾经碰到过这样一个现象:手机断电后开机重力游戏正常,但是假关机再开机后重力游戏就响应非常慢。从上面两个可能点入手,通过TRACE可以确定上层对底层轮询的IOCTL的频率是正常的,这个可以通过内核TRACE的时间看出来,那么问题就出现在GSENSOR本身。后来分析出确实是采样频率被从60HZ设定成1HZ了,难怪上层响应这么慢,这个最直接的体现就是GSENSOR上报的是一大串相同的数据,而正常的时候GSENSOR上报的数据是一定范围跳动的。
(转载)
G-Sensor 8452驱动及相关的更多相关文章
- Android开发环境——连接驱动ADB相关内容汇总
Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT相关 ...
- linux查看硬件信息及驱动设备相关整理
查看声卡设备:cat /proc/asound/cards 查看USB设备:cat /proc/bus/usb/devices 常用命令整理如下:用硬件检测程序kuduz探测新硬件:service k ...
- ubuntu 16.04(Windows 10双系统+grub引导)无法进入tt1~tt6(NVIDIA驱动安装相关-黑屏,login loop,分辨率)
目录 前言回顾 最终解决: 0.关闭x服务 1.禁用nouveau 2.加入 3.更新 4.查找匹配驱动 5.选择推荐版本 6.等待安装后重启,nvidia-smi查看是否安装成功,或者lsmod | ...
- Linux驱动开发相关
一般用printk 查看/etc/sysconf文件,看看内核调试信息放到了哪里 打印的消息一般放在/var/log/messages文件里面. 如果你是在X Windows下的XTerm中insmo ...
- 转:JDBC驱动配置相关
1.做JDBC请求 ,首先要了解这个JDBC对象是什么,现在以SQLServer为例来说明 首先下载对应的数据库驱动(百度“jdbc sqlserver驱动”,然后下载). 注意 :下载完成后,直接把 ...
- 摄像头ov2685中关于sensor id 设置的相关的寄存器地址
OV2685 : CHIP_ID address : 0x300A default : 0x26 address : 0x300B default : 0x85 address : 0x3 ...
- MTK驱动移植相关路径
转自:http://blog.csdn.net/yicao821/article/details/52314578 一.Flash兼容 bootable/bootloader/preloader/to ...
- 摄像头ov2685中关于sensor id 设置的相关的寄存器地址【转】
本文转载自:http://blog.csdn.net/morixinguan/article/details/51220992 OV2685 : CHIP_ID address : 0x300A ...
- 各种sql驱动的相关配置
一.SqlServer数据库 1.sqlServer{2005,2008}软件 dataDriverName=com.microsoft.sqlserver.jdbc.SQLServerDriver ...
随机推荐
- poj_2182 线段树/树状数组
题目大意 n个数排成一排(不知道大小,只是占了一个位置),从a[1]到a[n]进行遍历,对于每个a[i],给出从a[1]到a[i-1]中小于a[i]数的个数.要求出 a[1]到a[n]中这n个数的相对 ...
- UEditor整合代码高亮插件SyntaxHighlighter
1 下载UEditor : http://ueditor.baidu.com/website/download.html 下载SyntaxHighlighter :https://github.co ...
- 设计模式之工厂方法模式(Java实现)
“我先来”,“不,老公,我先!”.远远的就听到几个人,哦不,是工厂方法模式和抽象工厂模式俩小夫妻在争吵,尼妹,又不是吃东西,谁先来不都一样(吃货的世界~).“抽象工厂模式,赶紧的自我介绍,工厂方法模式 ...
- CVE-2017-1000117命令注入验证
首先,我们来看第一个问题,就是ssh的一种操作. ssh -oProxyCommand=gnome-calculator xxx 问题的本质在于ssh会把//后的host那么部分带-号的按照参数指令去 ...
- Egret3D初步学习笔记三 (角色使用)
一 Unity中编辑角色 仍然使用unity4.7.1_Egret3D_Dll.unitypackage. 里面含有一个角色. 二 查看人物的动画 选中lingtong 属性面板里有个Animator ...
- [SQL] 常用查询脚本
查询哪些存储过程使用了某个表 select b.name from syscomments a,sysobjects b where a.id=b.id and a.text LIKE '%ftblo ...
- rman备份的其它特性
1.7.3.1并发: 主要用于提高备份的速度,可以分为手动并发或自动并发 手动并发:通过分配多个通道并将文件指定到特定的通道 RMAN> run { 2> allocate channe ...
- 再谈js的作用域
再谈js的作用域 面试中遇到的题目: 题目一: var word = "hello world"; (function(){ alert(word); var word = ...
- jconsole远程连接超时问题解决方法
根据oracle网站上的文档,本地使用jconsole没有问题.但当我从windows连接到linux时(centos5.4)时,老是连接不上). 原因是Linux上JVM给jconsole的RMI配 ...
- postgresql----继承表INHERITS PARENT TABLE
使用INHERITS创建的新表会继承一个或多个父表,子表只会继承父表的表结构和NOT NULL,DEFAULT,CHECK三种约束,主键,外键和唯一键以及索引不会被继承,所以修改父表的结构(增删字段) ...