版权声明:本文为博主原创文章,未经博主允许不得转载。
第四章MPU6000传感器驱动解析
这个函数。至于这个函数我们可以查看到初始化这个几个参数是这个,这里我们对他进行分析一下,busid就是说明是哪个总线协议,可以看到这个枚举型是有5个数的都是关于内部SPI,外部SPI,内部IIC,外部IIC,这里的外部内部的意思是板上的传感器和自己外加的传感器,这个要理解清楚哦。Device_type是设备类型,external就是定义是内部V2硬件的传感器还自己外接的传感器,旋转角度其实就是跟传感器的摆放位置相关,加速度范围是8G,即为+-4G。
然后就是这个函数了
这个其实就是解析了启动传感器的判断了,还记得
这些就是在这里解析了,这里说明一下前面是对照找这个参数,然后接个冒号就是找这个参数值,比如我们来对照mpu6000 –X –R 4 start这个就是首先解析到-X就是
然后找到-R 然后找到这个参数后是4就是rotation是4也就是yaw旋转180°,接着获取start参数
,这个介绍完了,我们来查找我们V2硬件的mpu6000的启动吧。我们找到rc.sensors中有
这里就是启动了,如果不知道怎么找,那就去仔细阅读RCS那一章节了,然后再仔细阅读rc.sensors了。这里可以看得出不会进入该函数了。
接着进入到函数
这里的参数是,这里我不妨贴出来这个函数实际运行的就是进入到start中这里就会对驱动去循环查询
然后运行
,这里我们不对这个做详细说明,有兴趣的可以去看看,这里我们知道V2的硬件板就是使用的内部板载传感器。然后我们对start_bus说明,这个函数是启动总线协议了。这些个参数是进入函数
这里就是对函数协议的控制了。这里我们先找到设备总线的选择,针对MPU6000我们选择的是
中去找发现是
,device_type参数是6000,external还是0。
注:,这里是一个构造函数,C++中的new其实就是类似于C语言中的初始化。
看到没这里就开始对SPI的配置进行说明了,这里SPI的进行选择了哦,这里的bus=1了哦注意。Device变成了cs=4哦,然后就是模式和速率了。
这里对SPI的选择模式和配置就完成了。然后回到mpu6000.cpp中的下一步就是
初始化协议了,这里用到了虚函数的概念哦,这里不懂也没关系,最好是了解一下这些概念,应为这个系统会有很多都用到了虚函数,这里告诉你这个虚函数的就是SPI的初始化了。这里我们要找的就是SPI.ccp了,你可以查看到SPI的初始化了。这里我们就与刚才协议的驱动对接上了,
刚才说到这里的_bus=1,返回的值_dev=1,_device=cs=4
追踪到这里就是这个函数了,至于为什么开始是SPI_SELECT到后面变成了STM32_spi1select到spi驱动篇去看看。这里选择的执行时
,好了我们在来看看硬件图,看到没现在都对应起来了吧,spi选择的是SPI1,cs选择的是PC2引脚
。
再回到mpu6000.cpp中接下来就该
这里就开始对mpu6000的相关设置和配置,这里我们不对它进行细说这里还是一个构造函数,只是对相关数据进行初始化。这里面有很多,就有对路径注册,滤波器初始化,参数的初始化等等。这里开始进入到驱动的数据读取端了。这里的初始化是重载了器件的init函数,也就是
这个函数就需要仔细去阅读了,这里主要是去MPU的ID
,然后设备初始化开辟数据空间
进行复位相关配置等等,这里需要配合MPU6000的寄存器手册去看,这里不详细说明,如果有需要大家提出来,本人也是可以出一个文档进行说明,来教大家如何查看数据手册和编写底层驱动的。
这里的重头函数是,这里面就有了数据的读取了。进入该函数,首先进行定义数据,真正的读取是函数
这个函数是read,至于为什么是read函数就需要有一点linux的常识了,这里的read是一个虚函数。这里后面到时候在做解释。
这里就开始组合数据帧了,得到原始的加速度,温度和陀螺仪数据。
得到数据后对这些数据的处理也比价多,有数据非0判断、数据交换、旋转、数据偏移纠正滤波。这些里面就涉及到了算法哦,比如原始数据的滤波器就用到了二阶滤波。算法这块我们暂时不去细讲,目前的文档比较适合应用,到时候也会出一些文档适合真正的高手,就是算法这块了。
数据相关处理完了之后就是nuttx的 机制出马了需要发布数据。就是通过
这里也说一下,sensor_accel、sensor_gyro这两个就是主题的名字,至于这个主题就是
这里面就有对数据的说明了,这里说一下.msg文件只是一个过渡文件,最终会通过系统工具转换为.h文件。如果自己要写新的主题数据也是一样的编写一个.msg文件然后再目录下的Cmakelists文件加入新的.msg文件就Ok了。在使用的时候加入头文件(对应的文件.h)>就行了。这个生成的h文件是在目录下。发布数据后就差不多完事了。然后就是启动自动收集数据了。
。这样MPU6000的数据和驱动就打通了哦。
这里对nuttx的相关函数进行说明一下,自己去理解哦,这个并不难,也没必要知道函数怎么来的,只需要知道函数功能和使用就行了。
int poll(struct pollfd fds[], nfds_t nfds, int timeout)
功能:监控文件描述符(多个);
说明:timemout=0,poll()函数立即返回而不阻塞;timeout=INFTIM(-1),poll()会一直阻塞下去,直到检测到return > 0;
参数:
返回值:
int orb_subscribe(const struct orb_metadata *meta)
功能:订阅主题(topic);
说明:即使订阅的主题没有被公告,但是也能订阅成功;但是在这种情况下,却得不到数据,直到主题被公告;
参数:
返回值:
eg:
int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
功能:从订阅的主题中获取数据并将数据保存到buffer中;
参数:
返回值:
eg:
orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data)
功能:公告发布者的主题;
说明:在发布主题之前是必须的;否则订阅者虽然能订阅,但是得不到数据;
参数:
返回值:错误则返回ERROR;成功则返回一个可以发布主题的句柄;如果待发布的主题没有定义或声明则会返回-1,然后会将errno赋值为ENOENT;
eg:
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
功能:发布新数据到主题;
参数:
返回值:OK表示成功;错误返回ERROR;否则则有根据的去设置errno;
eg:
int orb_set_interval(int handle, unsigned interval)
功能:设置订阅的最小时间间隔;
说明:如果设置了,则在这间隔内发布的数据将订阅不到;需要注意的是,设置后,第一次的数据订阅还是由起初设置的频率来获取,
参数:
返回值:OK表示成功;错误返回ERROR;否则则有根据的去设置errno;
eg:
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority)
功能:设备/驱动器的多个实例实现公告,利用此函数可以注册多个类似的驱动程序;
说明:例如在飞行器中有多个相同的传感器,那他们的数据类型则类似,不必要注册几个不同的话题;
参数:
返回值:
eg:
int orb_subscribe_multi(const struct orb_metadata *meta, unsigned instance)
功能:订阅主题(topic);
说明:通过实例的ID索引来确定是主题的哪个实例;
参数:
返回值:
eg:
int orb_unsubscribe(int handle)
功能:取消订阅主题;
参数:
返回值:
eg:
int orb_check(int handle, bool *updated)
功能:订阅者可以用来检查一个主题在发布者上一次更新数据后,有没有订阅者调用过ob_copy来接收、处理过;
说明:如果主题在在被公告前就有人订阅,那么这个API将返回“not-updated”直到主题被公告。可以不用poll,只用这个函数实现数据的获取。
参数:
返回值:
eg:
int orb_stat(int handle, uint64_t *time)
功能:订阅者可以用来检查一个主题最后的发布时间;
参数:
返回值:
eg:
int orb_exists(const struct orb_metadata *meta, int instance)
功能:检测一个主题是否存在;
参数:
返回值:
eg:
int orb_priority(int handle, int *priority)
功能:获取主题优先级别;
参数:
返回值:
eg:
数据流程使用如下图:
http://blog.youkuaiyun.com/qq_18112493/article/details/69951102