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驱动及相关的更多相关文章

  1. Android开发环境——连接驱动ADB相关内容汇总

     Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT相关 ...

  2. linux查看硬件信息及驱动设备相关整理

    查看声卡设备:cat /proc/asound/cards 查看USB设备:cat /proc/bus/usb/devices 常用命令整理如下:用硬件检测程序kuduz探测新硬件:service k ...

  3. ubuntu 16.04(Windows 10双系统+grub引导)无法进入tt1~tt6(NVIDIA驱动安装相关-黑屏,login loop,分辨率)

    目录 前言回顾 最终解决: 0.关闭x服务 1.禁用nouveau 2.加入 3.更新 4.查找匹配驱动 5.选择推荐版本 6.等待安装后重启,nvidia-smi查看是否安装成功,或者lsmod | ...

  4. Linux驱动开发相关

    一般用printk 查看/etc/sysconf文件,看看内核调试信息放到了哪里 打印的消息一般放在/var/log/messages文件里面. 如果你是在X Windows下的XTerm中insmo ...

  5. 转:JDBC驱动配置相关

    1.做JDBC请求 ,首先要了解这个JDBC对象是什么,现在以SQLServer为例来说明 首先下载对应的数据库驱动(百度“jdbc sqlserver驱动”,然后下载). 注意 :下载完成后,直接把 ...

  6. 摄像头ov2685中关于sensor id 设置的相关的寄存器地址

    OV2685 : CHIP_ID address : 0x300A    default : 0x26 address : 0x300B    default : 0x85 address : 0x3 ...

  7. MTK驱动移植相关路径

    转自:http://blog.csdn.net/yicao821/article/details/52314578 一.Flash兼容 bootable/bootloader/preloader/to ...

  8. 摄像头ov2685中关于sensor id 设置的相关的寄存器地址【转】

    本文转载自:http://blog.csdn.net/morixinguan/article/details/51220992 OV2685 : CHIP_ID address : 0x300A   ...

  9. 各种sql驱动的相关配置

    一.SqlServer数据库 1.sqlServer{2005,2008}软件 dataDriverName=com.microsoft.sqlserver.jdbc.SQLServerDriver ...

随机推荐

  1. MUI 图标筛选切换(父页面传值子页面)

      1 父页面: index.html <li class="tab_layout"> <a href="javascript:;" clas ...

  2. 【Java nio】Channel

    package com.slp.nio; import org.junit.Test; import java.io.*; import java.nio.ByteBuffer; import jav ...

  3. call和apply方法

    /* * @ call和apply方法 * @ 当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作. * @ (有方法的)对象.call(" ...

  4. EUI组件之EditableText

    一.EditableText常规使用 EditableText是一个可输入文本,例如登陆时输入用户名.密码等. 拖动EditableText到exml即可 实际效果 其他: 1.输入密码框 设置inp ...

  5. c# Use NAudio Library to Convert MP3 audio into WAV audio(将Mp3格式转换成Wav格式)

    Have you been in need of converting mp3 audios to wav audios?  If so, the skill in this article prov ...

  6. 阿里云搭建SVN服务器

    1:安装svn apt-get install subversion 2. 开启svn服务器 svnserve -d 检查是否开启:ps aux | grep svnserve 若出现如下内容: wk ...

  7. Linux Git服务器安装

    ① 安装 Git ② 服务器端创建 git 用户,用来管理 Git 服务,并为 git 用户设置密码 ③ 服务器端创建 Git 仓库 ④ 客户端 clone 远程仓库 ⑤ 客户端创建 SSH 公钥和私 ...

  8. pta 天梯地图 (Dijkstra)

    本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线:一条是最短距离的路线.题目保证对任意的查询请求,地图上都至少存在一条可达路线. 输 ...

  9. es navi map+++++++nginx logs-parser

    http://www.cnblogs.com/ahaii/p/7410421.html [2017-12-17T00:01:03+08:00] ["GET /user/comm/login? ...

  10. html/css实现文字自动换行,超出部分出现(...)

    PS:这是我在别人博客copy下来的 做前端的我们都会发现这样一个问题,当你控制文字出现多行时,而这多行是有限制的(比如超出部分隐藏不显示),而这多行文字如果全部是数字或者字母抑或是数字和字母的组合时 ...