amoBBS 阿莫电子论坛

 找回密码
 注册
搜索
bottom↓
查看: 13389|回复: 31

分享自己調通的 MPU9255 SPI 讀取 AK8963 代碼

[复制链接]
发表于 2015-7-18 14:04:17 | 显示全部楼层 |阅读模式
本帖最后由 john800422 于 2015-7-18 14:17 编辑

自己調通的代碼,透過 SPI 讀取 MPU9255 的加速度計、陀螺儀、磁力計資料,
使用 MPU6555 內建的自動讀取功能,設定好後就會連續自動讀取 AK8963 的資料,
只需要從 EXT_SENS_DATA_00 - EXT_SENS_DATA_07 讀取出來就可以了,
這個功能蠻方便的,下面放出幾個關鍵的部分,詳細的工程最下面可以下載,或是在 github 下載
https://github.com/KitSprout/Red ... _Module_MPU9255_SPI

使用 STM32F103C 實現,目前 400 Hz 還可以正常運作。
接收部分使用 MATLAB,詳細參考下面帖子
http://www.amobbs.com/forum.php? ... =5627278&extra=

  1. #define MPU6555_InitRegNum 11
  2. #define AK8963_InitRegNum  2
  3. uint8_t MPU9255_Init( MPU_InitTypeDef *MPUx )
  4. {
  5.   uint8_t status = ERROR;
  6.   uint8_t MPU6555_InitData[MPU6555_InitRegNum][2] = {
  7.     {0x80, MPU6555_PWR_MGMT_1},     // Reset Device
  8.     {0x01, MPU6555_PWR_MGMT_1},     // Clock Source
  9.     {0x30, MPU6555_USER_CTRL},      // Set I2C_MST_EN, I2C_IF_DIS
  10.     {0x00, MPU6555_PWR_MGMT_2},     // Enable Acc & Gyro
  11.     {0x07, MPU6555_CONFIG},         // DLPF_CFG[2:0] = 111;
  12.     {0x18, MPU6555_GYRO_CONFIG},    // +-2000dps
  13.     {0x08, MPU6555_ACCEL_CONFIG},   // +-4G
  14.     {0x48, MPU6555_ACCEL_CONFIG_2}, // Set Acc Data Rates
  15.     {0x10, MPU6555_INT_PIN_CFG},    // Set INT_ANYRD_2CLEAR
  16.     {0x10, MPU6555_INT_ENABLE},     //
  17.     {0x4D, MPU6555_I2C_MST_CTRL},   // I2C Speed 400 kHz
  18.   };
  19.   uint8_t AK8963_InitData[AK8963_InitRegNum][2] = {
  20.     {0x01, AK8963_CNTL2},           // Reset Device
  21.     {0x06, AK8963_CNTL1},           // Continuous measurement mode 2
  22.   };

  23.   MPU6555_InitData[5][0] = MPUx->MPU_Gyr_FullScale;       // MPU6555_GYRO_CONFIG
  24.   MPU6555_InitData[4][0] = MPUx->MPU_Gyr_LowPassFilter;   // MPU6555_CONFIG
  25.   MPU6555_InitData[6][0] = MPUx->MPU_Acc_FullScale;       // MPU6555_ACCEL_CONFIG
  26.   MPU6555_InitData[7][0] = MPUx->MPU_Acc_LowPassFilter;   // MPU6555_ACCEL_CONFIG_2
  27.   AK8963_InitData[1][0] |= MPUx->MPU_Mag_FullScale;

  28.   for(uint8_t i = 0; i < MPU6555_InitRegNum; i++) {
  29.     MPU9255_WriteReg(MPU6555_InitData[i][1], MPU6555_InitData[i][0]);
  30.     Delay_1ms(1);
  31.   }

  32.   status = MPU9255_Check();
  33.   if(status != SUCCESS)
  34.     return ERROR;

  35.   Delay_10ms(1);

  36. #ifdef _USE_MAG_AK8963
  37.   for(uint8_t i = 0; i < AK8963_InitRegNum; i++) {
  38.     MPU9255_Mag_WriteReg(AK8963_InitData[i][1], AK8963_InitData[i][0]);
  39.     Delay_10ms(1);
  40.   }

  41.         MPU9255_WriteReg(MPU6555_I2C_SLV0_REG, AK8963_ST1);
  42.         MPU9255_WriteReg(MPU6555_I2C_SLV0_ADDR, AK8963_I2C_ADDR | 0x80);
  43.         MPU9255_WriteReg(MPU6555_I2C_SLV0_CTRL, 0x80 | 8);
  44. #endif

  45.   MPU9255_SetSpeed(SPIx_SPEED_HIGH);
  46.   Delay_10ms(1);

  47.   return SUCCESS;
  48. }
