MPU6050简介:
& b: d. I$ \2 L+ N) v' @MPU6050是InvenSense公司推出的全球首款整合性6轴运动处理组件,内带3轴陀螺仪和3轴加速度传感器,并且含有一个第二IIC接口,可用于连接外部磁力传感器。
! ~- u, u) _) n% ~那如何通过MPU6050传感器来获取数据呢?
" z8 ~ \3 z) `6 B1 ]% a具体步骤如下:" m0 c+ X& u* i- @8 S: I
4 b" R$ n' b8 P2 O! w$ V
1.新建项目:1 V$ ~. E2 A$ [$ I
8 g7 s% J& q" b; A0 I9 Y; \
3 Z' U3 ^* a" R! S! _/ D1 w8 ~9 a
# g# B x9 \) J5 \& _% K- ~/ ?
2.选择STM32F103C8T6芯片9 e/ n" t; F0 W0 b/ W$ W4 T
3 F8 ]3 |3 Z9 B+ l+ Y
6 P8 l+ e5 H7 L4 I+ I( G
' i- a0 P8 m+ H3 O+ i; K: o) V3.对工程文件命名5 E5 n6 l4 s4 B" {/ V
6 f6 z: L* |4 t
0 Y2 l0 u% X! `3 o( D) F) l# K
, M0 B' f9 `5 j3 A1 N+ [; _6 O4.在Connectivity中选择I2C1,在mode中选择I2C
# U- R- Z4 u; |- f$ A5 Q7 I f
% D Z# f, Y: r* C# B6 O4 a0 O
' R" r, |& L! U- Q8 b& L* C
' M3 G7 L1 ?! X' v: L+ | 5.根据原理图选择引脚
3 C$ K7 D" n. k' e1 m# K其中MPU6050中的SCL和SDA应对应于C8T6主控模块上的PB8和PB9,故应在右侧引脚设置中单击PB9,PB8引脚,选择I2C1_SDA项。
* G9 [) i6 y5 Q+ ]: z0 i* A4 U
9 Q" J! ~% U6 `. x, i- f( w
& @4 D/ | U( \* k5 ? x
" a6 z: L9 i6 N% A9 [2 W
9 p+ G7 j8 u& F; M# a) `( O6 U- B6.点击生成代码,在MPU6050下新建一个User文件夹,在User文件夹下新建一个BSP文件夹,在BSP文件夹下添加Inc和Src文件夹,并在Inc和Src文件夹下添加bsp_mpu6050.c和bsp_mpu6050.h文件。(注意新建的文件夹需要设置路径)
, q$ |1 C6 [, k% ?新建的User文件夹,设置路径:8 d7 n7 {4 E% ?; ^6 i1 k
3 \% C7 Q3 S; o4 g(只有设置完路径后才能添加的上.c和.h文件)
9 [# E0 V+ C$ D2 g* R! ?# ]9 i8 Z8 W& O3 Y2 b) ~
u% u+ \3 @8 w D4 |& J" @* G: R
( m5 A1 p' {& Z+ L4 _" U) {+ h" |再添加.c和,h文件
/ n6 a2 T. z) f( H y) g3 j" I7 f' Q, a" U) G" V* W) E8 w+ E
2 c, Y' x/ z7 E6 w: P" @) u
0 A$ Z4 y+ g" @- _7.把以下代码加入bsp_mpu6050.c, E# y7 W, Y; `
- #include "main.h"
4 y- P7 h8 {! T) h
^0 |/ g6 |" |# h- extern I2C_HandleTypeDef hi2c1;/ |' ?# ?4 O" @! P% S6 ?
3 d; f! f9 r$ B) M2 f* x- IMU_SensorData_Raw_Structer IMU_SensorData_Raw;
1 p/ R8 @; Q- r4 P4 }
: T* t( f8 o/ G; F' U- uint8_t BSP_MPU6050_ReadReg(uint8_t address)
) g! a6 }" d1 G' ~" Q# ]6 U) O - {1 K5 L5 ?. d7 a: R, l$ O K; @: f7 @' k
- uint8_t Value = 0;
' d% s7 W2 \2 H$ N! A4 @) O' P - HAL_I2C_Mem_Read(&hi2c1,IMU_ADDRESS_READ,address,I2C_MEMADD_SIZE_8BIT,&Value,1,0x10);& n$ z% X" K, s9 a9 j
- return Value;/ g. C I. U2 I9 z4 a" K
- }! P# v+ I' O* e' y3 _# t% |) P N
- 4 P. E9 E6 G) w5 Q7 a
- void BSP_MPU6050_ReadMultiReg(uint8_t address,uint8_t length,uint8_t *data)
2 h' Z5 G2 J) i, O1 t' ^ - {# {* w5 v! O# W S7 C$ z; K$ E
- HAL_I2C_Mem_Read(&hi2c1,IMU_ADDRESS_READ,address,I2C_MEMADD_SIZE_8BIT,data,length,0x10);1 \8 h+ q9 P. ], M( }6 ?
- }
3 _9 k6 s/ w) [0 M' S
& L2 r3 h/ E' [: V; U$ t- void BSP_MPU6050_WriteReg(uint8_t address,uint8_t data)
6 u* I& d6 B; x# Z9 x N - {
8 L6 Y& E2 K U4 E5 c - HAL_I2C_Mem_Write(&hi2c1,IMU_ADDRESS_WRITE,address,I2C_MEMADD_SIZE_8BIT,&data,1,0x10);) @" r% Y$ `9 W8 Z# U$ {
- HAL_Delay(100);, R" j5 I) V; ~, \* }
- }0 P( X+ s- o. Y. T
- S2 ?8 {/ K! }# s7 W( Q( F A
- void BSP_MPU6050_WriteMultiReg(uint8_t address,uint8_t length,uint8_t *data)0 p# V, Y0 y* U
- {
9 V# T1 }6 X1 j5 b8 a - HAL_I2C_Mem_Write(&hi2c1,IMU_ADDRESS_WRITE,address,I2C_MEMADD_SIZE_8BIT,data,length,0x10);
3 b: x1 ]" |7 O6 t5 l. [2 R# L7 b& h - HAL_Delay(100);
: r2 M% _- p/ J, i2 ~ - }$ Y- D- V8 `, l; \& h X
- # D5 I! |5 g* W& c. n
- uint8_t BSP_MPU6050_Read_WHOAMI(void)
/ T- H# [: G g( p - {
I9 U8 W1 G0 o$ j Z1 z - return BSP_MPU6050_ReadReg(MPUREG_WHOAMI);" d( z; b h# W" @( }) G" O) G
- }
6 p( F3 i; P* T a8 l" ^ - 4 |. Y0 I& L$ `, G2 P
- uint8_t BSP_MPU6050_Init(void): d% \. @) J2 b* N9 o' i5 _5 y
- {
# G$ d( F) N1 k* O - uint8_t tries;
4 I* i0 m" D r/ }' N8 G. Y2 s
" G0 ~4 G# L- D/ Y& h6 S! ]- for(tries = 0; tries<5; tries++)
) B* E; j: B8 @( S& A9 ?1 } - {* F9 z; A% k9 l/ d0 A
- BSP_MPU6050_WriteReg(MPUREG_PWR_MGMT_1,BIT_PWR_MGMT_1_DEVICE_RESET);//复位MPU60504 j5 {5 L! \' y0 c
- BSP_MPU6050_WriteReg(MPUREG_PWR_MGMT_1,BIT_PWR_MGMT_1_CLK_ZGYRO);//设置时钟. K4 I9 a- |! p9 a7 q8 ]# s
- if(BSP_MPU6050_ReadReg(MPUREG_PWR_MGMT_1) == BIT_PWR_MGMT_1_CLK_ZGYRO)//判断是否写入,写入则跳出循环9 r, `. V0 w8 l0 ?0 r9 S% y
- break;
3 v' Q0 K* h7 R - }& u, Q4 q) z8 R
- if(tries == 5)) R+ n; B5 g- j+ N+ j9 S% l9 p
- return 0;
9 c, }# }6 T5 M- t5 U+ E - 4 o7 @# B4 M: F. R9 d5 U
- BSP_MPU6050_WriteReg(MPUREG_PWR_MGMT_2,0x00);//禁止休眠
; W/ ?0 I' G7 a O+ c* [) X5 D - BSP_MPU6050_WriteReg(MPUREG_USER_CTRL,0x00);//I2C主模式关闭
& t& R2 f. M" O5 p - BSP_MPU6050_WriteReg(MPUREG_CONFIG,BITS_DLPF_CFG_20HZ);//设置低通滤波器& }( {6 {) `, ~% p a2 O# m
- BSP_MPU6050_WriteReg(MPUREG_SMPLRT_DIV,MPUREG_SMPLRT_200HZ);//设置采样频率! V6 Y" B' M [! t& Z
- BSP_MPU6050_WriteReg(MPUREG_GYRO_CONFIG,BITS_GYRO_FS_2000DPS);//设置陀螺仪量程& ?# F$ B7 p+ v$ r d; d
- BSP_MPU6050_WriteReg(MPUREG_ACCEL_CONFIG,BITS_ACCEL_FS_8G);//设置加速度计量程+ X% I, B2 c4 e, V
- BSP_MPU6050_WriteReg(MPUREG_INT_ENABLE,0x00);//禁止中断
/ d! }; `) `$ [. @5 q
7 m/ o. y; p2 k! t- if(BSP_MPU6050_Read_WHOAMI() == IMU_WHOAMI); ^/ r# |' P( T X/ J
- return 1;% ~* ?; T; m! m' }2 K4 l2 b
- else
( Q1 d q8 p8 {& K8 k$ p3 U - return 0;6 L" N& W1 l0 z) m% s1 m0 }
- }
0 `$ v! p! O) f. l - 7 o8 q# U \ b4 a# \
- void BSP_MPU6050_UpdateSensors(void)
% M8 h- ]& n, s - {7 L6 Q3 r( W# h
- uint8_t buffer[14];/ d( T! U0 o& W7 Z. I* T# J
- BSP_MPU6050_ReadMultiReg(MPUREG_ACCEL_XOUT_H,14,buffer);
+ v% d, O% T1 b, f8 r3 J% `6 D - IMU_SensorData_Raw.ACC_X = (buffer[0]<<8)|buffer[1];- W( H% q" ?3 Y8 F8 v# }: P0 y% g
- IMU_SensorData_Raw.ACC_Y = (buffer[2]<<8)|buffer[3];+ F5 z; N/ r' l" j0 c
- IMU_SensorData_Raw.ACC_Z = (buffer[4]<<8)|buffer[5];
& `/ f3 b( `5 j7 ]: N, X - IMU_SensorData_Raw.Temp = (buffer[6]<<8)|buffer[7];5 r& t+ j/ g0 ~" v; c4 f7 P
- IMU_SensorData_Raw.GYR_X = (buffer[8]<<8)|buffer[9];
' n+ X, f Q4 \- p h$ s - IMU_SensorData_Raw.GYR_Y = (buffer[10]<<8)|buffer[11];. A: C4 ~3 j3 S' ^4 Z8 Q+ @! E
- IMU_SensorData_Raw.GYR_Z = (buffer[12]<<8)|buffer[13];+ ]: ?; k- x9 {6 |
- }
复制代码
& K: j+ i; y: W: K8 X8.将以下代码加入bsp_mpu6050.h中
, [$ t+ `1 o+ X+ f k/ s/ A" N- #ifndef BSP_INC_BSP_MPU6050_H_2 A' h7 G: d( V Y
- #define BSP_INC_BSP_MPU6050_H_
& M4 N2 r7 _! o$ Y, V$ N - ! o1 }0 E: S: {
- #define IMU_WHOAMI 0x68: {6 \* L3 c4 V+ i9 t# c8 ?
- #define IMU_ADDRESS_READ 0xD1
& Y: h. B6 b: g) B- X5 x - #define IMU_ADDRESS_WRITE 0xD0
( ]0 H' G$ Z5 }6 @) ]0 u) @9 t
5 @' a2 ~" S4 Q" c% t- #define MPUREG_SMPLRT_DIV 0x19 // sample rate. Fsample= 1Khz/(<this value>+1) = 200Hz1 C" \( ~7 F+ E6 w1 `% |
- #define MPUREG_SMPLRT_1000HZ 0x009 H8 I' ?/ j1 w/ I# n+ a4 Z
- #define MPUREG_SMPLRT_500HZ 0x01
) w0 Q ?! \# g/ W - #define MPUREG_SMPLRT_250HZ 0x03
8 V7 s9 u! `3 B7 O - #define MPUREG_SMPLRT_200HZ 0x04
( G& z) a' S' j# b, m6 \1 j - #define MPUREG_SMPLRT_100HZ 0x09: z; p8 X- ?3 ]0 a1 J- i# S. q% {
- #define MPUREG_SMPLRT_50HZ 0x13$ k8 H( o: \ B. r6 E
- #define MPUREG_CONFIG 0x1A //低通滤波频率# n3 F U* C5 ]4 c
- #define MPUREG_GYRO_CONFIG 0x1B% ]( C- B m% j; A& q9 P4 a
- // bit definitions for MPUREG_GYRO_CONFIG9 G) e2 E& b" x/ X" W9 }7 {
- #define BITS_GYRO_FS_250DPS 0x00/ i; k2 V, q8 A& K {/ E; @
- #define BITS_GYRO_FS_500DPS 0x08* z W' } z0 ?3 F) |( m" C
- #define BITS_GYRO_FS_1000DPS 0x101 @! s6 U" y# Y/ M% K1 b
- #define BITS_GYRO_FS_2000DPS 0x18- o& m, c, m* K' A; n5 L
- #define BITS_GYRO_FS_MASK 0x18 // only bits 3 and 4 are used for gyro full scale so use this to mask off other bits
- I7 _7 L, X9 [: I - #define BITS_GYRO_ZGYRO_SELFTEST 0x206 k6 u5 l$ x# Y+ W# [$ b
- #define BITS_GYRO_YGYRO_SELFTEST 0x40$ I( h L3 R8 V" i
- #define BITS_GYRO_XGYRO_SELFTEST 0x80- D7 t8 u+ T4 V* I, e, g) J" L
- #define MPUREG_ACCEL_CONFIG 0x1C* j# G, f! W X+ e0 d$ ]1 L" A
- #define BITS_ACCEL_FS_2G 0x00
! e6 N- H1 C& v3 R8 E% C( y - #define BITS_ACCEL_FS_4G 0x08
! O2 Y5 n# M, ^% e - #define BITS_ACCEL_FS_8G 0x10
2 @8 f. E- S4 K% w - #define BITS_ACCEL_FS_16G 0x18
& O: K/ l! _5 L0 F7 p& ^9 D - #define MPUREG_INT_ENABLE 0x38 h7 k4 G9 T' t# Z: q' c3 m
- #define MPUREG_ACCEL_XOUT_H 0x3B, ~. _4 E3 S1 }% R- Z/ B
- #define MPUREG_ACCEL_XOUT_L 0x3C7 V; V( P3 W! ]1 z8 }
- #define MPUREG_ACCEL_YOUT_H 0x3D9 {# [0 U. u; K2 O
- #define MPUREG_ACCEL_YOUT_L 0x3E
; v1 k* E9 @6 E9 L* w - #define MPUREG_ACCEL_ZOUT_H 0x3F
& _! _% |8 o7 {% R% ]0 t - #define MPUREG_ACCEL_ZOUT_L 0x40, \6 _% X; \4 {0 I7 u" w
- #define MPUREG_TEMP_OUT_H 0x41
# k% K. s# z/ |- j: H: x: j/ I - #define MPUREG_TEMP_OUT_L 0x42
% r5 N/ I- Q! I$ Z - #define MPUREG_GYRO_XOUT_H 0x43 y; D6 a/ s* e7 }9 U1 F! {! `4 h
- #define MPUREG_GYRO_XOUT_L 0x44
; Y1 b/ S6 L K+ ` X; k+ M) r - #define MPUREG_GYRO_YOUT_H 0x45
# E# X8 ^5 {/ [$ Q% t' E# n! y - #define MPUREG_GYRO_YOUT_L 0x46$ {# [4 v+ B" J6 N/ A
- #define MPUREG_GYRO_ZOUT_H 0x47
" s% r' ?5 a$ k8 t7 p M/ n j - #define MPUREG_GYRO_ZOUT_L 0x48% g8 e$ D/ b8 ^- B9 |6 D
- #define MPUREG_USER_CTRL 0x6A
- v8 @4 s1 A9 u - #define MPUREG_PWR_MGMT_1 0x6B
# H; Q/ }% p& M0 w7 J6 t8 S! ]2 w - #define BIT_PWR_MGMT_1_CLK_INTERNAL 0x00 // clock set to internal 8Mhz oscillator
- X" N) M: } C0 u8 O) Z - #define BIT_PWR_MGMT_1_CLK_XGYRO 0x01 // PLL with X axis gyroscope reference1 G0 l5 M. U6 R: Q/ g9 G
- #define BIT_PWR_MGMT_1_CLK_YGYRO 0x02 // PLL with Y axis gyroscope reference
. C$ w: x" f7 e; W* G) s - #define BIT_PWR_MGMT_1_CLK_ZGYRO 0x03 // PLL with Z axis gyroscope reference8 I* j3 t& _' q: ?: e1 N
- #define BIT_PWR_MGMT_1_CLK_EXT32KHZ 0x04 // PLL with external 32.768kHz reference
) D3 u! |8 y7 S- E) g$ K! U - #define BIT_PWR_MGMT_1_CLK_EXT19MHZ 0x05 // PLL with external 19.2MHz reference
0 K% U) j2 Q1 ^7 y' V4 u. P - #define BIT_PWR_MGMT_1_CLK_STOP 0x07 // Stops the clock and keeps the timing generator in reset9 T. i _7 _$ N3 D
- #define BIT_PWR_MGMT_1_TEMP_DIS 0x08 // disable temperature sensor
/ ^% u k/ F' l3 M3 b - #define BIT_PWR_MGMT_1_CYCLE 0x20 // put sensor into cycle mode. cycles between sleep mode and waking up to take a single sample of data from active sensors at a rate determined by LP_WAKE_CTRL: e& p& O1 K' ?6 B; B; @% a
- #define BIT_PWR_MGMT_1_SLEEP 0x40 // put sensor into low power sleep mode
& C& T# C3 R& D: T/ r+ V - #define BIT_PWR_MGMT_1_DEVICE_RESET 0x80 // reset entire device
2 q1 [3 B s. H+ N" B7 ?% @6 k - 0 r/ M! I# C5 T7 `' G9 R4 Q- Z$ x
- #define MPUREG_PWR_MGMT_2 0x6C // allows the user to configure the frequency of wake-ups in Accelerometer Only Low Power Mode) o3 l- i0 K( s# ?* {; v
- + C& m+ V! P: U+ T# O3 c8 @6 K% J
- #define MPUREG_WHOAMI 0x75
& A7 W$ \. _* J: ~' b
. Z. v6 Z1 {8 F/ Y! Z. {6 U n* W5 Q- #define BITS_DLPF_CFG_20HZ 0x04
+ s* S8 L( |0 I: B4 ]
/ {& k5 E2 C. Y5 ^0 n5 Y- uint8_t BSP_MPU6050_ReadReg(uint8_t address);" X& R" q% G5 n, j1 g, M6 ^) T4 ^
- void BSP_MPU6050_ReadMultiReg(uint8_t address,uint8_t length,uint8_t *data);, Z5 ?! T, d" ~1 o* e1 L
- void BSP_MPU6050_WriteReg(uint8_t address,uint8_t data);
; g- U0 N% R( L. ?. V( z" e6 W - void BSP_MPU6050_WriteMultiReg(uint8_t address,uint8_t length,uint8_t *data);
) m# q9 ]$ N5 l! d+ |, T) W - uint8_t BSP_MPU6050_Read_WHOAMI(void);
8 N2 I+ `9 p2 Z) C4 w1 c - uint8_t BSP_MPU6050_Init(void);
: C7 g7 g- @$ Q) F" D7 T/ x - void BSP_MPU6050_UpdateSensors(void);' N2 G/ Q% ?4 ]. \$ I3 x2 ^
- 0 h7 u1 O8 S0 O2 E/ H/ x
- $ N R* h5 D! |/ D
- typedef struct
) B# w! X1 p/ L" ^ T+ d - {. V* s( c: C& h
- int16_t ACC_X;
) X1 @) l) \3 q- c& c - int16_t ACC_Y; R, M2 L) f4 v/ c( _# e; R
- int16_t ACC_Z;) |) Q) q( H& h. F+ t! |
- int16_t GYR_X;6 Q, c$ [/ I* q3 {" S% i$ e
- int16_t GYR_Y;
3 N" a0 v3 ?& E" `! c$ y! F - int16_t GYR_Z;
T9 E- u t7 _' X" p+ _- | - int16_t Temp;
% A/ h8 \: k2 ^5 C7 k' b0 a$ l - }IMU_SensorData_Raw_Structer;2 a- v, ?& O. E
, ^% h X% }/ b- #endif /* BSP_INC_BSP_MPU6050_H_ */
复制代码 / V2 w" t1 E7 T( N& z
9.把以下代码加入main.h中+ ?+ Y, C; g- F [
% X) H, R) ~4 w! v O
7 N) |1 X' R6 x# a8 \- ~7 L
+ e6 I0 M/ ?) K s) s1 w10.点击编译并烧录,烧录完成后,把bsp_mpu6050.h文件中的机构体IMU_SensorData_Raw复制到右上角现场表达式中。
4 N' W4 d' _8 {/ a. e6 _8 _. \* Y; e3 W
L7 T+ C9 {8 O1 g# ^: o% K
8 Y4 I" @9 [7 y8 R3 i11.点击运行,可在现场表达式中观察到MPU测量出的数据。3 ~6 e' X7 `( d
# J7 e. V! N- n7 ^. S/ L
" F2 @+ a* r. a- j- h$ {: s0 i- H% [2 F& V; R
' v) H( C8 I. G- b, R; [
. s: q1 ?' g( W- c6 F# \2 u: w0 `7 P
|