查看: 14518|回复: 18

[经验] GD32F207E+MPU9255数据读取

  [复制链接]

主题

好友

349

积分

秀才

  • TA的每日心情
    开心
    2015-12-31 18:35
  • 签到天数: 30 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2016-1-9 14:14:35 |显示全部楼层
    本帖最后由 湛无双 于 2016-1-11 11:08 编辑

    本次实验的目的在于能够读取到MPU9255的原始数据,后面还有帖子进行数据融合,今天主要内容是使用GD32F207ZE红板子进行开发,先是编写IIC程序,然后读取DATASHEET进行参数设置,并读取原始数据显示出来。
    首先,感谢爱板网提供的这次机会,让我能够使用上国产的GD32F207板子,总体来说,拿到板子感觉做工很精致,并且外观也不错,唯一有点缺陷的是为了更好的发挥板子的性能,没有使用到Arduino接口,不过这都没关系,后面会有扩展板发来,本人属于第二批的名单,不晓得什么时候能收到,不过这完全不影响我读取MPU9255原始数据。
    MPU9255集成了三轴加速度传感器,三轴陀螺仪和三轴磁力计。其中三轴磁力计是采用片内集成AK8963的方式实现的,这也导致了写程序的时候不仅仅要操作一个芯片,其实要操作两个芯片,虽然只有一个芯片。
    一、MPU9255硬件原理图
    9255-sch.jpg

    这个是买到的MPU9255的原理图,其实这个原理图中比较中的部分是接口定义和电源电压供应,可以看到模块把主要的接口都给引了出来,那么本次实验既然使用到了IIC接口,那就只用里面的SDA和SCL吧~。
    其次是原理图中的电源供应问题,根据芯片手册所提及的电源供给电压,里面是这么说的:
    1.png

    可以看到供给电压在2.4V~3.6V的范围,但是模块上已经集成了电压稳压模块,那就直接使用好了,如果外部电压采用3.3V,可以使用短路模块上的焊盘来实现低电压的输入,使用起来很方便,本次实验就是使用了这种方式。
    二、MPU9255软件编写
    ①查看MPU9255的设备地址
    2.png

    手册上所参考的I2C地址受外部引脚的控制,所购买的模块上已经把AD0强行拉低了,那么I2C设备地址为1101000,在实际的读写过程中需要进行读写,第八位表示读写,那么写的地址为11010000,读的地址为11010001,就可以说模拟I2C中地址为0xd0,这在后面的编写中是很重要的。
    ②查看相关寄存器
    在进行I2C调制之前,比较重要的一步是读取I2C设备的设备ID,这样就可以知道我们调试的I2C是否已经成功了,同时也可以查看设备是否存在,根据手册上所说的,设备ID名字为WHO AM I寄存器,通过读取这个寄存器可以返回一个固定值。
    3.png


    这个固定值为0x73,在这里需要提一句的是上电之初需要想电源管理寄存器写入0x00来启动设备,这一点是比较重要的。
    那么我们就可以借此编写代码,其中I2C底层的协议不再赘述。
    1. MPU_Write(MPU9255_ADDR,PWR_MGMT_1,0x00);

    2. Delay_1ms(10);
    3. i2c_dev=MPU_Read(MPU9255_ADDR,WHO_AM_I);
    复制代码
    在这个代码里面,我们开启了MPU9255,并且读取了设备寄存器,如果我们读取到的i2c_dev值为0x73,那就说明读取成功了,可以进行下一步的操作。
    ③读取三轴加速度和三轴陀螺仪
    在具体的操作中,还需要设置采样率,量程范围,不过这里不再说那些,先直接告诉大家怎么用,还是看手册,手册里面写了三轴加速度和三轴陀螺仪的数据地址。
    4.png

    手册上所述的地址如图所示,可以看到MPU9255还包含了温度测量功能,不过咱们目前用不到,还是不要管了,记得本科上传感器技术的老师说过有的传感器里面包含有温度测量功能,这个功能是用来校正传感器自身的温度漂移,实现传感器在温度上的校正,具体怎么操作也没有说,那么就算了。
    这样也就可以编写出来读取三轴加速度和三轴陀螺仪的函数了,这里使用了连续多个读取的方式,节省了时间提高了效率。
    1. void MPU9255_ReadAccel(ACCEL_TypeDef *ACCEL_Struct)
    2. {
    3.         u8 AccelTable[6];
    4.         
    5.         MPU_Reads(MPU9255_ADDR,ACCEL_XOUT_H,AccelTable,6);
    6.         
    7.         ACCEL_Struct->accel_x = ((u16)AccelTable[0])<<8 | AccelTable[1];
    8.         ACCEL_Struct->accel_y = ((u16)AccelTable[2])<<8 | AccelTable[3];
    9.         ACCEL_Struct->accel_z = ((u16)AccelTable[4])<<8 | AccelTable[5];
    10.         
    11. }
    12. void MPU9255_ReadGyro(GYRO_TypeDef *GYRO_Struct)
    13. {
    14.         u8 GyroTable[6];
    15.         
    16.         MPU_Reads(MPU9255_ADDR,GYRO_XOUT_H,GyroTable,6);
    17.         
    18.         GYRO_Struct->gyro_x = ((u16)GyroTable[0])<<8 | GyroTable[1];
    19.         GYRO_Struct->gyro_y = ((u16)GyroTable[2])<<8 | GyroTable[3];
    20.         GYRO_Struct->gyro_z = ((u16)GyroTable[4])<<8 | GyroTable[5];
    21. }
    复制代码
    上面的函数就完成了数据的读取了,到了这里大家可能疑惑三轴磁力计怎么没有,上面给大家说过了,三轴磁力计是MPU9255模块里面的另一个,需要特别的方式读取,那么我们就需要慢慢来分析。
    ④三轴磁力计数据读取
    同样下载了AK8963的手册,看手册里面是怎么说的。不过在读取之前需要将MPU9255设置为BYPASS MODE,怎么设置这个呢?有一个专门的寄存器可以完成。
    5.png

    就是这个55寄存器,十六进制值为0x37,只要他的位1设置为一就可以了,所以在读取钱需要向0x37寄存器写入0x02,至于其他位咱们就不管了。
    三轴磁力计AK8963的I2C设备地址在手册里面是这么叙述的:
    6.png


    分别是00011xxx,这个xxx咱们直接设置为0好了,那么8位地址就是0x18了,很好的一个地方是AK8963也有设备ID,我们可以读取到,直接读取AK8963的寄存器0x00就可以得到设备ID,值为0x48,这个如下面这个图:
    7.png


    那么程序里面就可以这么写:
    1. MPU_Write(MPU9255_ADDR,INT_PIN_CFG,0x02);//进入Bypass模式,用于控制电子指南针
    2. i2c_dev = MPU_Read(MAG_ADDR,MAG_WIA);
    3. if(i2c_dev == MAG_ID)
    4. {
    5.         MPU_Write(MAG_ADDR,MAG_CNTL1,0x01);
    6.         return 0;
    7. }
    复制代码
    直接读取ID看是否匹配,就可以查看方法是不是对的。我也是这个认为的,如果是对的,就可以启动单次数据转换了。
    在读取三轴磁力计数据的时候,写好的函数是这样的:
    1. void MPU9255_ReadMag(MAG_TypeDef *MAG_Struct)
    2. {
    3.         u8 MagTable[6];
    4.         
    5. //        MPU_Write(MAG_ADDR,MAG_CNTL1,0x01);
    6. //        Delay_1ms(10);
    7.         MPU_Reads(MAG_ADDR,MAG_XOUT_L,MagTable,6);
    8.         MPU_Write(MAG_ADDR,MAG_CNTL1,0x01);
    9.         
    10.         MAG_Struct->mag_x = ((u16)MagTable[1])<<8 | MagTable[0];
    11.         MAG_Struct->mag_y = ((u16)MagTable[3])<<8 | MagTable[2];
    12.         MAG_Struct->mag_z = ((u16)MagTable[5])<<8 | MagTable[4];
    13.         
    14. }
    复制代码
    这个里面的MAG_CNTL1是用来启动单次数据转换的,千万要记住,如果不加这句话,下次读取会发现三轴磁力计的数据是不会变的,切记切记。

    三、主函数的调用
    主函数的调用无非是查看设备是否存在,如果存在的话,就开始循环读取数据,并发送给电脑,我也是这么编写的。
    1. int main(void)
    2. {
    3.         ACCEL_TypeDef ACCEL_TypeStructure;
    4.         GYRO_TypeDef GYRO_TypeStructure;
    5.         MAG_TypeDef MAG_TypeStructure;
    6.         
    7.     LED_config();
    8.     SysTick_Configuration();
    9.         USART1_Init(115200);
    10.         
    11.         switch(MPU9255_Init())
    12.         {
    13.         case 1:
    14.                 while(1)
    15.                 {
    16.                         GPIOD->DOR ^= GPIO_PIN_11;
    17.                         Delay_1ms(500);
    18.                 }
    19.         case 2:
    20.                 while(1)
    21.                 {
    22.                         GPIOD->DOR ^= GPIO_PIN_12;
    23.                         Delay_1ms(300);
    24.                 }
    25.         case 0:
    26.                 break;
    27.         default:
    28.                 while(1);
    29.         }
    30.         
    31.     while (1)
    32.    {
    33.                 Delay_1ms(200);
    34.                 MPU9255_ReadAccel(&ACCEL_TypeStructure);
    35.                 MPU9255_ReadGyro(&GYRO_TypeStructure);
    36.                 MPU9255_ReadMag(&MAG_TypeStructure);
    37.                 u1_printf("ACCEL=>X:%d,Y:%d,Z:%d\r\n",ACCEL_TypeStructure.accel_x,ACCEL_TypeStructure.accel_y,ACCEL_TypeStructure.accel_z);
    38.                 u1_printf("GYRO=>X:%d,Y:%d,Z:%d\r\n",GYRO_TypeStructure.gyro_x,GYRO_TypeStructure.gyro_y,GYRO_TypeStructure.gyro_z);
    39.                 u1_printf("MAG=>X:%d,Y:%d,Z:%d\r\n",MAG_TypeStructure.mag_x,MAG_TypeStructure.mag_y,MAG_TypeStructure.mag_z);
    40.                 u1_printf("****************************\r\n");
    41.                 GPIOD->DOR ^= GPIO_PIN_13;
    42.    }
    43. }
    复制代码
    在程序的设计中,使用了串口来发送数据到电脑,这样查看数据是否是正确的,完成初步的实验调试,下一步是数据的融合,得到三轴姿态。

    四、实物图和结果
    首先是实物图,有点丑,大家别介意啊~
    IMG_20160108_174043.jpg


    IMG_20160108_174154.jpg


    这个里面使用到的电源为3.3V电源,其中SCL为PD9,SDA为PD8,哪个引脚无所谓,关键是配置正确就可以了。
    根据程序里面写的,但没有模块的时候,亮第一个灯亮,有了模块以后第三个灯亮,并且闪烁表示当前程序的运行状态。串口调试助手获取到的数据截图如下:
    8.png

    可以看到,数据当前获取正常,三轴加速度,三轴陀螺仪和三轴磁力计一切正常,完成了数据的读取,下一步数据融合有了数据的融合基础。



    回复

    使用道具 举报

    主题

    好友

    349

    积分

    秀才

  • TA的每日心情
    开心
    2015-12-31 18:35
  • 签到天数: 30 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2016-1-9 14:15:06 |显示全部楼层
    本帖最后由 湛无双 于 2016-1-9 15:36 编辑

    这个楼层用来放置源码工程包和参考资料,工程基于Keil5.15,使用了标准库进行MPU9255的开发。PDF手册包含了MPU9255的PS(Product Specification)和RM(Regesiter Map and Description),以及另外一个AK8963的手册。
    PS-MPU-9255 .pdf (469.21 KB, 下载次数: 148)
    RM-MPU-9255.pdf (722.8 KB, 下载次数: 172)
    AK8963.pdf (649.68 KB, 下载次数: 207)
    Project_MPU9255.zip (3.48 MB, 下载次数: 579)
    回复

    使用道具 举报

    主题

    好友

    349

    积分

    秀才

  • TA的每日心情
    开心
    2015-12-31 18:35
  • 签到天数: 30 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2016-1-9 14:15:42 |显示全部楼层
    占楼备用 稍后编辑 稍后编辑
    回复

    使用道具 举报

    主题

    好友

    815

    积分

    举人

  • TA的每日心情
    慵懒
    2014-11-28 09:29
  • 签到天数: 3 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    发表于 2016-1-11 09:27:56 |显示全部楼层
    非常不错的分享,赞!
    回复

    使用道具 举报

    主题

    好友

    27

    积分

    白丁

  • TA的每日心情
    开心
    2019-1-8 16:09
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2016-3-21 14:22:10 |显示全部楼层
    非常不错的分享,赞!
    回复

    使用道具 举报

    主题

    好友

    3

    积分

    白丁

    该用户从未签到

    发表于 2016-4-6 14:42:35 |显示全部楼层
    感谢楼主分享,赞!
    回复

    使用道具 举报

    主题

    好友

    3

    积分

    白丁

    该用户从未签到

    发表于 2016-7-14 17:32:52 |显示全部楼层
    :lol
    回复

    使用道具 举报

    主题

    好友

    817

    积分

    举人

  • TA的每日心情
    奋斗
    2017-12-1 14:21
  • 签到天数: 91 天

    连续签到: 1 天

    [LV.6]常住居民II

    发表于 2016-8-23 11:51:14 |显示全部楼层
    感谢楼主分享,赞!陀螺仪精度不高吧
    回复

    使用道具 举报

    主题

    好友

    8

    积分

    白丁

    该用户从未签到

    发表于 2016-10-2 17:24:02 |显示全部楼层
    谢谢楼主分享!
    不知为何,我无法读取磁力计ID
    MPU9250_WR_Reg(GYRO_ADDRESS,0x37,0x02);//turn on Bypass Mode
    Delayms(20);       
    BUF[0]=MPU9250_RD_Reg(MAG_ADDRESS,0x00);
    Buf[0]中数值为0.。。
    回复

    使用道具 举报

    主题

    好友

    4

    积分

    白丁

    该用户从未签到

    发表于 2016-10-13 16:29:24 |显示全部楼层
    感谢up主分享,受益匪浅
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    关闭

    站长推荐上一条 /4 下一条

    手机版|电路城

    GMT+8, 2019-12-15 10:53 , Processed in 0.119703 second(s), 21 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz!

    返回顶部