john800422 发表于 2015-7-18 14:04:17

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

本帖最后由 john800422 于 2015-7-18 14:17 编辑

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

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

#define MPU6555_InitRegNum 11
#define AK8963_InitRegNum2
uint8_t MPU9255_Init( MPU_InitTypeDef *MPUx )
{
uint8_t status = ERROR;
uint8_t MPU6555_InitData = {
    {0x80, MPU6555_PWR_MGMT_1},   // Reset Device
    {0x01, MPU6555_PWR_MGMT_1},   // Clock Source
    {0x30, MPU6555_USER_CTRL},      // Set I2C_MST_EN, I2C_IF_DIS
    {0x00, MPU6555_PWR_MGMT_2},   // Enable Acc & Gyro
    {0x07, MPU6555_CONFIG},         // DLPF_CFG = 111;
    {0x18, MPU6555_GYRO_CONFIG},    // +-2000dps
    {0x08, MPU6555_ACCEL_CONFIG},   // +-4G
    {0x48, MPU6555_ACCEL_CONFIG_2}, // Set Acc Data Rates
    {0x10, MPU6555_INT_PIN_CFG},    // Set INT_ANYRD_2CLEAR
    {0x10, MPU6555_INT_ENABLE},   //
    {0x4D, MPU6555_I2C_MST_CTRL},   // I2C Speed 400 kHz
};
uint8_t AK8963_InitData = {
    {0x01, AK8963_CNTL2},         // Reset Device
    {0x06, AK8963_CNTL1},         // Continuous measurement mode 2
};

MPU6555_InitData = MPUx->MPU_Gyr_FullScale;       // MPU6555_GYRO_CONFIG
MPU6555_InitData = MPUx->MPU_Gyr_LowPassFilter;   // MPU6555_CONFIG
MPU6555_InitData = MPUx->MPU_Acc_FullScale;       // MPU6555_ACCEL_CONFIG
MPU6555_InitData = MPUx->MPU_Acc_LowPassFilter;   // MPU6555_ACCEL_CONFIG_2
AK8963_InitData |= MPUx->MPU_Mag_FullScale;

for(uint8_t i = 0; i < MPU6555_InitRegNum; i++) {
    MPU9255_WriteReg(MPU6555_InitData, MPU6555_InitData);
    Delay_1ms(1);
}

status = MPU9255_Check();
if(status != SUCCESS)
    return ERROR;

Delay_10ms(1);

#ifdef _USE_MAG_AK8963
for(uint8_t i = 0; i < AK8963_InitRegNum; i++) {
    MPU9255_Mag_WriteReg(AK8963_InitData, AK8963_InitData);
    Delay_10ms(1);
}

        MPU9255_WriteReg(MPU6555_I2C_SLV0_REG, AK8963_ST1);
        MPU9255_WriteReg(MPU6555_I2C_SLV0_ADDR, AK8963_I2C_ADDR | 0x80);
        MPU9255_WriteReg(MPU6555_I2C_SLV0_CTRL, 0x80 | 8);
#endif

MPU9255_SetSpeed(SPIx_SPEED_HIGH);
Delay_10ms(1);

return SUCCESS;
}

void MPU9255_getData( int16_t *dataIMU )
{
uint8_t tmpRead = {0};

#ifdef _USE_MAG_AK8963
MPU9255_ReadRegs(MPU6555_ACCEL_XOUT_H, tmpRead, 22);
#else
MPU9255_ReadRegs(MPU6555_ACCEL_XOUT_H, tmpRead, 14);
#endif

dataIMU = (Byte16(int16_t, tmpRead,tmpRead));    // Temp
dataIMU = (Byte16(int16_t, tmpRead,tmpRead));    // Acc.X
dataIMU = (Byte16(int16_t, tmpRead,tmpRead));    // Acc.Y
dataIMU = (Byte16(int16_t, tmpRead,tmpRead));    // Acc.Z
dataIMU = (Byte16(int16_t, tmpRead,tmpRead));    // Gyr.X
dataIMU = (Byte16(int16_t, tmpRead, tmpRead));   // Gyr.Y
dataIMU = (Byte16(int16_t, tmpRead, tmpRead));   // Gyr.Z
#ifdef _USE_MAG_AK8963
dataIMU = (Byte16(int16_t, tmpRead, tmpRead));   // Mag.X
dataIMU = (Byte16(int16_t, tmpRead, tmpRead));   // Mag.Y
dataIMU = (Byte16(int16_t, tmpRead, tmpRead));   // Mag.Z
#endif
}