复制代码

  1. void MPU9255_getData( int16_t *dataIMU )
  2. {
  3.   uint8_t tmpRead[22] = {0};

  4. #ifdef _USE_MAG_AK8963
  5.   MPU9255_ReadRegs(MPU6555_ACCEL_XOUT_H, tmpRead, 22);
  6. #else
  7.   MPU9255_ReadRegs(MPU6555_ACCEL_XOUT_H, tmpRead, 14);
  8. #endif

  9.   dataIMU[0] = (Byte16(int16_t, tmpRead[6],  tmpRead[7]));    // Temp
  10.   dataIMU[1] = (Byte16(int16_t, tmpRead[0],  tmpRead[1]));    // Acc.X
  11.   dataIMU[2] = (Byte16(int16_t, tmpRead[2],  tmpRead[3]));    // Acc.Y
  12.   dataIMU[3] = (Byte16(int16_t, tmpRead[4],  tmpRead[5]));    // Acc.Z
  13.   dataIMU[4] = (Byte16(int16_t, tmpRead[8],  tmpRead[9]));    // Gyr.X
  14.   dataIMU[5] = (Byte16(int16_t, tmpRead[10], tmpRead[11]));   // Gyr.Y
  15.   dataIMU[6] = (Byte16(int16_t, tmpRead[12], tmpRead[13]));   // Gyr.Z
  16. #ifdef _USE_MAG_AK8963
  17.   dataIMU[7] = (Byte16(int16_t, tmpRead[16], tmpRead[15]));   // Mag.X
  18.   dataIMU[8] = (Byte16(int16_t, tmpRead[18], tmpRead[17]));   // Mag.Y
  19.   dataIMU[9] = (Byte16(int16_t, tmpRead[20], tmpRead[19]));   // Mag.Z
  20. #endif  
  21. }
复制代码

  1. void SysTick_Handler( void )
  2. {
  3.   int16_t IMU_Buf[12] = {0};
  4.   int16_t readData[12] = {0};

  5.   LED_R_Toggle;
  6.   MPU9255_getData(readData);
  7.   readData[1] = readData[1] - Bx;    // Acc.X
  8.   readData[2] = readData[2] - By;    // Acc.Y
  9.   readData[3] = readData[3] - Bz;    // Acc.Z

  10.   IMU_Buf[0] = (int16_t)(readData[1] * Sxx + readData[2] * Sxy + readData[3] * Sxz);  // Acc.X
  11.   IMU_Buf[1] = (int16_t)(readData[1] * Syx + readData[2] * Syy + readData[3] * Syz);  // Acc.Y
  12.   IMU_Buf[2] = (int16_t)(readData[1] * Szx + readData[2] * Szy + readData[3] * Szz);  // Acc.Z
  13.   IMU_Buf[3] = readData[4] * MPU9255G_2000dps;                                        // Gyr.X
  14.   IMU_Buf[4] = readData[5] * MPU9255G_2000dps;                                        // Gyr.Y
  15.   IMU_Buf[5] = readData[6] * MPU9255G_2000dps;                                        // Gyr.Z
  16.   IMU_Buf[6] = readData[7] * MPU9255M_4800uT;                                         // Mag.X
  17.   IMU_Buf[7] = readData[8] * MPU9255M_4800uT;                                         // Mag.Y
  18.   IMU_Buf[8] = readData[9] * MPU9255M_4800uT;                                         // Mag.Z
  19.   IMU_Buf[9] = readData[0] * MPU9255T_85degC;                                         // temp

  20.   Serial_sendDataMATLAB(IMU_Buf, 10);
  21. }
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
发表于 2015-7-18 14:17:45 | 显示全部楼层
首页一看繁体字 就知道是楼主!
发表于 2015-7-18 14:52:53 | 显示全部楼层
芯片在哪买的?
 楼主| 发表于 2015-7-18 19:22:05 | 显示全部楼层
