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. 索引原理 B tree

    数据库原理之-索引 背景介绍: 用数据库的时候经常有几个疑问: 1:为啥通过加索引就能提升数据的查询料率? 2:为啥加多了索引会导致增删改的效率变低? 3:为啥有的人能用好有的人用不好? 这些问题我们 ...

  2. @font-face 字体

    一.@font-face是CSS3中的一个模块,把自己定义的Web字体嵌入到你网页中 @font-face的语法规则 @font-face { font-family: <YourWebFont ...

  3. ios Quartz 各种绘制图形用法

    摘要: CoreGraphics的功能非常强大,可以绘制各种图形:今天学习一下怎么绘制简单的点线面,记录学习. 一.导入coreGraphics.framework 二.绘制图形 1.绘制矩形 // ...

  4. 【Android】Android背景选择器selector用法汇总

    一.创建xml文件,位置:drawable/xxx.xml,同目录下记得要放相关图片 <?xml version="1.0" encoding="utf-8&quo ...

  5. java的this表示当前类还是当前实例?

    转自:http://www.runoob.com/java/java-basic-syntax.html this 表示调用当前实例或者调用另一个构造函数

  6. Google浏览器提示用户要允许网站允许flash!

    开发的flash播放器,在谷歌浏览器上播放不了,需要提示用户手动开启允许网站运行flash: <script type="text/javascript"> if (w ...

  7. angularJS中的MVC思想?

    mvc 思想: 将应用程序的组成,划分为三个部分:model , controller 和 view ; - 控制器的作用是用来初始化模型用的: - 模型就是用于存储数据的: - 视图是展示数据的: ...

  8. [NGINX] - 配置文件优化 - NGINX.CONF

    Nginx 本文主要针对公司的Nginx负载均衡配置进行解释,配置文件在最下方.因为公司没有使用PHP,所以NGINX里面并没有太多facgi模块相关优化    NGINX.CONF user   语 ...

  9. 容斥原理解决某个区间[1,n]闭区间与m互质数数量问题

    首先贴出代码(闭区间[1,n]范围内和m互质的数) 代码: int solve(II n,II m){ vector<II>p; ;i*i<=m;i++){ ){ p.push_ba ...

  10. Oracle体系结构之Oracle10gR2体系结构-内存、进程

    oracle体系结构图1 oracle体系结构图2 用户进程(访问oracle的客户端的总称) 工具的使用:sqlplus.pl/sql developer 如何访问数据库: 本机直接通过sock方式 ...