四轴飞行器1.3 MPU6050(大端)和M4的FPU开启方法

 原创文章,欢迎转载,转载请注明出处
      最近时间花在最多的地方就是STM32的I2C上了。之前就知道STM32的I2C并不好用,因为之前用过模拟的I2C,也写过AVR的I2C也就是TWI的硬件驱动,所以想试试写STM32的硬件I2C。。。为了避免库带来的麻烦,之前和特意将STM32F4的标准库升级到了1.3.0,但是貌似问题依旧。于是在网上找到了ST转为I2C写的CPAL的库,拿着它的英文手册和例子看了下,觉得很不错,功能相当的齐全,按照手册配置用起来应该不错,于是开始加载到自己的项目中。它需要一个定时器,用来管理超时,当通讯出现问题的时候,通过这个超时机制可以见得到,从而可以做一些简单的处理,它默认用的是systick中断,这个好办啊,用RTT的一个线程来替代systick或者用另外一个定时器就可以了,它还有一个要求,需要用到I2C相关的两个中断设置为最高优先级,虽然觉得优点不舒服哈,但是只能这样设置了,其实STM32中I2C的硬件缺陷就在这,需要第一时间响应I2C中断,否则就可能出现问题,就算自己写STM32的I2C,这两个中断优先级也需要设定的很高,可是之后发现了一个我认为可能接受不了的东西,就是在中断里面有一个宏,__CPAL_I2C_TIMEOUT ,定义如下
 #define __CPAL_I2C_TIMEOUT_DETECT                ((pDevInitStruct->wCPAL_Timeout == CPAL_I2C_TIMEOUT_MIN) ||\
(pDevInitStruct->wCPAL_Timeout == CPAL_I2C_TIMEOUT_DEFAULT)) #define __CPAL_I2C_TIMEOUT(cmd, timeout) pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_MIN + (timeout);\
while (((cmd) == ) && (!__CPAL_I2C_TIMEOUT_DETECT));\
if (__CPAL_I2C_TIMEOUT_DETECT)\
{\
return CPAL_I2C_Timeout (pDevInitStruct); \
}\
pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_DEFAULT

也就是说,这个CPAL库需要试用最高优先级的中断,而且在最高优先级的中断里面有个while,这可是最高优先级中断好么,我其他的中断还要不要响应了?RTT的线程调度还能不能愉快的调度了?积分还能不能在正确的时间内完成了, 积分出来的数据会不会漂的更厉害?果断弃之。。
      放弃CPAL库后,还有三个选择,买的板子是有写好的I2C的硬件库的,没有开源,为了快点做出来,就用他的库吧,当放进来编译好没错误后,下到板子里面运行,发现会卡死。。用不了。。当时不知道什么问题,后来想应该是没有用c99的原因,MDK默认是c89。还有两个选择,自己写硬件I2C或者用简单暴力的模拟I2C。。。折腾了好几天,进度太慢,我们首要任务是先飞起来,后面慢慢改,于是决定用模拟I2C,只要好点封装起来,后面把写好的更好的I2C放进去还是很容易的。
     模拟I2C就不多说了, 说下MPU6050吧。。。MPU6050网络上的资料那是非常的多,设置什么的都比较简单,我比较懒哈,没用FIFO,懒得设置,就打算从0x3B移植读到0X48,把所有数据读出来,简单的方法就是一个byte一个byte的读出来,然后强制转换成U16格式的再进行计算就可以了,可是这真的行得通吗?用union测试了下,STM32F4的是小端模式,也就是说数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中,可是看看MPU6050的手册,你会发现它是大端模式,数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中。如下图:

如果全部顺序读出来,LSB和MSB是反的,要转换一次。。于是又懒了,I2C连续读都已经写好了,但是不用算了,利用struct和union解决这个问题好了,用如下的方式定义一个struct和union的混合结构:

 typedef struct
{
union
{
struct
{
u8 data_L;
u8 data_H;
} b;
s16 data;
} acce_x;
union
{
struct
{
u8 data_L;
u8 data_H;
} b;
s16 data;
} acce_y;
union
{
struct
{
u8 data_L;
u8 data_H;
} b;
s16 data;
} acce_z; union
{
struct
{
u8 data_L;
u8 data_H;
} b;
s16 data;
} temp; union
{
struct
{
u8 data_L;
u8 data_H;
} b;
s16 data;
} gyro_x;
union
{
struct
{
u8 data_L;
u8 data_H;
} b;
s16 data;
} gyro_y;
union
{
struct
{
u8 data_L;
u8 data_H;
} b;
s16 data;
} gyro_z; }MPU6050_DATA_T;

读数据的时候就容易了,一个字节一个字节的读,例如读ACCX的高字节,读到mpu6050_data_t->acce_x.b.data_H中, 低字节读到mpu6050_data_t->acce_x.b.data_L中,而我们取数据的时候用mpu6050_data_t.acce_x.data就可以了,不需要进行LSB和MSB的数据转换了,哈,懒人用懒人的方法,不过这个方法毕竟效率不高,等飞机飞起来再改。。哈。。
读到的数据如下:

这些数值都是没有处理过的,裸数据,还要校正和根据我们选的量程来进行转换才行。。

加速读我们选的是+-4G,陀螺仪选的量程是+-2000度每秒,他们每个数值的寄存器都是16位的,对应的满量程数值为65536,65536/8 = 8192,计算出来的数值和手册上刚好是对应的哈,我们只要将读到的数据除以8192,再乘当地的重力加速度,就可以的到实际的加速度值了,总所周知,虽然M4带FPU,我们也开启了FPU,但是做乘法比做除法快,所以我们不除8192,而是乘以8192的倒数0.0001220703125,然后再乘9.81就好了。

陀螺仪是一样的哈,+-2000度每秒 对应的LSB Sensitivity是16.4,16.4的倒数是0.0609756097560976,读出来的值乘这个数,不过我们只取了小数点的后八位。
    温度的话手册上有个公式,除以340+36.5就得出实际温度了。转换后的图如下:

其实我们上面有偷懒,漏了两个步骤哈。。其一是加速度传感器的标定,我们还没错,不过影响不会太大,还有就是陀螺的0偏校正,这个是要做的。

以前用过lsm303dlh算出过姿态数据的哈,就是反三角函数算,用的场合不一样,数据也没有滤波什么的,就这样算了。。这里终点是我们要用到反三角函数,M4可是带FPU的,不用白不用。。用了速度快很多。。哈。。开启FPU。。需要下面几个步骤:
在SystemIni 中有如下一句话

   /* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << *)|(3UL << *)); /* set CP10 and CP11 Full Access */
#endif

所以第一步需要设置这两个宏,__FPU_PRESENT,__FPU_USED,寻找一番,发现在STM32F4XX.h中

 #define __MPU_PRESENT             1       /*!< STM32F4XX provides an MPU
#define __FPU_PRESENT 1 /*!< FPU present 已经定义好了
如果我们需要用到FPU,我们需要使用ARM为我们提供的数学函数,我们需要包涵arm_math.h头文件,
还需要添加arm_cortexMxx_math.lib到工程文件中,位于\Libraries\CMSIS\Lib\ARM中。

* The library installer contains prebuilt versions of the libraries in the <code>Lib</code> folder.
   * - arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4)
   * - arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4)
   * - arm_cortexM4l_math.lib (Little endian on Cortex-M4)
   * - arm_cortexM4b_math.lib (Big endian on Cortex-M4)
   * - arm_cortexM3l_math.lib (Little endian on Cortex-M3)
   * - arm_cortexM3b_math.lib (Big endian on Cortex-M3)
   * - arm_cortexM0l_math.lib (Little endian on Cortex-M0)

   * - arm_cortexM0b_math.lib (Big endian on Cortex-M3)

STM32F407我们用的是小端模式,并且带FPU,支持浮点运算的,所以我们要添加的库是 arm_cortexM4lf_math.lib ,编译后会发现有错误,需要添加 ARM_MATH_CM4宏,好了,一切准备就绪,可以使用M4的FPU了。。哈。。
看一下stm32f40x\Libraries\CMSIS\DSP_Lib\Source目录,发现有不少文件,如下图:

解释看个名字也能直到大概哈,草靠网上的解释,矩阵计算,滤波函数说不定后面可以用到。。瞬间感觉高大上。。

BasicMathFunctions
提供浮点数的各种基本运算函数,如加减乘除等运算。
CommonTables
arm_common_tables.c文件提供位翻转或相关参数表。
ComplexMathFunctions
复述数学功能,如向量处理,求模运算的。
ControllerFunctions
控制功能,主要为PID控制函数。arm_sin_cos_f32/-q31.c函数提供360点正余弦函数表和任意角度的正余弦函数值计算功能。
FastMathFunctions
快速数学功能函数,提供256点正余弦函数表和任意任意角度的正余弦函数值计算功能,和Q值开平方运算:
Arm_cos_f32/_q15/_q31.c:提供256点余弦函数表和任意角度余弦值计算功能。
Arm_sin_f32/_q15/_q31.c:提供256点正弦函数表和任意角度正弦值计算功能。
Arm_sqrt_q15/q31.c:提供迭代法计算平方根的函数。对于M4F的平方根运算,通过执行VSQRT指令完成。
FilteringFunctions
滤波函数功能,主要为FIR和LMS(最小均方根)滤波函数。
MatrixFunctions
矩阵处理函数。
StatisticsFunctions
统计功能函数,如求平均值、计算RMS、计算方差/标准差等。
SupportFunctions
支持功能函数,如数据拷贝,Q格式和浮点格式相互转换,Q任意格式相互转换。
TransformFunctions
变换功能。包括复数FFT(CFFT)/复数FFT逆运算(CIFFT)、实数FFT(RFFT)/实数FFT逆运算(RIFFT)、和DCT(离散余弦变换)和配套的初始化函数。  

 
接下来要做的就是把MPU6050裸数据处理下,传到matlab进行数据处理了。。要写matlab的串口咯。。。。 
 
通讯协议也可能开始需要简单的策划下了,因为后面准备自己通过2401做遥控器的,通讯协议也应该开始考虑了。。