Shampoo 发表于 2015-7-18 14:17
首页一看繁体字 就知道是楼主!

感謝支持
 楼主| 发表于 2015-7-18 19:26:52 | 显示全部楼层

目前是用模塊,芯片的話X寶應該可以買到。
发表于 2015-7-18 21:19:58 | 显示全部楼层
我在搞 MPU9250,能不能将你的原理图贴出来参考下。
 楼主| 发表于 2015-7-18 21:27:53 | 显示全部楼层
沉默胜过白金 发表于 2015-7-18 21:19
我在搞 MPU9250,能不能将你的原理图贴出来参考下。

實際是用 CJMCU-MPU 模塊,沒有要資料所以不清楚電路,
你可以參考我之前的設計 SmartIMU,裡面有 MPU9250 的電路,如果要相容 MPU6500,NC 腳不要接地。
https://github.com/Hom-Wang/SmartIMU
发表于 2015-7-18 21:34:51 | 显示全部楼层
john800422 发表于 2015-7-18 21:27
實際是用 CJMCU-MPU 模塊,沒有要資料所以不清楚電路,
你可以參考我之前的設計 SmartIMU,裡面有 MPU925 ...

Thanks a lot !
发表于 2015-7-19 17:15:55 | 显示全部楼层
台湾哥  
发表于 2015-7-19 17:25:42 | 显示全部楼层
请教MPU9255跟之前MPU9250有什么区别?我还以为只能用IIC,有点郁闷呢
发表于 2015-7-19 17:29:32 | 显示全部楼层
https://code.google.com/p/open-headtracker/downloads/list
这里他有个校准的工具,他用的是6050,如果楼主能够移植过来就太好了
 楼主| 发表于 2015-7-19 18:28:23 | 显示全部楼层
Timingtime 发表于 2015-7-19 17:25
请教MPU9255跟之前MPU9250有什么区别?我还以为只能用IIC,有点郁闷呢

似乎只差在 AAR 庫,但好像只支援 ATMEL 的晶片,詳細可以看官網說明。

MPU9150 只支援 I2C,MPU9250 就支援 SPI / I2C 了,SPI 比 I2C 有更高的傳輸速度,
可以減少傳輸占用的時間,增加解算算法的更新頻率。
 楼主| 发表于 2015-7-19 18:30:10 | 显示全部楼层
Timingtime 发表于 2015-7-19 17:29
https://code.google.com/p/open-headtracker/downloads/list
这里他有个校准的工具,他用的是6050,如果楼 ...

最近在重新做感測器的校正,有時間看看。
发表于 2015-7-19 21:32:39 | 显示全部楼层
你好,今天看了一下关于MPU9250的数据手册,有这么几个疑问:

1、假使我使用I2C通信方式,并且我要读取9个轴的数据,是不是在配置的时候,先将芯片配置为Pass-Through Mode模式,使用单片机完成对磁力计的配置,然后转为I2C Master Mode,进而完成相应的配置,通过单片机对ACC,GYRO,以及MAG寄存器读数据?
2、如果1可行,那么,在我SPI方式时,如何对磁力计进行配置?难道要先将这两个引脚模拟成I2C,配置完成后再配置为SPI,对其进行操作,读写?或者说在SPI方式下是不需要对磁力计进行配置(我看手册上没有写,粗略介绍了一下SPI方式),直接可以对各个寄存器读取数据?

 楼主| 发表于 2015-7-19 22:16:38 | 显示全部楼层
