I am interfacing an MPU-9250 to an STM8S207 microcontroller. The MPU-9250 is accessed via 400kHz I2C. I have no isses with getting measurement data from the temperature, gyro and accelerometer, but can not get the built-in AK8963 magnetometer measurement results. I can read out the AK8963 device ID correctly, looks like the Fuse-ROM calibration values are correct, but when I program the 0x0A (CNTL1) mode register to 0x01 or 0x02 (single or 8Hz measurements), the DRDY flag never transitions to 1, and the CNTL1 register reads back 0x03, which is a reserved value.

Any ideas what I am missing?

The initialization sequence I'm using is below, after configure_imu() is called, reg 0x0A from the AK8963 reads back as 0x03.

void configure_imu()
u8 status, mag_mode, mag_sense[3];
i2c_write_byte(MPU_I2CAddress, 27,GYRO_FULL_SCALE_2000_DPS); // Configure gyroscope range  
i2c_write_byte(MPU_I2CAddress, 28,ACC_FULL_SCALE_16_G); // Configure accelerometers range  
i2c_write_byte(MPU_I2CAddress, 0x37,0x02); // Set bypass mode for external I2C master connection

i2c_write_byte(MPU_I2CAddress, 0x6B,0x01); // Clock source is PLLGYROZ
i2c_write_byte(MPU_I2CAddress, 0x19,0x04); // Set SMPLRT_DIV to 0x04; this gives a 200 Hz sample rate when using the DLPF
i2c_write_byte(MPU_I2CAddress, 0x1A,0x03); // 42 Hz LPF
i2c_write_byte(MPU_I2CAddress, 0x6A,0x01); // Disable master mode and clear all signal paths
//i2c_write_byte(MPU_I2CAddress, 0x37,0x32); // Interrupts pin stays high until cleared, cleared on any read, I2C bypass
//i2c_write_byte(MPU_I2CAddress, 0x38,0x01);                                        // Data ready interrupt enabled 

status = i2c_read(MAG_I2CAddress, 0x00, I2C_rx_rd_ptr++, 1);
if (status==0) return;  
i2c_write_byte(MAG_I2CAddress, 0x0B,0x01);  // Software Reset Magnetometer
i2c_write_byte(MAG_I2CAddress, 0x0B,0x00);  // Deassert Software Reset Magnetometer
do { status = i2c_read(MAG_I2CAddress, 0x0A, &mag_mode, 1); }
    while ((status==1) && (mag_mode>0));
i2c_write_byte(MAG_I2CAddress, 0x0A,0x0F);  // Enter Fuse-ROM mode
i2c_read(MAG_I2CAddress, 0x10, mag_sense, 3);   // Read the x-, y-, and z-axis calibration values
i2c_write_byte(MAG_I2CAddress, 0x0A,0x00);  // Enter power-down mode
i2c_write_byte(MAG_I2CAddress, 0x0A,0x02);       // Magnetometer to enter continuous 8Hz measurement mode


Thank you all for the comments! In the next version of the board I replaced the MPU-9250, however widespread it is, with a Bosch BMO055. It's little help if you are already committed to MPU9150/9250, but if board re-spin is still an option for you, I highly recommend the Bosch part. It has the Sensor Fusion engine built in, generating the acceleration / heading / quarternion information right outside the box without any MCU post-processing - which is actually what I needed.

  • \$\begingroup\$ Do you need to set up pass-through mode? "Pass-Through mode is also used to access the AK8963 magnetometer directly from the host. In this configuration the slave address for the AK8963 is 0X0C or 12 decimal." \$\endgroup\$ Jan 9, 2016 at 1:24
  • \$\begingroup\$ ThanksKrunal for you comment. Pass-through mode is set up, and I can correctly read the WHOAMI hw ID register of hte AK8963. I can also read factory calibration values from the fuse-rom, and read the correct MODE value (0x00) from (0x0A) after reset. However, once I write 0x01 or 0x02 to address 0x0A, instructing the magnetometer to provide a measurement sample, the data never becomes ready, and 0x0A reads back as 0x03. \$\endgroup\$
    – maszoka
    Jan 10, 2016 at 4:04

1 Answer 1


In case you still need the help, Have you tried reading the ST2 register every time also? There is a sentence in section 8.3.5. of the data sheet "Therefore, when any of measurement data is read, be sure to read ST2 register at the end." I also had problems with the continuous modes, so I switched to triggered mode.

The two things solved my data problems with this chip.

Best of luck. Tom


Not the answer you're looking for? Browse other questions tagged or ask your own question.