四轴飞行器1.3 MPU6050(大端)和M4的FPU开启方法的更多相关文章

  1. 四轴飞行器飞行原理与双闭环PID控制

    四轴轴飞行器是微型飞行器的其中一种,相对于固定翼飞行器,它的方向控制灵活.抗干扰能力强.飞行稳定,能够携带一定的负载和有悬停功能,因此能够很好地进行空中拍摄.监视.侦查等功能,在军事和民用上具备广泛的 ...

  2. 四轴飞行器1.5 各种PID对比分析及选择

    原创文章,欢迎转载,转载请注明出处 这篇文章主要介绍我对PID的理解,以及选择PID算法的过程. 一 PID的理解和学习过程 二 飞控的PID效果 先上个飞控PID的响应的视频:介绍在后面 地址:ht ...

  3. 四轴飞行器1.2.2 RT-Thread 串口

    四轴飞行器1.2.2 RT-Thread 串口        本来是打算说根据RT-Thread的设备管理提供的驱动接口些串口驱动的,但是仔细一看,我去,串口驱动写好了,只需要调用就可以了.下面我们说 ...

  4. 四轴飞行器1.1 Matlab 姿态显示

    四轴飞行器1.1 Matlab 姿态显示 开始做四轴了,一步一步来,东西实在很多,比较杂.先做matlab上位机,主要用来做数据分析,等板子到了可以写飞控的程序了,从底层一层一层开始写..希望能好好的 ...

  5. 四轴飞行器1.7 NRF24L01P无线通讯和改进型环形缓冲(转)

    源: 四轴飞行器1.7 NRF24L01P无线通讯和改进型环形缓冲

  6. 从零开始的四轴飞行器-开篇flag

    在这里立下flag,我要理解学会四轴飞行器的控制方法.

  7. 四轴飞行器1.4 姿态解算和Matlab实时姿态显示

    原创文章,欢迎转载,转载请注明出处 MPU6050数据读取出来后,经过一个星期的努力,姿态解算和在matlab上的实时显示姿态终于完成了. 1:完成matlab的串口,并且实时通过波形显示数据 2:添 ...

  8. crazyflie四轴飞行器

    源地址:http://www.bitcraze.se/2013/02/pre-order-has-started/ Crazyflie是一个开源的纳米四旋翼 来几张靓照 开发平台是开源的,所以原理图和 ...

  9. Delphi笔记(GL_Scene四轴飞行器模型)

    有了前的一篇做铺垫,已经简单的说了GL_Scene的下载安装和一个简单的实例制作.现在就要开始制作一个3D的模型了,具体的步骤就不再这里多说了,直接上图和代码吧! [第一版]先看一下最开始的版本吧,比 ...

随机推荐

  1. Timeout expired 超时时间已到. 达到了最大池大小 错误及Max Pool Size设置

    参考数据库链接串: <add key="data" value="server=192.168.1.123; Port=3306; uid=root; pwd=ro ...

  2. 安装rac遇到的问题总结:

    1. 选择虚拟机工具 这个过程是非常的波折.这次安装也让我吸取了很大教训,获得了宝贵经验. 首先啊,必须了解rac的机制. 共享磁盘+多实例. 这就意味着,我们必须使用一个支持共享磁盘的虚拟机. 第一 ...

  3. 【转】sun.misc.BASE64Encoder找不到jar包的解决方法

    只需要在project build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了.(太神奇了,转自http://blog. ...

  4. php汉字截取

    /** * 截取HTML,并自动补全闭合 * @param $html * @param $length * @param $end */ function subHtml($html,$length ...

  5. js call方法介绍

    call 方法 请参阅 应用于:Function 对象 要求 版本 5.5 调用一个对象的一个方法,以另一个对象替换当前对象. call([thisObj[,arg1[, arg2[, [,.argN ...

  6. 树 -- AVL树

    前言 通过之前对二叉查找树的讨论,我们知道在给定节点数目的情况下,二叉树的高度越低,查找所用时间也就越短. 在讨论红黑树的时候,我们说过红黑树并非完全"平衡"的二叉树,只是近似&q ...

  7. zend framework virtualhost设置方法

    Phpunit 的用法 php phpunit.phar 就可以运行phpunit了 修改本地域名vhost F:\Tools\wamp\bin\apache\apache2.4.9\conf\ext ...

  8. HTML 5 新标签

    HTML 5 是一个新的网络标准,目标在于取代现有的 HTML 4.01, XHTML 1.0 and DOM Level 2  HTML 标准.它希望能够减少浏览器对于需要插件的丰富性网络应用服务( ...

  9. RabbitMQ是一个由erlang开发的基于AMQP(Advanced Message Queue )协议的开源实现。

    RabbitMQ是一个由erlang开发的基于AMQP(Advanced Message Queue )协议的开源实现. 1. 介绍 RabbitMQ是一个由erlang开发的基于AMQP(Advan ...

  10. Linux 内核无线子系统

    Linux 内核无线子系统 浅谈 Linux 内核无线子系统 Table of Contents 1. 全局概览 2. 模块间接口 3. 数据路径与管理路径 4. 数据包是如何被发送? 5. 谈谈管理 ...