本帖最后由 john800422 于 2015-7-19 22:17 编辑
沉默胜过白金 发表于 2015-7-19 21:32
你好,今天看了一下关于MPU9250的数据手册,有这么几个疑问:

1、假使我使用I2C通信方式,并且我要读取9个 ...


I2C 讀取 MPU9250 的 AK8963 有兩種方法:
1。Pass-Through Mode,將 Auxiliary I2C 直接與 Primary I2C 連接,也就是說你可以將 MPU9250 看成掛在同一個 I2C 上的 MPU6500 和 AK8963。
2。I2C Master Mode,將 Auxiliary I2C 與 Primary I2C 斷開,透過 I2C_SLVx_ADDR、I2C_SLVx_REG、I2C_SLVx_CTRL 等寄存器來讀寫 AK8963。

SPI 讀取 MPU9250 的 AK8963 就只適用上述的 I2C Master Mode
透過 SPI 設定 MPU6500 上的 I2C_SLVx_ADDR、I2C_SLVx_REG、I2C_SLVx_CTRL ... 寄存器,來讓 MPU6500 自動透過 Auxiliary I2C 讀取 AK8963,不需要再模擬 I2C,詳細設定可以參考頂樓的程序。
发表于 2015-7-21 09:26:12 | 显示全部楼层
john800422 发表于 2015-7-19 18:30
最近在重新做感測器的校正,有時間看看。

好的,谢了。
其他六轴倒是没有问题。磁力计校准有些看不懂。磁力计才8Hz感觉比较弱啊。。我是拿来校正方向的,不知道有没有影响
 楼主| 发表于 2015-7-21 19:39:37 | 显示全部楼层
Timingtime 发表于 2015-7-21 09:26
好的,谢了。
其他六轴倒是没有问题。磁力计校准有些看不懂。磁力计才8Hz感觉比较弱啊。。我是拿来校正方 ...

AK8963 Continuous measurement mode 2 可以達到 100Hz,對於航向來說已經足夠了,
磁力計的校正可以參考我之前的帖子,橢圓擬合,針對2維平面做校正,
若需要校正到 3 維空間的話,論壇裡搜橢球擬合應該有。
发表于 2015-7-21 22:53:19 | 显示全部楼层
john800422 发表于 2015-7-21 19:39
AK8963 Continuous measurement mode 2 可以達到 100Hz,對於航向來說已經足夠了,
磁力計的校正可以參考 ...

感谢
测试了下MPU9250_Write_Reg(AK8963_CNTL1, 0x06);  
陀螺仪开始飘得很厉害,Z轴数值差了260多,一直在转,校准后每秒飘一点,好点,但是还漂移
大概是3-8,无法接受,可以感觉出来。所以没办法这么用,只能用8Hz。这一点真的很奇怪,弄了一晚上,不明所以。
 楼主| 发表于 2015-7-22 03:18:18 | 显示全部楼层
Timingtime 发表于 2015-7-21 22:53
感谢
测试了下MPU9250_Write_Reg(AK8963_CNTL1, 0x06);  
陀螺仪开始飘得很厉害,Z轴数值差了260多,一直 ...

不太懂你說的 ...
MPU9250_Write_Reg(AK8963_CNTL1, 0x06) 與陀螺儀輸出有甚麼關係?
发表于 2015-7-22 08:58:46 | 显示全部楼层
本帖最后由 Timingtime 于 2015-7-22 09:14 编辑
john800422 发表于 2015-7-22 03:18
不太懂你說的 ...
MPU9250_Write_Reg(AK8963_CNTL1, 0x06) 與陀螺儀輸出有甚麼關係?


不知道,我也纳闷。。很古怪。
我是用1KHz的
发表于 2015-7-26 20:10:51 | 显示全部楼层
Timingtime 发表于 2015-7-22 08:58
不知道,我也纳闷。。很古怪。
我是用1KHz的

