MPU6050简介:
5 p2 v$ O- ] P; EMPU6050是InvenSense公司推出的全球首款整合性6轴运动处理组件,内带3轴陀螺仪和3轴加速度传感器,并且含有一个第二IIC接口,可用于连接外部磁力传感器。
& b" h/ e c- _% R. ?3 x3 F5 s" c那如何通过MPU6050传感器来获取数据呢?: d% G- I% |0 W1 |: A/ I
具体步骤如下:+ y/ U0 I9 z; s% V+ Q, C3 S
. i1 |8 O4 d: b, W9 N$ q+ M/ q1.新建项目:$ [% V" S, h: k% E
. x( i/ ^3 z- ^4 N I
6 ~0 u9 {8 T7 i+ F, A+ U
- V) q9 [$ u' [; O4 s2.选择STM32F103C8T6芯片# U, u' M! v3 n3 s: @# W
7 K+ a8 f% Y' N% q" g, g. m( |
9 z6 d3 G& {% R6 }7 a# b# t, r5 _# H
3.对工程文件命名
6 o5 ^$ F) b3 v5 t1 n
7 F& U( s3 T9 o) E3 D; H& W# C
9 H2 ?; R; W) X T1 I8 m' q1 {
# r& i$ t/ C) `/ U# _. q( X
4.在Connectivity中选择I2C1,在mode中选择I2C
( N9 q' g* V6 x4 G
! \7 S7 }0 K9 @: P6 X, W2 G4 H
h* ^7 h/ A& k: R: _
6 o5 V* j9 f, H3 w/ v# @. h" \( @ 5.根据原理图选择引脚) x4 p1 w; m7 o# @$ @+ j
其中MPU6050中的SCL和SDA应对应于C8T6主控模块上的PB8和PB9,故应在右侧引脚设置中单击PB9,PB8引脚,选择I2C1_SDA项。
m2 ^/ p/ ^1 V9 K$ l7 g* B* A T# c& a# H7 C( h
( [* o0 Z o! p4 d0 u4 V1 y! q. ^
5 ~3 ?$ A5 B% i3 @: l9 [
/ ^: }7 W# b5 V' Q6.点击生成代码,在MPU6050下新建一个User文件夹,在User文件夹下新建一个BSP文件夹,在BSP文件夹下添加Inc和Src文件夹,并在Inc和Src文件夹下添加bsp_mpu6050.c和bsp_mpu6050.h文件。(注意新建的文件夹需要设置路径)$ o4 M6 V! s* L- k
新建的User文件夹,设置路径:
: t1 G; e l! }- w n5 y9 d+ t/ F9 r
; l5 d/ ~1 h' o3 e7 n(只有设置完路径后才能添加的上.c和.h文件)
3 T% n- U4 L0 n. [+ ^0 {
" e- E C8 M/ L2 G
! x& R2 x/ m: E& F& s
! G" T; y0 f2 p4 I P% ?
再添加.c和,h文件
& h' b& x/ [; a' T' v, h& K
0 Z1 ~. t1 p- a. C( `' K
$ ~6 o* x+ ~8 x5 c: X7 s9 F1 t. E6 y5 {; q" }
7.把以下代码加入bsp_mpu6050.c
5 d, }( }' W! O @0 \# t- F/ _' H8 ^$ F% B- #include "main.h"! } p" q% K7 F0 E% V# h
- ; r5 c9 _' F2 n
- extern I2C_HandleTypeDef hi2c1;- R8 ~# E& I) g8 g$ R6 i0 w
+ U8 L0 F+ w# d5 \6 q% e7 Y- IMU_SensorData_Raw_Structer IMU_SensorData_Raw;6 ^; D& @$ s6 w# l4 v3 ^" V/ m
- # |& K! H- F4 A: b5 o, l3 o
- uint8_t BSP_MPU6050_ReadReg(uint8_t address); c" K0 O1 w/ I0 C. D, i0 A
- {
8 }2 A! v" }9 {+ U. | s# {5 b - uint8_t Value = 0;
# Z* K! j9 G9 {0 d: e - HAL_I2C_Mem_Read(&hi2c1,IMU_ADDRESS_READ,address,I2C_MEMADD_SIZE_8BIT,&Value,1,0x10);
) f: m& U I c( G' x# r1 m& a' H - return Value;* M+ A4 R+ G0 p$ i$ G
- }( A8 i7 a; j( b, i5 M% l( W( ?
- / m4 _& C, I5 r' g% m
- void BSP_MPU6050_ReadMultiReg(uint8_t address,uint8_t length,uint8_t *data)
2 W' g5 C, j4 Z% Z H - {
9 G, m. `6 R2 [7 \ - HAL_I2C_Mem_Read(&hi2c1,IMU_ADDRESS_READ,address,I2C_MEMADD_SIZE_8BIT,data,length,0x10);2 k# O d }2 W& m. u
- }
& H9 ?3 f5 o/ w; a; Y - 5 r# X4 |* V1 b5 E
- void BSP_MPU6050_WriteReg(uint8_t address,uint8_t data)
" u( _2 ^: w' s( H3 s K8 ]5 i - {4 z7 N2 u4 e. d) x% ?
- HAL_I2C_Mem_Write(&hi2c1,IMU_ADDRESS_WRITE,address,I2C_MEMADD_SIZE_8BIT,&data,1,0x10);, G5 u8 [0 L+ R( n8 ?( n6 z3 l5 L
- HAL_Delay(100);
( y& H3 t% l0 m - }& G& u& G. P) }0 |' m8 C
- ' m x' U9 ^( d' d
- void BSP_MPU6050_WriteMultiReg(uint8_t address,uint8_t length,uint8_t *data)
8 I$ m1 ^7 S( `1 n" G' k$ p/ f2 Z - {
: y4 ]2 ^9 Z& B. G; b - HAL_I2C_Mem_Write(&hi2c1,IMU_ADDRESS_WRITE,address,I2C_MEMADD_SIZE_8BIT,data,length,0x10);
! ^. _3 a, N! V6 p' F- m" V8 `9 [% A# o - HAL_Delay(100);. @ A9 {* B2 k
- }0 @0 a3 p& T% h! [9 @5 Y5 r
7 m1 F# D! i W0 j3 O- uint8_t BSP_MPU6050_Read_WHOAMI(void)- J3 a+ N5 X% H1 ?6 w, k _
- {
4 w+ P7 c- [9 e4 n6 B; z - return BSP_MPU6050_ReadReg(MPUREG_WHOAMI);2 o) c$ }3 m7 C$ ?# [& _
- }
) y2 ]" C ?! T0 m
3 h, q/ c1 D: d1 D- x( [; }- uint8_t BSP_MPU6050_Init(void)6 V6 t+ S6 T0 j( |" c, Q& Q5 a) r
- {
- c4 i5 u& H5 [0 ^ - uint8_t tries;; _* `& D: T1 g9 r/ w
?" J3 W) m- p# o" P& }( t/ ~- for(tries = 0; tries<5; tries++)$ g" T* d* d. f1 _8 ]( S! X! L8 ]
- {
" I1 \0 y% r: R% l: K - BSP_MPU6050_WriteReg(MPUREG_PWR_MGMT_1,BIT_PWR_MGMT_1_DEVICE_RESET);//复位MPU6050
8 [, L3 Q% l& U5 k - BSP_MPU6050_WriteReg(MPUREG_PWR_MGMT_1,BIT_PWR_MGMT_1_CLK_ZGYRO);//设置时钟
# N/ x* v, ~4 [" @, S - if(BSP_MPU6050_ReadReg(MPUREG_PWR_MGMT_1) == BIT_PWR_MGMT_1_CLK_ZGYRO)//判断是否写入,写入则跳出循环
' {: }. [$ y8 s6 Q - break;$ F0 Z2 n$ S0 H W
- }0 @4 V8 f# K$ [
- if(tries == 5)
: I- R6 i+ b0 D4 V# { - return 0;. O2 q5 L7 x7 z6 h3 O
- 6 X5 \3 o A* U- J# O, O) U/ n' i2 N
- BSP_MPU6050_WriteReg(MPUREG_PWR_MGMT_2,0x00);//禁止休眠; O( h' T/ N8 y* z$ b
- BSP_MPU6050_WriteReg(MPUREG_USER_CTRL,0x00);//I2C主模式关闭
" J$ K/ L1 ]' x5 b; q+ a - BSP_MPU6050_WriteReg(MPUREG_CONFIG,BITS_DLPF_CFG_20HZ);//设置低通滤波器6 f3 B+ [3 K; i
- BSP_MPU6050_WriteReg(MPUREG_SMPLRT_DIV,MPUREG_SMPLRT_200HZ);//设置采样频率2 j# a. t. X" Z. d& E
- BSP_MPU6050_WriteReg(MPUREG_GYRO_CONFIG,BITS_GYRO_FS_2000DPS);//设置陀螺仪量程0 V/ {% r f X+ c9 { `
- BSP_MPU6050_WriteReg(MPUREG_ACCEL_CONFIG,BITS_ACCEL_FS_8G);//设置加速度计量程& C4 n x3 S" e1 o6 l8 k. D
- BSP_MPU6050_WriteReg(MPUREG_INT_ENABLE,0x00);//禁止中断0 s6 q! C; l- `& k" p2 U2 Y
* Z& |5 U( M0 I$ n& }( g9 g, H- if(BSP_MPU6050_Read_WHOAMI() == IMU_WHOAMI)' L$ J9 r5 q: I
- return 1;8 v# f5 @ ^1 C
- else
4 K. C5 V! d. o1 k3 X8 G' I - return 0;
|' ]/ A/ C/ i - }
& X, |! Y/ _5 R, Z$ r* i
* U$ ~& [+ S, o6 E- void BSP_MPU6050_UpdateSensors(void)% |; q& s6 i$ s3 G" \( w* W
- {1 _. X4 l( Y: q" i. I
- uint8_t buffer[14];
* k% ~- L+ x$ Q* U - BSP_MPU6050_ReadMultiReg(MPUREG_ACCEL_XOUT_H,14,buffer);& s, f" y. n! r8 f9 c8 R( h* j
- IMU_SensorData_Raw.ACC_X = (buffer[0]<<8)|buffer[1];
/ B4 F5 B) W) P4 k: I& d- f - IMU_SensorData_Raw.ACC_Y = (buffer[2]<<8)|buffer[3];, k' v2 Z4 a7 v+ `8 }0 L! M
- IMU_SensorData_Raw.ACC_Z = (buffer[4]<<8)|buffer[5];% O T6 N$ ] @: Y
- IMU_SensorData_Raw.Temp = (buffer[6]<<8)|buffer[7];' U0 \7 T! e J, f
- IMU_SensorData_Raw.GYR_X = (buffer[8]<<8)|buffer[9];. G; N7 R" v b4 c! T
- IMU_SensorData_Raw.GYR_Y = (buffer[10]<<8)|buffer[11];
- W6 z6 X: c. |& F2 y2 w* v K* P - IMU_SensorData_Raw.GYR_Z = (buffer[12]<<8)|buffer[13];* d# J+ h& H; A6 U8 ]) D
- }
复制代码
& q+ } n i! I: d6 G$ s# x8.将以下代码加入bsp_mpu6050.h中
" `6 m( X+ F4 V8 m- #ifndef BSP_INC_BSP_MPU6050_H_
- R; g. e4 q, u - #define BSP_INC_BSP_MPU6050_H_
* a; ^# p% O2 s! t4 N, w. m - / K$ k- h: }/ O# g( R
- #define IMU_WHOAMI 0x68
6 P- n6 D9 R4 F0 j4 w - #define IMU_ADDRESS_READ 0xD1
) e5 m- _8 V, u$ ?9 } - #define IMU_ADDRESS_WRITE 0xD0# m" w0 E( \' E/ w/ m
/ D; v9 @8 A1 M) Z; E$ A: J+ O- #define MPUREG_SMPLRT_DIV 0x19 // sample rate. Fsample= 1Khz/(<this value>+1) = 200Hz8 i0 y1 v, n1 L2 ^
- #define MPUREG_SMPLRT_1000HZ 0x00$ v' y; X/ w: i. f- `' h% W5 |$ i' L
- #define MPUREG_SMPLRT_500HZ 0x01
! \/ k: \( e' W0 } - #define MPUREG_SMPLRT_250HZ 0x03
) }; p- G7 s0 s, r - #define MPUREG_SMPLRT_200HZ 0x04
2 S8 x* }! W2 p3 Q+ S4 x- M - #define MPUREG_SMPLRT_100HZ 0x090 a1 _6 e/ c$ S: f: C
- #define MPUREG_SMPLRT_50HZ 0x139 Y2 v, M8 q1 d$ l& \6 b
- #define MPUREG_CONFIG 0x1A //低通滤波频率
4 G0 {4 }% |0 S' O& n6 G; F - #define MPUREG_GYRO_CONFIG 0x1B
8 J1 c! ^+ R1 L9 H6 S - // bit definitions for MPUREG_GYRO_CONFIG
5 f/ ^6 z" K* l5 q! M - #define BITS_GYRO_FS_250DPS 0x003 k7 q% {" h5 Q; V
- #define BITS_GYRO_FS_500DPS 0x08
# J4 z0 ]9 [! J: n - #define BITS_GYRO_FS_1000DPS 0x10$ ?0 ?. d1 ~% Z1 ?0 N0 u
- #define BITS_GYRO_FS_2000DPS 0x18: k2 v3 e; ]& n W
- #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
, g" k6 B4 B. u5 q; Q5 d - #define BITS_GYRO_ZGYRO_SELFTEST 0x20
- \+ {4 X1 ^: U4 w - #define BITS_GYRO_YGYRO_SELFTEST 0x40
* U1 d. |2 b) X: o& S% f - #define BITS_GYRO_XGYRO_SELFTEST 0x80. j* j4 \; v3 p$ l+ O
- #define MPUREG_ACCEL_CONFIG 0x1C8 ^5 n: u1 ~+ K( T
- #define BITS_ACCEL_FS_2G 0x00
8 }4 r$ W5 q, d - #define BITS_ACCEL_FS_4G 0x08' G5 _5 z, o' f5 Y
- #define BITS_ACCEL_FS_8G 0x10) a) r, a& [' v% b- T4 M/ i
- #define BITS_ACCEL_FS_16G 0x18
) p" E/ y9 [" ^5 }5 t y! e - #define MPUREG_INT_ENABLE 0x38) p5 b/ I: |8 Q; Y' B( x, `
- #define MPUREG_ACCEL_XOUT_H 0x3B5 ]3 e( I7 L& y8 C$ E; }. g
- #define MPUREG_ACCEL_XOUT_L 0x3C6 b* C' @" n$ p' {/ a0 P2 B
- #define MPUREG_ACCEL_YOUT_H 0x3D
& N9 I9 t _% R2 q+ D - #define MPUREG_ACCEL_YOUT_L 0x3E* ^" l/ `' @# I: c% o' L$ `5 U
- #define MPUREG_ACCEL_ZOUT_H 0x3F
h7 M% ~" g( [- l' \- h. v - #define MPUREG_ACCEL_ZOUT_L 0x40
- R$ U/ I3 ] M! Z+ K3 w |% { - #define MPUREG_TEMP_OUT_H 0x41( ^9 j: Z+ F# V+ F3 T% l
- #define MPUREG_TEMP_OUT_L 0x421 c' U3 k# G5 G, }( t H
- #define MPUREG_GYRO_XOUT_H 0x434 p4 I- |6 t2 A$ H4 F* X4 o, f6 u5 B
- #define MPUREG_GYRO_XOUT_L 0x44
% t4 L5 F1 R) }' {) |( ^ - #define MPUREG_GYRO_YOUT_H 0x45
+ Z% x' q- Z) l, X4 S - #define MPUREG_GYRO_YOUT_L 0x46
! R: y% O- T' X - #define MPUREG_GYRO_ZOUT_H 0x47
% h6 u* g1 N% } S0 I$ a$ B - #define MPUREG_GYRO_ZOUT_L 0x48+ P/ l! j4 S# m0 N8 X+ {+ M
- #define MPUREG_USER_CTRL 0x6A
! p5 ?% i" L9 d! k! ]6 y9 [, r - #define MPUREG_PWR_MGMT_1 0x6B- G" m" {: F) A
- #define BIT_PWR_MGMT_1_CLK_INTERNAL 0x00 // clock set to internal 8Mhz oscillator
- r& y; y4 G9 h4 U& ? - #define BIT_PWR_MGMT_1_CLK_XGYRO 0x01 // PLL with X axis gyroscope reference
5 A# ^& n( E6 Y( X( a+ K - #define BIT_PWR_MGMT_1_CLK_YGYRO 0x02 // PLL with Y axis gyroscope reference0 e1 Z, N5 \) f! ]5 m
- #define BIT_PWR_MGMT_1_CLK_ZGYRO 0x03 // PLL with Z axis gyroscope reference
" s! R# _8 i( X - #define BIT_PWR_MGMT_1_CLK_EXT32KHZ 0x04 // PLL with external 32.768kHz reference) ]4 _7 j% s9 K/ ]0 Y
- #define BIT_PWR_MGMT_1_CLK_EXT19MHZ 0x05 // PLL with external 19.2MHz reference! P0 J1 X& k! K; e& O
- #define BIT_PWR_MGMT_1_CLK_STOP 0x07 // Stops the clock and keeps the timing generator in reset
" h5 V# `& b8 l: ?! |/ i: d - #define BIT_PWR_MGMT_1_TEMP_DIS 0x08 // disable temperature sensor
) Z' }9 G' ^+ x - #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_CTRL0 M6 c: D2 E t! V7 d, r
- #define BIT_PWR_MGMT_1_SLEEP 0x40 // put sensor into low power sleep mode
1 f# W# y. `. ` H6 q - #define BIT_PWR_MGMT_1_DEVICE_RESET 0x80 // reset entire device
& q; ^* o' ^$ H; C0 a0 y4 d$ F; V6 J - - `# w: E! c2 ~, t8 J6 j& }6 i
- #define MPUREG_PWR_MGMT_2 0x6C // allows the user to configure the frequency of wake-ups in Accelerometer Only Low Power Mode) L x( k+ q" X: v( |: j
! D4 h4 ~8 k1 G2 K9 L( P6 h2 W7 t- #define MPUREG_WHOAMI 0x75$ S$ a+ {& H _
- + g: g3 i% Q& @3 Y/ q
- #define BITS_DLPF_CFG_20HZ 0x04( G. _2 Y ^' n0 s5 x
" {! v1 T d3 [% t- uint8_t BSP_MPU6050_ReadReg(uint8_t address);
/ \- A) r: ^: y - void BSP_MPU6050_ReadMultiReg(uint8_t address,uint8_t length,uint8_t *data);' ~4 w5 K$ g" F& A- C0 f5 `/ J2 W
- void BSP_MPU6050_WriteReg(uint8_t address,uint8_t data);
# V( ]6 s8 v: P; U' x: {3 |" S' a - void BSP_MPU6050_WriteMultiReg(uint8_t address,uint8_t length,uint8_t *data);
! [/ Y* Q6 R( w* j/ a - uint8_t BSP_MPU6050_Read_WHOAMI(void);& o7 B8 ]( U9 y* J: G# X. Y
- uint8_t BSP_MPU6050_Init(void);% q4 S+ I% w. m
- void BSP_MPU6050_UpdateSensors(void);, o" f' n: h$ P& P+ _
- 4 v q% y2 L/ |# a& H
1 n+ `- l! |) i% L9 U% y$ u- typedef struct4 \# F3 E6 q( A
- {
- V8 p+ [- o. Y8 [6 k' c - int16_t ACC_X;
3 p9 z, q2 \0 N( [ - int16_t ACC_Y;
0 s1 y9 a, _0 l% w - int16_t ACC_Z;/ M- y) ~. ^# b; d
- int16_t GYR_X; k3 `. L) K! y9 \& @7 C
- int16_t GYR_Y;2 c3 Y. e+ ^+ f& K; q& Y
- int16_t GYR_Z;
- G% {( _' j; D+ O - int16_t Temp;6 p' S# x2 u4 s1 {* e
- }IMU_SensorData_Raw_Structer;
) H+ t$ Z$ Y J0 w+ S% `5 t - ' M' @; B! q5 {3 t
- #endif /* BSP_INC_BSP_MPU6050_H_ */
复制代码 * d" G! z5 I! p1 y/ ]% V4 F
9.把以下代码加入main.h中
3 ^% d. `% F( v+ {# [
; Q8 f+ p. ^1 a) O3 ~) \( j
) L6 [# e$ J; [# g+ t
% [1 ?, t1 i/ x: g( O5 {10.点击编译并烧录,烧录完成后,把bsp_mpu6050.h文件中的机构体IMU_SensorData_Raw复制到右上角现场表达式中。
/ D% [( w4 z w7 U( E/ q( d! B
. A) N- X; m- R# o ]( q
0 l5 n; e4 T% o: @
0 l. _# P8 j. j$ d, J11.点击运行,可在现场表达式中观察到MPU测量出的数据。
) l5 `; A9 D- |$ V2 S* _/ I/ o
# ~/ y1 t, k: A Y3 j2 J% [
. n) F% s9 ~8 a4 l# E3 i& e
; ?7 c x( i0 `
, W# X& X( L5 S% j3 P2 _
9 }# s N, y' G- v7 a
# X+ p+ F$ R$ o, |+ \! k |