void SysTick_Handler( void )
{
int16_t IMU_Buf = {0};
int16_t readData = {0};

LED_R_Toggle;
MPU9255_getData(readData);
readData = readData - Bx;    // Acc.X
readData = readData - By;    // Acc.Y
readData = readData - Bz;    // Acc.Z

IMU_Buf = (int16_t)(readData * Sxx + readData * Sxy + readData * Sxz);// Acc.X
IMU_Buf = (int16_t)(readData * Syx + readData * Syy + readData * Syz);// Acc.Y
IMU_Buf = (int16_t)(readData * Szx + readData * Szy + readData * Szz);// Acc.Z
IMU_Buf = readData * MPU9255G_2000dps;                                        // Gyr.X
IMU_Buf = readData * MPU9255G_2000dps;                                        // Gyr.Y
IMU_Buf = readData * MPU9255G_2000dps;                                        // Gyr.Z
IMU_Buf = readData * MPU9255M_4800uT;                                       // Mag.X
IMU_Buf = readData * MPU9255M_4800uT;                                       // Mag.Y
IMU_Buf = readData * MPU9255M_4800uT;                                       // Mag.Z
IMU_Buf = readData * MPU9255T_85degC;                                       // temp

Serial_sendDataMATLAB(IMU_Buf, 10);
}

Shampoo 发表于 2015-7-18 14:17:45

首页一看繁体字 就知道是楼主!

沉默胜过白金 发表于 2015-7-18 14:52:53

芯片在哪买的?

john800422 发表于 2015-7-18 19:22:05

Shampoo 发表于 2015-7-18 14:17
首页一看繁体字 就知道是楼主!

感謝支持{:lol:}

john800422 发表于 2015-7-18 19:26:52

沉默胜过白金 发表于 2015-7-18 14:52
芯片在哪买的?

目前是用模塊,芯片的話X寶應該可以買到。

沉默胜过白金 发表于 2015-7-18 21:19:58

我在搞 MPU9250,能不能将你的原理图贴出来参考下。

john800422 发表于 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 !{:smile:}

309579471 发表于 2015-7-19 17:15:55

台湾哥{:lol:}

Timingtime 发表于 2015-7-19 17:25:42

请教MPU9255跟之前MPU9250有什么区别?我还以为只能用IIC,有点郁闷呢

Timingtime 发表于 2015-7-19 17:29:32

https://code.google.com/p/open-headtracker/downloads/list
这里他有个校准的工具,他用的是6050,如果楼主能够移植过来就太好了

john800422 发表于 2015-7-19 18:28:23

Timingtime 发表于 2015-7-19 17:25
请教MPU9255跟之前MPU9250有什么区别?我还以为只能用IIC,有点郁闷呢

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

MPU9150 只支援 I2C,MPU9250 就支援 SPI / I2C 了,SPI 比 I2C 有更高的傳輸速度,
可以減少傳輸占用的時間,增加解算算法的更新頻率。

john800422 发表于 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方式),直接可以对各个寄存器读取数据?

john800422 发表于 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,詳細設定可以參考頂樓的程序。

Timingtime 发表于 2015-7-21 09:26:12

john800422 发表于 2015-7-19 18:30
最近在重新做感測器的校正,有時間看看。

好的,谢了。
其他六轴倒是没有问题。磁力计校准有些看不懂。磁力计才8Hz感觉比较弱啊。。我是拿来校正方向的,不知道有没有影响

john800422 发表于 2015-7-21 19:39:37

Timingtime 发表于 2015-7-21 09:26
好的,谢了。
其他六轴倒是没有问题。磁力计校准有些看不懂。磁力计才8Hz感觉比较弱啊。。我是拿来校正方 ...

AK8963 Continuous measurement mode 2 可以達到 100Hz,對於航向來說已經足夠了,
磁力計的校正可以參考我之前的帖子,橢圓擬合,針對2維平面做校正,
若需要校正到 3 維空間的話,論壇裡搜橢球擬合應該有。

Timingtime 发表于 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。这一点真的很奇怪,弄了一晚上,不明所以。

john800422 发表于 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) 與陀螺儀輸出有甚麼關係?

Timingtime 发表于 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的

Timingtime 发表于 2015-7-26 20:10:51

Timingtime 发表于 2015-7-22 08:58
不知道,我也纳闷。。很古怪。
我是用1KHz的

搞错了,应该给AK8963发,抱歉。

Timingtime 发表于 2015-7-27 00:39:09

1000Hz没问题,太帅。
请教怎么跑8000Hz?

xiaowenshao 发表于 2015-7-28 18:17:26

MPU9255 MPU9250有啥区别呢

沉默胜过白金 发表于 2015-8-2 19:17:23

你好,我现在有个疑问,为什么在读 暂存器的时候, 每个地址,都和 0x80 做了 或运算。

SPI_RW(SPIx, 0x80 | ReadAddr);?

john800422 发表于 2015-8-2 22:29:59

沉默胜过白金 发表于 2015-8-2 19:17
你好,我现在有个疑问,为什么在读 暂存器的时候, 每个地址,都和 0x80 做了 或运算。

SPI_RW(SPIx, 0x ...

詳細自行參考 MPU9255 或 MPU9250 datasheet, SPI 協議部分。

eva_yang 发表于 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);

NR4ein 发表于 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!
页: [1]
查看完整版本: 分享自己調通的 MPU9255 SPI 讀取 AK8963 代碼