四轴飞行器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. c++中冒号(:)和双冒号(::)的用法

    1.冒号(:)用法 (1)表示机构内位域的定义(即该变量占几个bit空间) typedef struct _XXX{ unsigned ; unsigned char c; } ; XXX (2)构造 ...

  2. 20160121--Spring

    package com.hanqi; public class HelloWorld { public HelloWorld() { } public HelloWorld(String name) ...

  3. JAVA GC之标记 第五节

    JAVA GC之标记  第五节 OK,我们继续昨天最后留下的问题,什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理. 至于怎么标记,一般有两种方 ...

  4. Cent OS 修改网卡配置

    进入网卡修改界面 vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 描述网卡设备名称 BOOTPROTO=static 静态IP,这里一 ...

  5. echarts实现上海地域PM值(map、timeline)

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  6. 学习iOS开发的前言

    一.什么是iOS 要想学习iOS开发,首先要搞清楚什么是iOS.iOS其实是一款操作系统,就像平时我们在电脑上用的XP.Win7,都是操作系统. 那什么是操作系统呢?操作系统其实是一种软件,是直接运行 ...

  7. 几种改变Activity回退栈默认行为的Intent Flag

    FLAG_与LaunchMode相比最大的不同是临时性 1.FLAG_ACTIVITY_NEW_TASK: Developer.android.com的说法: (1)在新的task中启动这个Activ ...

  8. ThinkPHP中ajax提交数据

    最近在做项目时遇到了一些需要从页面用ajax提交数据到后台的操作,无奈本人技术有限,网上苦寻,研究了一下ajax和thinkPHP的结合,黄天不负苦心人,终于搞定了. 闲话少叙,进入正题:我需要从页面 ...

  9. c语言libcurl 使用实例get/post方法+c语言字符串处理

    #include <stdio.h> #include <curl/curl.h> #include <string.h> #include <ctype.h ...

  10. mciSendString用法

    使用MCI API,源文件中需要包含头文件 Mmsystem.h,在Project->Settings->Link->Object/libray module中加入库 Winmm.l ...