搞错了,应该给AK8963发,抱歉。
发表于 2015-7-27 00:39:09 | 显示全部楼层
1000Hz没问题,太帅。
请教怎么跑8000Hz?
发表于 2015-7-28 18:17:26 | 显示全部楼层
MPU9255 MPU9250有啥区别呢
发表于 2015-8-2 19:17:23 | 显示全部楼层
你好,我现在有个疑问,为什么在读 暂存器的时候, 每个地址,都和 0x80 做了 或运算。

  SPI_RW(SPIx, 0x80 | ReadAddr);  ?
 楼主| 发表于 2015-8-2 22:29:59 | 显示全部楼层
沉默胜过白金 发表于 2015-8-2 19:17
你好,我现在有个疑问,为什么在读 暂存器的时候, 每个地址,都和 0x80 做了 或运算。

  SPI_RW(SPIx, 0x ...

詳細自行參考 MPU9255 或 MPU9250 datasheet, SPI 協議部分。
发表于 2015-8-25 16:05:51 | 显示全部楼层
请问哪位仁兄有MPU9255 (6555)的寄存器资料,谢谢!
发表于 2015-8-25 22:03:22 | 显示全部楼层
有空搞个试试
发表于 2016-5-18 00:28:24 | 显示全部楼层
在获取地磁数据的过程中,相同的程序有时烧录后成功读取到地磁ID 0x48,可有时烧录后却失败。
目前为止只成功过三次,很奇怪,不知道什么原因??
我用的是MPU9250
发表于 2016-5-18 00:32:45 | 显示全部楼层
        初始化程序按照您的移植,9250和9255寄存器地址都一样
        MPU9250_Write_Reg(PWR_MGMT_1,0X80);         
        MPU9250_Write_Reg(PWR_MGMT_1,0X01);         
        MPU9250_Write_Reg(USER_CTRL,0X30);                
        MPU9250_Write_Reg(PWR_MGMT_2,0X00);       
        MPU9250_Write_Reg(SMPLRT_DIV,0x00);               
//        MPU9250_Write_Reg(CONFIG,0X06);                               
        MPU9250_Write_Reg(CONFIG,0X03);                       
        MPU9250_Write_Reg(GYRO_CONFIG,0X18);
        MPU9250_Write_Reg(ACCEL_CONFIG,0x18);
        MPU9250_Write_Reg(ACCEL_CONFIG2,0);
       
       
        ret = MPU9250_Read_Regs(WHO_AM_I, 1, &id);
        if(ret<0) return ret;
        if(id!=0x71)
                return -1;
        osDelay(1);
        id = MPU9250_Mag_ReadReg(AK8963_WIA);
        if(ret<0) return ret;
        if(id!=0x48)
                return -1;
        osDelay(1);

        MPU9255_Mag_WriteReg(AK8963_CNTL2,0x01);
        osDelay(10);
        MPU9255_Mag_WriteReg(AK8963_CNTL1,0x16);
        osDelay(10);
        MPU9250_Write_Reg(MPU9250_I2C_SLV0_REG,AK8963_ST1);
        MPU9250_Write_Reg(MPU9250_I2C_SLV0_ADDR,AK8963_I2C_ADDR        |        0x80);
        MPU9250_Write_Reg(MPU9250_I2C_SLV0_CTRL,0x80 | 8);
发表于 2016-5-20 17:58:52 | 显示全部楼层
使用MPU9255成功读出了9轴的数据,但是后续加入DMP后反而无法读取磁力计的信号,不知道大家遇到这种情况没有?
发表于 2018-11-30 04:55:00 | 显示全部楼层
谢谢分享!美丽的台湾朋友
发表于 2018-11-30 22:04:30 | 显示全部楼层
恋芜 发表于 2018-11-30 04:55
谢谢分享!美丽的台湾朋友

Chinese Taipei!
友情提示:标题不合格、重复发帖,将会被封锁ID。详情请参考:论坛通告:封锁ID、获得注册邀请码、恢复被封ID、投诉必读
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|阿莫电子论坛(原ourAVR/ourDEV) ( 公安备案:44190002001997(交互式论坛) 工信部备案:粤ICP备09047143号 )

GMT+8, 2019-1-19 09:20

阿莫电子论坛, 原"中国电子开发网"

© 2004-2018 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表