WINCE陀螺仪驱动的实现总结

     这周4天的时间写了一个WINCE的陀螺仪驱动,今天调试完成,总结一下:
    由于是第一次真正的从头开始添加一个新的WINCE驱动。所以这几天大部分的工作还是在学习如何在wince中添加一个新的驱动。这个需要单独写一篇笔记来记录一下。
    上周调过i2c的矩阵键盘,这次的wince项目中挂在i2c总线上的就2个设备,矩阵键盘和陀螺仪,所以这周趁热打铁把陀螺仪驱动也写了一下,填了进去。
    开始感觉陀螺仪是很神秘的东东,于是找出来它的原理来学习了一下,但是也不是很明白,大体明白,应该就是2个围绕轴转动的环,但是对于驱动来说我们不用很清楚它的工作原理即可,因为陀螺仪跟处理器之前是通过陀螺仪的设备控制器来传输的,在我们处理器看来,我们看到的只是控制器,而不是陀螺仪设备本身,我们只要明白怎么使用控制器就可以了。
    首先将陀螺仪控制器的datasheet看了一遍,大体意思就是向控制器发送命令,然后读取控制器通过A/D转换出来的x,y,z轴的坐标,这个就是陀螺仪反馈出来的数据,其他的我们不用太关心就可以。
    发现了一点就是陀螺仪控制器没有中断引脚,细想也对,脱落仪的工作都是同步事件,没有异步事件。只有当处理器需要使用陀螺仪的时候我们才需要调用驱动,并且只是读取陀螺仪反馈的数据。所以驱动中最重要实现的函数就是read函数。
    不用中断这个驱动算是省了一大半的功夫,只要i2c时序没有问题就应该可以从控制器中读取出数据。于是还是采取老办法,在pmon下利用命令来测试时序。


    按照datasheet,从陀螺仪控制器获取数据的时序是:

 

    slave地址+写----》寄存器0地址----》命令0x1----》delay 7ms
    唤醒设备准备数据进行A/D转换
   
    slave地址+写----》寄存器0地址----》slave地址+读----》read 7 data

    一共7字节数据,第一字节是控制状态数据,后面6字节是x,y,z坐标,都是占2字节。

 

    我现在pmon下利用命令试,想了一下,上面的时序跟pmon里面基本一致,应该没什么问题。先m1 0 1,然后d1 0 7.读出了数据,数据虽然看不明白,但是动开发板,数据有变化,心中窃喜,感觉应该差不多。
    于是按照wince流设备的驱动框架写完驱动(这个过程是最费时间的过程,第一次写wince驱动,注册表什么的都不明白。。。),底层还是使用pmon里面的i2c数据传输时序。
    在获取数据的函数中加打印,编译内核调试,写了一个简单的测试程序,运行每隔1秒获取一次陀螺仪坐标,但是读取出来的数据都是0。。。。这是怎么回事。
    首先还是得考虑时序的问题。把控制器手册再仔细的看了一遍,特别是时序,然后对比了一下pmon的i2c时序,发现问题了。
    pmon下的i2c总体时序都是slave地址+寄存器地址+单个数据。
    而控制器手册上对这个控制器的读写时序,写是slave地址+寄存器地址+命令。而读取的时序却是slave地址+寄存器地址+7字节数据,读取第一个数据,第二个数据就会放到数据寄存器上,往后循环。
    pmon里面对于需要读取多字节的数据是一个大循环。如果读取7字节数据,就是上面的时序循环7次。
    这很明显的时序不正确,在这里要注意一点,总线只是提供通讯的线路。而总线协议呢,是总线的master和slave之间协商好的通讯方式。所以i2c总线的传输时序并不是固定的,只不过i2c给大家提供了一个通用协议让大家尽量遵从。如果你不想使用i2c总线的协议,自己弄一个协议也行,但是得保证设备必须也要遵循这个协议,不然你按照你的协议来,设备不响应还是白搭,不同设备之间协议可能有差别。具体的时序这个在slave控制器手册上肯定会详细写清楚。不能有一点偏差。这样slave设备就不会响应,也就得不到数据。
    于是我就按照datasheet上的时序将代码修改了一下,再运行就可以获取出陀螺仪的坐标了。
    然后我又把代码整理了一下,因为这是第一次从上到下做一个完整的驱动,所以代码不是很规范。
    我又想起来一个问题,就是为什么我在pmon下用命令测试时序,能够读出数据,但是我在内核中就只能读出0呢。
    我就仔细想了一遍pmon下的读写时序,写时序没什么问题,关键在于读取时序。
    7次大循环的slave+寄存器+数据,每一次读出数据都会发stop。而按照手册数据与数据之间是连续的,读完一次数据,下一个数据就会放到数据寄存器上,依次读出(手册是说数据指针会指向下一个,一样道理)。
    这样看来,读出0的原因是,寄存器地址写的是0,是控制状态寄存器,数据准备好后这个寄存器数据是0,每一次循环就相当于重新读取,所以始终是读的寄存器0的数据,也就是0,而第二个数据放到数据寄存器的时候已经发了stop命令了,这个原因是找到了。
    那为什么pmon中可以读取出数据呢,还是从最上层的d1的实现函数dump看。发现dump里面对于数据的个数,也是采取大循环。但是在调用最底层读取函数的时候传寄存器的地址是循环累加的,也就是说,第一次循环读出寄存器0数据,第二次循环读出是寄存器1数据,这样循环,读出7字节数据。由于数据在时序的第一阶段唤醒设备测量数据时就获取完成,后面的时序都是来读取这些数据,指导下一次发送命令0x1来唤醒的时候才更新数据。所以这种读取方法也是正确的,只不过效率比直接在一次读取中读出7个数据低

你可能感兴趣的:(WINCE陀螺仪驱动的实现总结)