Application example of mpu6050 based on nrf52832

Posted by donbre on Sun, 19 Sep 2021 17:06:07 +0200

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_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);

. 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,&register_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;
            return true;
        return false;

*  Ô˶¯¼ì²âÖжÏ
void Motion_Interrupt(void)             //

	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;
	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);

	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)	
	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
    //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();	

*  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

Topics: NRF52832