1 Platform Based
1. Hardware platform: nRF52832
2: Software sdk: nRF5_SDK_14.2.0_17b948a
3: Reference blog link
Address 1
Address 2
Address 3
Address 4
2. Drive with I2C interface
Refer to the previous blog, which has been written and tested, and can be transplanted and called directly
Analog I2C address
3 MPU6050 motion interrupt related register
For one reason or another, many registers are omitted from the technical documents of MPU6050, and these deliberately omitted registers often involve various advanced applications, such as motion interrupt (free fall interrupt, acceleration interrupt and static interrupt), internal DMP data fusion and internal FIFO. Thank you for sorting out the relevant registers and DMP drivers by using decompilation and other technical means.
In addition to the basic registers (PWR_MGMT, CONFIG, ACCEL_CONFIG, etc.), the relevant internal registers involved in motion interrupt application mainly include:
1: Interrupt enable register: INT_ENABLE, register address 0x38, is the switch register of all interrupt outputs of MPU6050, which is used to enable motion interrupt, FIFO overflow interrupt and data interrupt;
2 FIFO control register: USER_CTRL, register address 0x6A, which is used to enable FIFO and control I2C host of MPU6050. When the motion interrupt function is applied, FIFO and I2C host shall be closed;
3 FIFO enable register: FIFO_EN, register address 0x23, which is used to enable each FIFO function and shall be closed when the motion interrupt function is applied;
4 interrupt pin configuration register: INT_PIN_CFG, register address 0x37, which is used to set the level standard and driving mode (push-pull, open drain) of INT interrupt pin;
5 motion status register: MOT_DETECT_STATUS, register address 0x61, which is used to indicate the type of interrupt when triggering motion interrupt (free fall interrupt, acceleration interrupt and static interrupt).
6 free fall interrupt threshold register: FF_THR, register address 0x1D. When the free fall interrupt is enabled, the value of this register determines the trigger threshold of the interrupt. The higher the value, the less sensitive it is to detect the free fall;
7 free fall interrupt time register: FF_DUR, register address 0x1E. When the free fall interrupt is enabled, the value of this register determines the duration threshold of the interrupt. When the duration of the free fall reaches the set threshold, the interrupt is triggered. The higher the value, the longer the time threshold for free fall detection;
8 acceleration interrupt threshold register: MOT_THR, register address 0x1F. When enabling acceleration interrupt, the value of this register determines the trigger threshold of the interrupt. The higher the value, the greater the acceleration required to trigger the interrupt.
9 acceleration interrupt time register: MOT_DUR, register address 0x20. When the acceleration interrupt is enabled, the value of this register determines the duration threshold of the interrupt. When the duration of the acceleration value reaches the set threshold, the interrupt is triggered. The higher the value, the longer the acceleration duration required to trigger the interrupt;
10 static interrupt threshold register: ZRMOT_THR, register address 0x21. When the static interrupt is enabled, if the three-axis values output by the current accelerometer are less than the static interrupt threshold, the static interrupt will be generated. The higher the value, the looser the requirement to trigger a quiescent interrupt.
11 static interrupt time register: ZRMOT_DUR, register address 0x22. When the static interrupt is enabled, the value of this register determines the duration required to trigger the static interrupt. The higher the value, the longer the static duration required to trigger the interrupt.
Unless otherwise specified, each register is logic 1 enabled
Interrupt enable register: INT_ENABLE
FIFO control register: USER_CTRL
FIFO enable register: FIFO_EN
Interrupt pin configuration register: INT_PIN_CFG
Motion status register: MOT_DETECT_STATUS
Free fall interrupt threshold register: FF_THR
4 code example
. h file
#ifndef mpu6050_h_ #define mpu6050_h_ #include "stdint.h" #define MPU6050_SDA_PIN 16 #define MPU6050_SCL_PIN 15 #define MPU6050_ADDRESS_AD0_LOW 0xD0 #define MPU6050_ADDRESS_AD0_HIGH 0XD1 #define MPU_ADDR 0xD0 /*lint ++flb "Enter library region" */ #define ADDRESS_WHO_AM_I (0x75U) // !< WHO_AM_I register identifies the device. Expected value is 0x68. #define ADDRESS_SIGNAL_PATH_RESET (0x68U) // !< #define MPU6050_ADDRESS 0x69 #define MPU6050_GYRO_OUT 0x43 #define MPU6050_ACC_OUT 0x3B #define MPU_SELF_TESTX_REG 0X0D //×Ô¼ì¼Ä´æÆ÷X #define MPU_SELF_TESTY_REG 0X0E //×Ô¼ì¼Ä´æÆ÷Y #define MPU_SELF_TESTZ_REG 0X0F //×Ô¼ì¼Ä´æÆ÷Z #define MPU_SELF_TESTA_REG 0X10 //×Ô¼ì¼Ä´æÆ÷A #define MPU_SAMPLE_RATE_REG 0X19 //²ÉÑùƵÂÊ·ÖƵÆ÷ #define MPU_CFG_REG 0X1A //ÅäÖüĴæÆ÷ #define MPU_GYRO_CFG_REG 0X1B //27:ÍÓÂÝÒÇÅäÖüĴæÆ÷ #define MPU_ACCEL_CFG_REG 0X1C //28¼ÓËٶȼÆÅäÖüĴæÆ÷ #define MPU_FF_THR 0X1D //×ÔÓÉÂäÌå¼ì²âÖжÏãÐÖµ #define MPU_FF_DUR 0X1E //×ÔÓÉÂäÌåÖжÏʼþ #define MPU_MOTION_DET_REG 0X1F //Ô˶¯¼ì²â·§ÖµÉèÖüĴæÆ÷ #define MPU_MOT_DUR_REG 0X20 //Ô˶¯ÖжÏʱ¼ä #define MPU_ZRMOT_THR_REG 0X21 //¾²Ö¹¼ì²âãÐÖµ #define MPU_ZRMOT_DUR_REG 0X22 //¾²Ö¹¼ì²âʱ¼ä #define MPU_FIFO_EN_REG 0X23 //FIFOʹÄܼĴæÆ÷ #define MPU_I2CMST_CTRL_REG 0X24 //IICÖ÷»ú¿ØÖƼĴæÆ÷ #define MPU_I2CSLV0_ADDR_REG 0X25 //IIC´Ó»ú0Æ÷¼þµØÖ·¼Ä´æÆ÷ #define MPU_I2CSLV0_REG 0X26 //IIC´Ó»ú0Êý¾ÝµØÖ·¼Ä´æÆ÷ #define MPU_I2CSLV0_CTRL_REG 0X27 //IIC´Ó»ú0¿ØÖƼĴæÆ÷ #define MPU_I2CSLV1_ADDR_REG 0X28 //IIC´Ó»ú1Æ÷¼þµØÖ·¼Ä´æÆ÷ #define MPU_I2CSLV1_REG 0X29 //IIC´Ó»ú1Êý¾ÝµØÖ·¼Ä´æÆ÷ #define MPU_I2CSLV1_CTRL_REG 0X2A //IIC´Ó»ú1¿ØÖƼĴæÆ÷ #define MPU_I2CSLV2_ADDR_REG 0X2B //IIC´Ó»ú2Æ÷¼þµØÖ·¼Ä´æÆ÷ #define MPU_I2CSLV2_REG 0X2C //IIC´Ó»ú2Êý¾ÝµØÖ·¼Ä´æÆ÷ #define MPU_I2CSLV2_CTRL_REG 0X2D //IIC´Ó»ú2¿ØÖƼĴæÆ÷ #define MPU_I2CSLV3_ADDR_REG 0X2E //IIC´Ó»ú3Æ÷¼þµØÖ·¼Ä´æÆ÷ #define MPU_I2CSLV3_REG 0X2F //IIC´Ó»ú3Êý¾ÝµØÖ·¼Ä´æÆ÷ #define MPU_I2CSLV3_CTRL_REG 0X30 //IIC´Ó»ú3¿ØÖƼĴæÆ÷ #define MPU_I2CSLV4_ADDR_REG 0X31 //IIC´Ó»ú4Æ÷¼þµØÖ·¼Ä´æÆ÷ #define MPU_I2CSLV4_REG 0X32 //IIC´Ó»ú4Êý¾ÝµØÖ·¼Ä´æÆ÷ #define MPU_I2CSLV4_DO_REG 0X33 //IIC´Ó»ú4дÊý¾Ý¼Ä´æÆ÷ #define MPU_I2CSLV4_CTRL_REG 0X34 //IIC´Ó»ú4¿ØÖƼĴæÆ÷ #define MPU_I2CSLV4_DI_REG 0X35 //IIC´Ó»ú4¶ÁÊý¾Ý¼Ä´æÆ÷ //#define MPU_PWR_MGMT1_REG 0X6B //µçÔ´¹ÜÀí¼Ä´æÆ÷1 //#define MPU_PWR_MGMT2_REG 0X6C //µçÔ´¹ÜÀí¼Ä´æÆ÷2 #define MPU_I2CMST_STA_REG 0X36 //IICÖ÷»ú״̬¼Ä´æÆ÷ #define MPU_INTBP_CFG_REG 0X37 //ÖжÏ/ÅÔ·ÉèÖüĴæÆ÷ #define MPU_INT_EN_REG 0X38 //ÖжÏʹÄܼĴæÆ÷ #define MPU_INT_STA_REG 0X3A //ÖжÏ״̬¼Ä´æÆ÷ #define MPU_I2CMST_DELAY_REG 0X67 //IICÖ÷»úÑÓʱ¹ÜÀí¼Ä´æÆ÷ #define MPU_SIGPATH_RST_REG 0X68 //ÐźÅͨµÀ¸´Î»¼Ä´æÆ÷ #define MPU_MDETECT_CTRL_REG 0X69 //Ô˶¯¼ì²â¿ØÖƼĴæÆ÷ #define MPU_USER_CTRL_REG 0X6A //Óû§¿ØÖƼĴæÆ÷ #define MPU_PWR_MGMT1_REG 0X6B //µçÔ´¹ÜÀí¼Ä´æÆ÷1 #define MPU_PWR_MGMT2_REG 0X6C //µçÔ´¹ÜÀí¼Ä´æÆ÷2 #define MPU_FIFO_CNTH_REG 0X72 //FIFO¼ÆÊý¼Ä´æÆ÷¸ß°Ëλ #define MPU_FIFO_CNTL_REG 0X73 //FIFO¼ÆÊý¼Ä´æÆ÷µÍ°Ëλ #define MPU_FIFO_RW_REG 0X74 //FIFO¶Áд¼Ä´æÆ÷ #define MPU_DEVICE_ID_REG 0X75 //Æ÷¼þID¼Ä´æÆ÷ #define MPU_MOT_DETECT_STATUS 0X61 //Ô˶¯×´Ì¬¼Ä´æÆ÷ void mpu6050_init(void); void task_read_MPU6050(void); #endif
. c driver code
#include "mpu6050.h" #include "iic_io.h" #include "utility.h" #include "bsp.h" static uint8_t m_device_address; // !< Device address in bits [7:1] /************************************************ * mpu6050_register_write * ******************************************/ bool mpu6050_register_write(uint8_t register_address, uint8_t value) { uint8_t w2_data[2]; w2_data[0] = register_address; w2_data[1] = value; return hrs_iic_transfer(m_device_address, w2_data, 2, TWI_ISSUE_STOP); } /***************************************************************************** *@function name: mpu6050_register_read *@description : write and read reg *@Para : register_address *******************************************************************************/ bool mpu6050_register_read(uint8_t register_address, uint8_t * destination, uint8_t number_of_bytes) { bool transfer_succeeded; transfer_succeeded=hrs_iic_transfer(m_device_address,®ister_address,1, TWI_DONT_ISSUE_STOP); transfer_succeeded=hrs_iic_transfer(m_device_address|TWI_READ_BIT, destination, number_of_bytes, TWI_ISSUE_STOP); return transfer_succeeded; } /*********************************************** * mpu6050_verify_product_id * ***********************************/ const uint8_t expected_who_am_i = 0x68U; // !< Expected value to get from WHO_AM_I register. bool mpu6050_verify_product_id(void) { uint8_t who_am_i=0; if (mpu6050_register_read(ADDRESS_WHO_AM_I, &who_am_i, 1)) { BSP_RTT("mpu6050_verify_product_id =0x%02x\r\n",who_am_i); if (who_am_i != expected_who_am_i) { return false; } else { return true; } } else { return false; } } /********************************************* * Ô˶¯¼ì²âÖÐ¶Ï * **************************************/ void Motion_Interrupt(void) // { mpu6050_register_write(MPU_MOTION_DET_REG,0x01); mpu6050_register_write(MPU_MOT_DUR_REG,0x14); mpu6050_register_write(MPU_CFG_REG,0x04); //DLPF mpu6050_register_write(MPU_ACCEL_CFG_REG,0x1C); // mpu6050_register_write(MPU_INTBP_CFG_REG,0X1C); //INT mpu6050_register_write(MPU_INT_EN_REG,0x40); // } /********************************************* * MPU_Fall_Init * ****************************************************/ void MPU_Fall_Init(void) // { mpu6050_register_write(MPU_FF_THR,0x14); //20mg mpu6050_register_write(MPU_FF_DUR,0x0A); //10ms mpu6050_register_write(MPU_CFG_REG,0x04); //DLPF mpu6050_register_write(MPU_ACCEL_CFG_REG,0x1C); // mpu6050_register_write(MPU_INTBP_CFG_REG,0X1C); //INT mpu6050_register_write(MPU_INT_EN_REG,0x40); // } /********************************************* * MPU_Zero_Motion_Init * ****************************************************/ void MPU_Zero_Motion_Init(void) { mpu6050_register_write(MPU_ZRMOT_THR_REG,0x20); //64mg mpu6050_register_write(MPU_ZRMOT_DUR_REG,0x20); //32ms mpu6050_register_write(MPU_CFG_REG,0x04); //DLPF mpu6050_register_write(MPU_ACCEL_CFG_REG,0x1C); // mpu6050_register_write(MPU_INTBP_CFG_REG,0X1C); //INT mpu6050_register_write(MPU_INT_EN_REG,0x40); // } /************************************** * mpu6050_init * *****************************/ // uint8_t inData[7]={0x00, // 0x00, // 0x03, // 0x10, // 0x00, // 0x32, // 0x01}; /****************************************************************************/ // bit2-bit0 /* * * | ??????| ??? * * DLPF_CFG | ??| ??| ??| ??| ??? * ------------- + -------- + ------- + -------- + ------ + - ----------- * 0 | 260Hz | 0ms | 256Hz | 0.98ms | 8kHz * 1 | 184Hz | 2.0ms | 188Hz | 1.9ms | 1kHz * 2 | 94Hz | 3.0ms | 98Hz | 2.8ms | 1kHz * 3 | 44Hz | 4.9ms | 42Hz | 4.8ms | 1kHz * 4 | 21Hz | 8.5ms | 20Hz | 8.3ms | 1kHz * 5 | 10Hz | 13.8ms | 10Hz | 13.4ms | 1kHz * 6 | 5Hz | 19.0ms | 5Hz | 18.6ms | 1kHz * 7 | ??| ??| ?? * */ void mpu6050_init(void) { bool transfer_succeeded = 0xff; uint8_t device_address =0x68; hrs_iic_init(MPU6050_SDA_PIN,MPU6050_SCL_PIN); delay_ms(100); m_device_address = (uint8_t)(device_address << 1); // Do a reset on signal paths uint8_t reset_value = 0x04U | 0x02U | 0x01U; // Resets gyro, accelerometer and temperature sensor signal paths transfer_succeeded = mpu6050_register_write(ADDRESS_SIGNAL_PATH_RESET, reset_value); //ÉèÖòÉÑùÂÊ //rate:4~1000(Hz) mpu6050_register_write(MPU_SAMPLE_RATE_REG ,0x00);// -- SMPLRT_DIV = 0 Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) //-- EXT_SYNC_SET 0 (½ûÓþ§ÕñÊäÈë½Å) ; //default DLPF_CFG = 0 => (µÍͨÂ˲¨)ACC bandwidth = 260Hz GYRO bandwidth = 256Hz) //0x06-5hz mpu6050_register_write(MPU_CFG_REG ,0x06);//0x00); //CONFIG //-- SLEEP 0; CYCLE 0; TEMP_DIS 0; CLKSEL 3 (PLL with Z Gyro reference) mpu6050_register_write(MPU_PWR_MGMT1_REG , 0x03); //PWR_MGMT_1 mpu6050_register_write(MPU_USER_CTRL_REG , 0x00); // 0x6AµÄ I2C_MST_EN ÉèÖóÉ0 ĬÈÏΪ0 6050 ʹÄÜÖ÷IIC mpu6050_register_write(MPU_FIFO_EN_REG,0X00); //close fifo /*****************************ÉèÖÃGYRO****************************************************/ //fsr:0,¡À250dps;1,¡À500dps;2,¡À1000dps;3,¡À2000dps bit3-bit4 uint8_t gyro_fsr =3;// mpu6050_register_write(MPU_GYRO_CFG_REG,gyro_fsr<<3);// 0x10); //gyroÅäÖà Á¿³Ì 0-1000¶ÈÿÃë /*****************************ÉèÖà ACC****************************************************/ //fsr:0,+-2G;1,+-4G;2,+-8G s ;3,+-16G bit3-bit4 uint8_t acc_fsr =0; mpu6050_register_write(MPU_ACCEL_CFG_REG,acc_fsr<<3); //ACCÉèÖà Á¿³Ì +-2G s /*********************************************************************************************/ // £¬¸ßµçƽÖжϣ¬Ò»Ö±Êä³ö¸ßµçƽֱµ½ÖжÏÇå³ý mpu6050_register_write(MPU_INTBP_CFG_REG, 0x1C);//0x32);// INTµÍµçƽ mpu6050_register_write(MPU_INT_EN_REG, 0X40);// 0x01); // Read and verify product ID transfer_succeeded &= mpu6050_verify_product_id(); Motion_Interrupt(); } /******************************************************* * MPU6050_ReadGyro * ÍÓÂÝÒÇÖµ *********************************/ void MPU6050_ReadGyro(int16_t *pGYRO_X , int16_t *pGYRO_Y , int16_t *pGYRO_Z ) { uint8_t buf[6]; mpu6050_register_read(MPU6050_GYRO_OUT, buf, 6); *pGYRO_X = (buf[0] << 8) | buf[1]; if(*pGYRO_X & 0x8000) *pGYRO_X-=65536; *pGYRO_Y= (buf[2] << 8) | buf[3]; if(*pGYRO_Y & 0x8000) *pGYRO_Y-=65536; *pGYRO_Z = (buf[4] << 8) | buf[5]; if(*pGYRO_Z & 0x8000) *pGYRO_Z-=65536; } /******************************************************* * MPU6050_ReadAcc * ¼ÓËÙ¶ÈÖµ *********************************/ void MPU6050_ReadAcc( int16_t *pACC_X , int16_t *pACC_Y , int16_t *pACC_Z ) { uint8_t buf[6]; mpu6050_register_read(MPU6050_ACC_OUT, buf, 6); *pACC_X = (buf[0] << 8) | buf[1]; if(*pACC_X & 0x8000) *pACC_X-=65536; *pACC_Y= (buf[2] << 8) | buf[3]; if(*pACC_Y & 0x8000) *pACC_Y-=65536; *pACC_Z = (buf[4] << 8) | buf[5]; if(*pACC_Z & 0x8000) *pACC_Z-=65536; } void task_read_MPU6050(void) { int16_t AccValue[3],GyroValue[3]; MPU6050_ReadAcc( &AccValue[0], &AccValue[1] , &AccValue[2] ); MPU6050_ReadGyro(&GyroValue[0] , &GyroValue[1] , &GyroValue[2] ); BSP_RTT("6050-ACC: %d %d %d ",AccValue[0],AccValue[1],AccValue[2]); BSP_RTT("6050-GYRO: %d %d %d \r\n",GyroValue[0],GyroValue[1],GyroValue[2]); }
Can join QQ group: 687360507
To communicate with everyone, technology lies in sharing and progress