将磁力计或者三轴加速度计通过IIC接到R2的
时间:10-02
整理:3721RD
点击:
怎样将将磁力计或者三轴加速度计通过IIC接到R2的?
Hi,
可以参照Mpu9250例子。
/*
* Copyright (c) 2015-2016, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** ============================================================================
* @file SensorMpu9250.c
*
* @brief Driver for the InvenSense MPU9250 Motion Processing Unit.
* ============================================================================
*/
/* -----------------------------------------------------------------------------
* Includes
* ------------------------------------------------------------------------------
*/
#include "Board.h"
#include "SensorMpu9250.h"
#include "SensorOpt3001.h" // For reset of I2C bus
#include "SensorUtil.h"
#include "SensorI2C.h"
/* -----------------------------------------------------------------------------
* Constants and macros
* ------------------------------------------------------------------------------
*/
// Registers
#define SELF_TEST_X_GYRO 0x00 // R/W
#define SELF_TEST_Y_GYRO 0x01 // R/W
#define SELF_TEST_Z_GYRO 0x02 // R/W
#define SELF_TEST_X_ACCEL 0x0D // R/W
#define SELF_TEST_Z_ACCEL 0x0E // R/W
#define SELF_TEST_Y_ACCEL 0x0F // R/W
#define XG_OFFSET_H 0x13 // R/W
#define XG_OFFSET_L 0x14 // R/W
#define YG_OFFSET_H 0x15 // R/W
#define YG_OFFSET_L 0x16 // R/W
#define ZG_OFFSET_H 0x17 // R/W
#define ZG_OFFSET_L 0x18 // R/W
#define SMPLRT_div 0x19 // R/W
#define CONFIG 0x1A // R/W
#define GYRO_CONFIG 0x1B // R/W
#define ACCEL_CONFIG 0x1C // R/W
#define ACCEL_CONFIG_2 0x1D // R/W
#define LP_ACCEL_ODR 0x1E // R/W
#define WOM_THR 0x1F // R/W
#define FIFO_EN 0x23 // R/W
// .. registers 0x24 - 0x36 are not applicable to the SensorTag HW configuration
#define INT_PIN_CFG 0x37 // R/W
#define INT_ENABLE 0x38 // R/W
#define INT_STATUS 0x3A // R
#define ACCEL_XOUT_H 0x3B // R
#define ACCEL_XOUT_L 0x3C // R
#define ACCEL_YOUT_H 0x3D // R
#define ACCEL_YOUT_L 0x3E // R
#define ACCEL_ZOUT_H 0x3F // R
#define ACCEL_ZOUT_L 0x40 // R
#define TEMP_OUT_H 0x41 // R
#define TEMP_OUT_L 0x42 // R
#define GYRO_XOUT_H 0x43 // R
#define GYRO_XOUT_L 0x44 // R
#define GYRO_YOUT_H 0x45 // R
#define GYRO_YOUT_L 0x46 // R
#define GYRO_ZOUT_H 0x47 // R
#define GYRO_ZOUT_L 0x48 // R
// .. registers 0x49 - 0x60 are not applicable to the SensorTag HW configuration
// .. registers 0x63 - 0x67 are not applicable to the SensorTag HW configuration
#define SIGNAL_PATH_RESET 0x68 // R/W
#define ACCEL_INTEL_CTRL 0x69 // R/W
#define USER_CTRL 0x6A // R/W
#define PWR_MGMT_1 0x6B // R/W
#define PWR_MGMT_2 0x6C // R/W
#define FIFO_COUNT_H 0x72 // R/W
#define FIFO_COUNT_L 0x73 // R/W
#define FIFO_R_W 0x74 // R/W
#define WHO_AM_I 0x75 // R/W
// Masks is mpuConfig valiable
#define ACC_CONFIG_MASK 0x38
#define GYRO_CONFIG_MASK 0x07
// Values PWR_MGMT_1
#define MPU_SLEEP 0x4F // Sleep + stop all clocks
#define MPU_WAKE_UP 0x09 // Disable temp. + intern osc
// Values PWR_MGMT_2
#define ALL_AXES 0x3F
#define GYRO_AXES 0x07
#define ACC_AXES 0x38
// Data sizes
#define DATA_SIZE 6
// Output data rates
#define INV_LPA_0_3125HZ 0
#define INV_LPA_0_625HZ 1
#define INV_LPA_1_25HZ 2
#define INV_LPA_2_5HZ 3
#define INV_LPA_5HZ 4
#define INV_LPA_10HZ 5
#define INV_LPA_20HZ 6
#define INV_LPA_40HZ 7
#define INV_LPA_80HZ 8
#define INV_LPA_160HZ 9
#define INV_LPA_320HZ 10
#define INV_LPA_640HZ 11
#define INV_LPA_STOPPED 255
// Bit values
#define BIT_ANY_RD_CLR 0x10
#define BIT_RAW_RDY_EN 0x01
#define BIT_WOM_EN 0x40
#define BIT_LPA_CYCLE 0x20
#define BIT_STBY_XA 0x20
#define BIT_STBY_YA 0x10
#define BIT_STBY_ZA 0x08
#define BIT_STBY_XG 0x04
#define BIT_STBY_YG 0x02
#define BIT_STBY_ZG 0x01
#define BIT_STBY_XYZA (BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA)
#define BIT_STBY_XYZG (BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)
// User control register
#define BIT_LATCH_EN 0x20
#define BIT_ACTL 0x80
// INT Pin / Bypass Enable Configuration
#define BIT_BYPASS_EN 0x02
#define BIT_AUX_IF_EN 0x20
// Magnetometer registers
#define MAG_WHO_AM_I 0x00 // Should return 0x48
#define MAG_INFO 0x01
#define MAG_ST1 0x02 // Data ready status: bit 0
#define MAG_XOUT_L 0x03 // Data array
#define MAG_XOUT_H 0x04
#define MAG_YOUT_L 0x05
#define MAG_YOUT_H 0x06
#define MAG_ZOUT_L 0x07
#define MAG_ZOUT_H 0x08
#define MAG_ST2 0x09 // Overflow(bit 3), read err(bit 2)
#define MAG_CNTL1 0x0A // Mode bits 3:0, resolution bit 4
#define MAG_CNTL2 0x0B // System reset, bit 0
#define MAG_ASTC 0x0C // Self test control
#define MAG_I2CDIS 0x0F // I2C disable
#define MAG_ASAX 0x10 // x-axis sensitivity adjustment
#define MAG_ASAY 0x11 // y-axis sensitivity adjustment
#define MAG_ASAZ 0x12 // z-axis sensitivity adjustment
#define MAG_DEVICE_ID 0x48
// Mode
#define MAG_MODE_OFF 0x00
#define MAG_MODE_SINGLE 0x01
#define MAG_MODE_CONT1 0x02
#define MAG_MODE_CONT2 0x06
#define MAG_MODE_FUSE 0x0F
// Resolution
#define MFS_14BITS 0 // 0.6 mG per LSB
#define MFS_16BITS 1 // 0.15 mG per LSB
// Sensor selection/de-selection
#define SENSOR_SELECT() SensorI2C_select(SENSOR_I2C_1,Board_MPU9250_ADDR)
#define SENSOR_SELECT_MAG() SensorI2C_select(SENSOR_I2C_1,Board_MPU9250_MAG_ADDR)
#define SENSOR_DESELECT() SensorI2C_deselect()
/* -----------------------------------------------------------------------------
* Local Functions
* ------------------------------------------------------------------------------
*/
static void sensorMpuSleep(void);
static void sensorMpu9250WakeUp(void);
static void sensorMpu9250SelectAxes(void);
static void SensorMpu9250_Callback(PIN_Handle handle, PIN_Id pinId);
static void sensorMagInit(void);
static void sensorMagEnable(bool);
static bool sensorMpu9250SetBypass(void);
/* -----------------------------------------------------------------------------
* Local Variables
* ------------------------------------------------------------------------------
*/
static uint8_t mpuConfig;
static uint8_t magStatus;
static uint8_t accRange;
static uint8_t accRangeReg;
static uint8_t val;
// Magnetometer calibration
static int16_t calX;
static int16_t calY;
static int16_t calZ;
// Magnetometer control
static uint8_t scale = MFS_16BITS; // 16 bit resolution
static uint8_t mode = MAG_MODE_SINGLE; // Operating mode
// Pins that are used by the MPU9250
static PIN_Config MpuPinTable[] =
{
Board_MPU_INT | PIN_INPUT_EN | PIN_PULLDOWN | PIN_IRQ_DIS | PIN_HYSTERESIS,
Board_MPU_POWER | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_TERMINATE
};
static PIN_State pinGpioState;
static PIN_Handle hMpuPin;
// The application may register a callback to handle interrupts
static SensorMpu9250CallbackFn_t isrCallbackFn = NULL;
/* -----------------------------------------------------------------------------
* Public functions
* ------------------------------------------------------------------------------
*/
/*******************************************************************************
* @fn SensorMpu9250_powerOn
*
* @brief This function turns on the power supply to MPU9250
*
* @return none
*/
void SensorMpu9250_powerOn(void)
{
// Turn on power supply
PIN_setOutputValue(hMpuPin,Board_MPU_POWER, Board_MPU_POWER_ON);
DELAY_MS(100);
SensorMpu9250_reset();
}
/*******************************************************************************
* @fn SensorMpu9250_powerOff
*
* @brief This function turns off the power supply to MPU9250
*
* @return none
*/
void SensorMpu9250_powerOff(void)
{
// Make sure pin interrupt is disabled
PIN_setInterrupt(hMpuPin, PIN_ID(Board_MPU_INT)|PIN_IRQ_DIS);
// Turn off power supply
PIN_setOutputValue(hMpuPin,Board_MPU_POWER, Board_MPU_POWER_OFF);
// Force an access on I2C bus #0 (sets the I2C lines to a defined state)
SensorOpt3001_test();
}
/*******************************************************************************
* @fn SensorMpu9250_powerIsOn
*
* @brief Return 'true' if MPU power is on
*
* @return state of MPU power
*/
bool SensorMpu9250_powerIsOn(void)
{
return PIN_getOutputValue(Board_MPU_POWER) == Board_MPU_POWER_ON;
}
/*******************************************************************************
* @fn SensorMpu9250_registerCallback
*
* @brief Register a call-back for interrupt processing
*
* @return none
*/
void SensorMpu9250_registerCallback(SensorMpu9250CallbackFn_t pfn)
{
isrCallbackFn = pfn;
}
/*******************************************************************************
* @fn SensorMpu9250_init
*
* @brief This function initializes the MPU abstraction layer.
*
* @return True if success
*/
bool SensorMpu9250_init(void)
{
// Pins used by MPU
hMpuPin = PIN_open(&pinGpioState, MpuPinTable);
// Register MPU interrupt
PIN_registerIntCb(hMpuPin, SensorMpu9250_Callback);
// Application callback initially NULL
isrCallbackFn = NULL;
return SensorMpu9250_reset();
}
/*******************************************************************************
* @fn SensorMpu9250_reset
*
* @brief This function resets the MPU
*
* @return True if success
*/
bool SensorMpu9250_reset(void)
{
bool ret;
// Make sure pin interrupt is disabled
PIN_setInterrupt(hMpuPin, PIN_ID(Board_MPU_INT)|PIN_IRQ_DIS);
accRange = ACC_RANGE_INVALID;
mpuConfig = 0; // All axes off
magStatus = 0;
if (!SENSOR_SELECT())
{
return false;
}
// Device reset
val = 0x80;
SensorI2C_writeReg(PWR_MGMT_1, &val, 1);
SENSOR_DESELECT();
DELAY_MS(100);
ret = SensorMpu9250_test();
if (ret)
{
// Initial configuration
SensorMpu9250_accSetRange(ACC_RANGE_8G);
sensorMagInit();
// Power save
sensorMpuSleep();
}
return ret;
}
/*******************************************************************************
* @fn SensorMpu9250_enableWom
*
* @brief Enable Wake On Motion functionality
*
* @param threshold - wake-up trigger threshold (unit: 4 mg, max 1020mg)
*
* @return True if success
*/
bool SensorMpu9250_enableWom(uint8_t threshold)
{
ST_ASSERT(SensorMpu9250_powerIsOn());
if (!SENSOR_SELECT())
{
return false;
}
// Make sure accelerometer is running
val = 0x09;
ST_ASSERT(SensorI2C_writeReg(PWR_MGMT_1, &val, 1));
// Enable accelerometer, disable gyro
val = 0x07;
ST_ASSERT(SensorI2C_writeReg(PWR_MGMT_2, &val, 1));
// Set Accel LPF setting to 184 Hz Bandwidth
val = 0x01;
ST_ASSERT(SensorI2C_writeReg(ACCEL_CONFIG_2, &val, 1));
// Enable Motion Interrupt
val = BIT_WOM_EN;
ST_ASSERT(SensorI2C_writeReg(INT_ENABLE, &val, 1));
// Enable Accel Hardware Intelligence
val = 0xC0;
ST_ASSERT(SensorI2C_writeReg(ACCEL_INTEL_CTRL, &val, 1));
// Set Motion Threshold
val = threshold;
ST_ASSERT(SensorI2C_writeReg(WOM_THR, &val, 1));
// Set Frequency of Wake-up
val = INV_LPA_20HZ;
ST_ASSERT(SensorI2C_writeReg(LP_ACCEL_ODR, &val, 1));
// Enable Cycle Mode (Accel Low Power Mode)
val = 0x29;
ST_ASSERT(SensorI2C_writeReg(PWR_MGMT_1, &val, 1));
// Select the current range
ST_ASSERT(SensorI2C_writeReg(ACCEL_CONFIG, &accRangeReg, 1));
// Clear interrupt
SensorI2C_readReg(INT_STATUS,&val,1);
SENSOR_DESELECT();
mpuConfig = 0;
// Enable pin for wake-on-motion interrupt
PIN_setInterrupt(hMpuPin, PIN_ID(Board_MPU_INT)|PIN_IRQ_POSEDGE);
return true;
}
/*******************************************************************************
* @fn SensorMpu9250_irqStatus
*
* @brief Check whether a data or wake on motion interrupt has occurred
*
* @return Return interrupt status
*/
uint8_t SensorMpu9250_irqStatus(void)
{
uint8_t intStatus;
intStatus = 0;
ST_ASSERT(SensorMpu9250_powerIsOn());
if (SENSOR_SELECT())
{
if (!SensorI2C_readReg(INT_STATUS,&intStatus,1))
{
intStatus = 0;
}
SENSOR_DESELECT();
}
return intStatus;
}
/*******************************************************************************
* @fn SensorMpu9250_enable
*
* @brief Enable accelerometer readout
*
* @param Axes: Gyro bitmap [0..2], X = 1, Y = 2, Z = 4. 0 = gyro off
* @ Acc bitmap [3..5], X = 8, Y = 16, Z = 32. 0 = accelerometer off
* MPU bit [6], all axes
*
* @return None
*/
void SensorMpu9250_enable(uint16_t axes)
{
ST_ASSERT_V(SensorMpu9250_powerIsOn());
if (mpuConfig == 0 && axes != 0)
{
// Wake up the sensor if it was off
sensorMpu9250WakeUp();
}
mpuConfig = axes;
if (mpuConfig != 0)
{
// Enable gyro + accelerometer + magnetometer readout
sensorMpu9250SelectAxes();
}
else if (mpuConfig == 0)
{
sensorMpuSleep();
}
}
/*******************************************************************************
* @fn SensorMpu9250_accSetRange
*
* @brief Set the range of the accelerometer
*
* @param newRange: ACC_RANGE_2G, ACC_RANGE_4G, ACC_RANGE_8G, ACC_RANGE_16G
*
* @return true if write succeeded
*/
bool SensorMpu9250_accSetRange(uint8_t newRange)
{
bool success;
if (newRange == accRange)
{
return true;
}
ST_ASSERT(SensorMpu9250_powerIsOn());
if (!SENSOR_SELECT())
{
return false;
}
accRangeReg = (newRange << 3);
// Apply the range
success = SensorI2C_writeReg(ACCEL_CONFIG, &accRangeReg, 1);
SENSOR_DESELECT();
if (success)
{
accRange = newRange;
}
return success;
}
/*******************************************************************************
* @fn SensorMpu9250_accReadRange
*
* @brief Apply the selected accelerometer range
*
* @param none
*
* @return range: ACC_RANGE_2G, ACC_RANGE_4G, ACC_RANGE_8G, ACC_RANGE_16G
*/
uint8_t SensorMpu9250_accReadRange(void)
{
ST_ASSERT(SensorMpu9250_powerIsOn());
if (!SENSOR_SELECT())
{
return false;
}
// Apply the range
SensorI2C_readReg(ACCEL_CONFIG, &accRangeReg, 1);
SENSOR_DESELECT();
accRange = (accRangeReg>>3) & 3;
return accRange;
}
/*******************************************************************************
* @fn SensorMpu9250_accRead
*
* @brief Read data from the accelerometer - X, Y, Z - 3 words
*
* @return True if data is valid
*/
bool SensorMpu9250_accRead(uint16_t *data )
{
bool success;
ST_ASSERT(SensorMpu9250_powerIsOn());
// Burst read of all accelerometer values
if (!SENSOR_SELECT())
{
return false;
}
success = SensorI2C_readReg(ACCEL_XOUT_H, (uint8_t*)data, DATA_SIZE);
SENSOR_DESELECT();
if (success)
{
SensorUtil_convertToLe((uint8_t*)data,DATA_SIZE);
}
return success;
}
/*******************************************************************************
* @fn SensorMpu9250_gyroRead
*
* @brief Read data from the gyroscope - X, Y, Z - 3 words
*
* @return TRUE if valid data, FALSE if not
*/
bool SensorMpu9250_gyroRead(uint16_t *data )
{
bool success;
ST_ASSERT(SensorMpu9250_powerIsOn());
// Select this sensor
if (!SENSOR_SELECT())
{
return false;
}
// Burst read of all gyroscope values
success = SensorI2C_readReg(GYRO_XOUT_H, (uint8_t*)data, DATA_SIZE);
SENSOR_DESELECT();
if (success)
{
SensorUtil_convertToLe((uint8_t*)data,DATA_SIZE);
}
return success;
}
/*******************************************************************************
* @fn SensorMpu9250_test
*
* @brief Run a sensor self-test
*
* @return TRUE if passed, FALSE if failed
*/
bool SensorMpu9250_test(void)
{
static bool first = true;
ST_ASSERT(SensorMpu9250_powerIsOn());
// Select Gyro/Accelerometer
if (!SENSOR_SELECT())
{
return false;
}
// Make sure power is ramped up
if (first)
{
DELAY_MS(100);
first = false;
}
// Check the WHO AM I register
ST_ASSERT(SensorI2C_readReg(WHO_AM_I, &val, 1));
ST_ASSERT(val == 0x71);
SENSOR_DESELECT();
return true;
}
/*******************************************************************************
* @fn SensorMpu9250_accConvert
*
* @brief Convert raw data to G units
*
* @param rawData - raw data from sensor
*
* @return Converted value
******************************************************************************/
float SensorMpu9250_accConvert(int16_t rawData)
{
float v;
switch (accRange)
{
case ACC_RANGE_2G:
//-- calculate acceleration, unit G, range -2, +2
v = (rawData * 1.0) / (32768/2);
break;
case ACC_RANGE_4G:
//-- calculate acceleration, unit G, range -4, +4
v = (rawData * 1.0) / (32768/4);
break;
case ACC_RANGE_8G:
//-- calculate acceleration, unit G, range -8, +8
v = (rawData * 1.0) / (32768/8);
break;
case ACC_RANGE_16G:
//-- calculate acceleration, unit G, range -16, +16
v = (rawData * 1.0) / (32768/16);
break;
}
return v;
}
/*******************************************************************************
* @fn SensorMpu9250_gyroConvert
*
* @brief Convert raw data to deg/sec units
*
* @param data - raw data from sensor
*
* @return none
******************************************************************************/
float SensorMpu9250_gyroConvert(int16_t data)
{
//-- calculate rotation, unit deg/s, range -250, +250
return (data * 1.0) / (65536 / 500);
}
/*******************************************************************************
* @fn sensorMpuSleep
*
* @brief Place the MPU in low power mode
*
* @return
*/
static void sensorMpuSleep(void)
{
bool success;
ST_ASSERT_V(SensorMpu9250_powerIsOn());
if (!SENSOR_SELECT())
{
return;
}
val = ALL_AXES;
success = SensorI2C_writeReg(PWR_MGMT_2, &val, 1);
if (success)
{
val = MPU_SLEEP;
success = SensorI2C_writeReg(PWR_MGMT_1, &val, 1);
}
SENSOR_DESELECT();
}
/*******************************************************************************
* @fn sensorMpu9250WakeUp
*
* @brief Exit low power mode
*
* @return none
*/
static void sensorMpu9250WakeUp(void)
{
bool success;
ST_ASSERT_V(SensorMpu9250_powerIsOn());
if (!SENSOR_SELECT())
{
return;
}
val = MPU_WAKE_UP;
success = SensorI2C_writeReg(PWR_MGMT_1, &val, 1);
if (success)
{
// All axis initially disabled
val = ALL_AXES;
success = SensorI2C_writeReg(PWR_MGMT_2, &val, 1);
mpuConfig = 0;
}
if (success)
{
// Restore the range
success = SensorI2C_writeReg(ACCEL_CONFIG, &accRangeReg, 1);
if (success)
{
// Clear interrupts
success = SensorI2C_readReg(INT_STATUS,&val,1);
}
}
SENSOR_DESELECT();
}
/*******************************************************************************
* @fn sensorMpu9250SelectAxes
*
* @brief Select gyro, accelerometer, magnetometer
*
* @return none
*/
static void sensorMpu9250SelectAxes(void)
{
if (!SENSOR_SELECT())
{
return;
}
// Select gyro and accelerometer (3+3 axes, one bit each)
val = ~mpuConfig;
SensorI2C_writeReg(PWR_MGMT_2, &val, 1);
SENSOR_DESELECT();
// Select magnetometer (all axes at once)
sensorMagEnable(!!(mpuConfig & MPU_AX_MAG));
}
/*******************************************************************************
* @fn sensorMpu9250SetBypass
*
* @brief Allow the I2C bus to control the magnetomoter
*
* @return true if success
*/
static bool sensorMpu9250SetBypass(void)
{
bool success;
if (SENSOR_SELECT())
{
val = BIT_BYPASS_EN | BIT_LATCH_EN;
success = SensorI2C_writeReg(INT_PIN_CFG, &val, 1);
DELAY_MS(10);
SENSOR_DESELECT();
}
else
{
success = false;
}
return success;
}
/*******************************************************************************
* @fn sensorMagInit
*
* @brief Initialize the compass
*
* @return none
*/
static void sensorMagInit(void)
{
ST_ASSERT_V(SensorMpu9250_powerIsOn());
if (!sensorMpu9250SetBypass())
{
return;
}
if (SENSOR_SELECT_MAG())
{
static uint8_t rawData[3];
// Enter Fuse ROM access mode
val = MAG_MODE_FUSE;
SensorI2C_writeReg(MAG_CNTL1, &val, 1);
DELAY_MS(10);
// Get calibration data
if (SensorI2C_readReg(MAG_ASAX, &rawData[0], 3))
{
// Return x-axis sensitivity adjustment values, etc.
calX = (int16_t)rawData[0] + 128;
calY = (int16_t)rawData[1] + 128;
calZ = (int16_t)rawData[2] + 128;
}
// Turn off the sensor by doing a reset
val = 0x01;
SensorI2C_writeReg(MAG_CNTL2, &val, 1);
SENSOR_DESELECT();
}
}
/*******************************************************************************
* @fn SensorMpu9250_magReset
*
* @brief Reset the magnetometer
*
* @return none
*/
void SensorMpu9250_magReset(void)
{
ST_ASSERT_V(SensorMpu9250_powerIsOn());
if (sensorMpu9250SetBypass())
{
if (SENSOR_SELECT_MAG())
{
// Turn off the sensor by doing a reset
val = 0x01;
SensorI2C_writeReg(MAG_CNTL2, &val, 1);
DELAY_MS(10);
// Re-enable if already active
if (mpuConfig & MPU_AX_MAG)
{
// Set magnetometer data resolution and sample ODR
val = (scale << 4) | mode;
SensorI2C_writeReg(MAG_CNTL1, &val, 1);
}
SENSOR_DESELECT();
}
}
}
/*******************************************************************************
* @fn sensorMagEnable
*
* @brief Enable or disable the compass part of the MPU9250
*
* @return none
*/
static void sensorMagEnable(bool enable)
{
uint8_t val;
ST_ASSERT_V(SensorMpu9250_powerIsOn());
if (!sensorMpu9250SetBypass())
{
return;
}
if (SENSOR_SELECT_MAG())
{
if (enable)
{
// Set magnetometer data resolution and sample ODR
val = (scale << 4) | mode;
}
else
{
// Power down magnetometer
val = 0x00;
}
SensorI2C_writeReg(MAG_CNTL1, &val, 1);
SENSOR_DESELECT();
}
}
/*******************************************************************************
* @fn SensorMpu9250_magTest
*
* @brief Run a magnetometer self test
*
* @return TRUE if passed, FALSE if failed
*/
bool SensorMpu9250_magTest(void)
{
ST_ASSERT(SensorMpu9250_powerIsOn());
// Connect magnetometer internally in MPU9250
sensorMpu9250SetBypass();
// Select magnetometer
SENSOR_SELECT_MAG();
// Check the WHO AM I register
val = 0xFF;
ST_ASSERT(SensorI2C_readReg(MAG_WHO_AM_I, &val, 1));
ST_ASSERT(val == MAG_DEVICE_ID);
SENSOR_DESELECT();
return true;
}
/*******************************************************************************
* @fn SensorMpu9250_magRead
*
* @brief Read data from the compass - X, Y, Z - 3 words
*
* @return Magnetometer status
*/
uint8_t SensorMpu9250_magRead(int16_t *data)
{
uint8_t val;
uint8_t rawData[7]; // x/y/z compass register data, ST2 register stored here,
// must read ST2 at end of data acquisition
magStatus = MAG_NO_POWER;
ST_ASSERT(SensorMpu9250_powerIsOn());
magStatus = MAG_STATUS_OK;
// Connect magnetometer internally in MPU9250
SENSOR_SELECT();
val = BIT_BYPASS_EN | BIT_LATCH_EN;
if (!SensorI2C_writeReg(INT_PIN_CFG, &val, 1))
{
magStatus = MAG_BYPASS_FAIL;
}
SENSOR_DESELECT();
if (magStatus != MAG_STATUS_OK)
{
return false;
}
// Select this sensor
SENSOR_SELECT_MAG();
if (SensorI2C_readReg(MAG_ST1,&val,1))
{
// Check magnetometer data ready bit
if (val & 0x01)
{
// Burst read of all compass values + ST2 register
if (SensorI2C_readReg(MAG_XOUT_L, &rawData[0],7))
{
val = rawData[6]; // ST2 register
// Check if magnetic sensor overflow set, if not report data
if(!(val & 0x08))
{
// Turn the MSB and LSB into a signed 16-bit value,
// data stored as little Endian
data[0] = ((int16_t)rawData[1] << 8) | rawData[0];
data[1] = ((int16_t)rawData[3] << 8) | rawData[2];
data[2] = ((int16_t)rawData[5] << 8) | rawData[4];
// Sensitivity adjustment
data[0] = data[0] * calX >> 8;
data[1] = data[1] * calY >> 8;
data[2] = data[2] * calZ >> 8;
}
else
{
magStatus = MAG_OVERFLOW;
}
}
else
{
magStatus = MAG_READ_DATA_ERR;
}
}
else
{
magStatus = MAG_DATA_NOT_RDY;
}
}
else
{
magStatus = MAG_READ_ST_ERR;
}
// Set magnetometer data resolution and sample ODR
// Start new conversion
val = (scale << 4) | mode;
SensorI2C_writeReg(MAG_CNTL1, &val, 1);
SENSOR_DESELECT();
return magStatus;
}
/*******************************************************************************
* @fn SensorMpu9250_magStatus
*
* @brief Return the magnetometer status
*
* @return mag status
*/
uint8_t SensorMpu9250_magStatus(void)
{
return magStatus;
}
/*******************************************************************************
* @fn SensorMpu9250_Callback
*
* Interrupt service routine for the MPU
*
* @param handle PIN_Handle connected to the callback
*
* @param pinId PIN_Id of the DIO triggering the callback
*
* @return none
******************************************************************************/
static void SensorMpu9250_Callback(PIN_Handle handle, PIN_Id pinId)
{
if (pinId == Board_MPU_INT)
{
if (isrCallbackFn != NULL)
{
isrCallbackFn();
}
}
}
/*
* Copyright (c) 2015-2016, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** ============================================================================
* @file SensorMpu9250.h
*
* @brief Driver for the InvenSense MPU9250 Motion Processing Unit.
*
* ============================================================================
*/
#ifndef SENSOR_MPU9250_H
#define SENSOR_MPU9250_H
#ifdef __cplusplus
extern "C" {
#endif
/* -----------------------------------------------------------------------------
* Includes
* -----------------------------------------------------------------------------
*/
#include "stdint.h"
#include "stdbool.h"
/* -----------------------------------------------------------------------------
* Constants
* -----------------------------------------------------------------------------
*/
// Accelerometer ranges
#define ACC_RANGE_2G 0
#define ACC_RANGE_4G 1
#define ACC_RANGE_8G 2
#define ACC_RANGE_16G 3
#define ACC_RANGE_INVALID 0xFF
// Axis bitmaps
#define MPU_AX_GYR 0x07
#define MPU_AX_ACC 0x38
#define MPU_AX_MAG 0x40
#define MPU_AX_ALL 0x7F
// Interrupt status bit
#define MPU_DATA_READY 0x01
#define MPU_MOVEMENT 0x40
// Magnetometer status
#define MAG_STATUS_OK 0x00
#define MAG_READ_ST_ERR 0x01
#define MAG_DATA_NOT_RDY 0x02
#define MAG_OVERFLOW 0x03
#define MAG_READ_DATA_ERR 0x04
#define MAG_BYPASS_FAIL 0x05
#define MAG_NO_POWER 0x06
/* ----------------------------------------------------------------------------
* Typedefs
* -----------------------------------------------------------------------------
*/
typedef void (*SensorMpu9250CallbackFn_t)(void);
/* -----------------------------------------------------------------------------
* Functions
* -----------------------------------------------------------------------------
*/
bool SensorMpu9250_init(void);
bool SensorMpu9250_reset(void);
void SensorMpu9250_registerCallback(SensorMpu9250CallbackFn_t);
bool SensorMpu9250_test(void);
void SensorMpu9250_powerOn(void);
void SensorMpu9250_powerOff(void);
bool SensorMpu9250_powerIsOn(void);
void SensorMpu9250_enable(uint16_t config);
bool SensorMpu9250_enableWom(uint8_t threshold);
uint8_t SensorMpu9250_irqStatus(void);
bool SensorMpu9250_accSetRange(uint8_t range);
uint8_t SensorMpu9250_accReadRange(void);
bool SensorMpu9250_accRead(uint16_t *rawData);
float SensorMpu9250_accConvert(int16_t rawValue);
bool SensorMpu9250_gyroRead(uint16_t *rawData);
float SensorMpu9250_gyroConvert(int16_t rawValue);
bool SensorMpu9250_magTest(void);
uint8_t SensorMpu9250_magRead(int16_t *pRawData);
uint8_t SensorMpu9250_magStatus(void);
void SensorMpu9250_magReset(void);
/*******************************************************************************
*/
#ifdef __cplusplus
};
#endif
#endif
