你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32心得三十七:MPU6050六轴传感器实验

[复制链接]
STMCU小助手 发布时间:2022-11-18 19:00
主要内容:8 [; r% Y8 X$ g* F/ q" K
1)MPU6050简介;# }; u9 k/ g; V
2)MPU6050相关寄存器介绍;
, x; p# E6 S0 T/ e8 b* }7 B  J9 L3)相关实验代码解读(除了案例可实现的功能外,主函数增加了在LCD屏上显示6轴的原始数据(含正负号)的功能)。* A% B3 L2 z6 R2 d: ~+ {% S9 {
/ K" U' c* h4 E
一、什么是MPU6050?& x+ Z0 ]% ]0 p0 F0 _
MPU6050是InvenSense公司推出的全球首款整合性6轴运动处理组件,内带3轴陀螺仪和3轴加速度传感器,并且含有一个第二IIC接口,可用于连接外部磁力传感器,利用自带数字运动处理器(DMP: Digital Motion Processor)硬件加速引擎,通过主IIC接口,可以向应用端输出完整的9轴姿态融合演算数据。. j4 y; ~, D! x( ^

: [. g6 g5 T# k/ ]% o% Z二、MPU6050特点$ g6 W1 ~# l0 G( P/ p
1)自带数字运动处理(DMP: Digital Motion Processing),输出6轴或9轴(需外接磁传感器)姿态解算数据;
1 H5 y! ^0 W* o+ l, ]2)集成可程序控制,测量范围为±250、±500、±1000与±2000°/sec 的3轴角速度感测器(陀螺仪);
, h" A8 e; d' A: f; ^1 l- ?- F# d3)集成可程序控制,范围为±2g、±4g、±8g和±16g的3轴加速度传感器;
: N& x$ }. \; p7 H8 c& B4)自带数字温度传感器;2 d1 f5 R: l. b4 }5 l
5)可输出中断(interrupt),支持姿势识别、摇摄、画面放大缩小、滚动、快速下降中断、high-G中断、零动作感应、触击感应、摇动感应功能;
  _0 Y( V7 G4 r6)自带1024字节FIFO,有助于降低系统功耗;
- I; n8 q+ `0 ]+ q2 e. r9 c, o: L7)高达400Khz的IIC通信接口;
8 N, [8 M1 A( X# s+ d6 W8)超小封装尺寸:4x4x0.9mm(QFN)。6 t9 w& P+ e5 k" n7 s: s) z' H6 Y$ M
) M8 K5 n  Y0 r& H
三、MPU6050框图
/ k8 _( E$ g" c1 k1 ` 20201202115316729.png $ y$ O. r$ x8 B/ k8 W# M- _; c$ s
AD0=0对应器件物理地址=0X68
6 |! S0 ~2 @% @  `" j) B- p3 V7 kAD0=1对应器件物理地址=0X69/ Y% F9 O% H) |* d6 |
3 ]# N9 f$ ]# n1 C4 ]/ c; a; j1 u' D
四、MPU6050初始化
7 O, U3 [) a* H1 n. d1)初始化IIC接口;' W2 Y9 G$ y+ A
2)复位MPU6050,由电源管理寄存器1(0X6B)控制;
* |6 O8 E0 F5 Y2 T! D1 P: g3)设置角速度和加速度传感器的满量程范围,由陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置 ;/ `/ c8 x  `3 a  z5 b6 D! ?$ _
4)设置其他参数:
4 F4 `7 n  S5 g. H6 A' K设置中断,由中断使能寄存器(0X38)控制;8 ^( u" j( I& I7 z" Y' d8 ]/ e
设置AUX IIC接口,由户控制寄存器(0X6A)控制;. U0 v9 @- t4 n0 |: J: c! l
设置FIFO,由FIFO使能寄存器(0X23)控制;
& s8 M" s; o( B! ^$ N2 t设置陀螺仪采样率 ,由采样率分频寄存器(0X19)控制;
. W1 {+ n8 n8 W0 j设置数字低通滤波器,由配置寄存器(0X1A)控制;' H9 J/ Y5 n- x6 a  \8 `4 Q( }
5)设置系统时钟。由电源管理寄存器1(0X6B)控制。一般选择x轴陀螺PLL作为时钟源,以获得更高精度的时钟;
  l6 V8 ^2 I7 S0 \2 \# u6)使能角速度传感器(陀螺仪)和加速度传感器。由电源管理寄存器2(0X6C)控制。6 r7 p. a! o- A  T' O0 h, Y; }" r
初始化完成后,即可读取陀螺仪、加速度传感器和温度传感器的数据了!!) m7 U# I/ ]7 P; U
6 g) T& U3 m7 ^$ S: W
五、主要的寄存器介绍
: I+ U: [: u* C- p5.1)电源管理寄存器1(0X6B)' |" ~8 n4 p( R

" J# P8 h! ?9 l) I0 O8 A 20201202124650455.png : |2 p2 n3 G' [9 o" g) j

7 w, _: C9 a1 S9 O5 p2 j( y" bDEVICE_RESE=1,复位MPU6050,复位完成后,自动清零;# d) g5 z, K2 L9 q
SLEEP=1,进入睡眠模式;SLEEP=0,正常工作模式;2 Q& U1 Z- U* o* r2 R  |) J" d: Y
TEMP_DIS,用于设置是否使能温度传感器,设置为0,则使能;
' y( y. i9 e9 a& Z6 N$ nCLKSEL[2:0],用于选择系统时钟源,如下表所示:8 x3 E6 H% O' s/ {( Q: e
( _' c7 p" T( U" G6 J& j- e, O4 w& w
20201202124734929.png   p/ @+ U) b7 O( M4 @0 i: P

$ |6 O" B; n/ |) q) X3 P5.2)陀螺仪配置寄存器(0X1B); l9 {3 U, R) R& J, Z- U; P* a

2 b$ l6 y* a' e2 [& \1 b& Z 20201202124826207.png
: r0 V; z* [9 e) p2 x* |7 D# d7 Z" E+ V- t' |. ]: Y0 o
主要关注FS_SEL[1:0]这两个位,用于设置陀螺仪的满量程范围:6 b  D) A* p, g5 F# U  f# V
0,±250°/S;1,±500°/S;2,±1000°/S;3,±2000°/S;
- F, g8 q3 ^& v" c8 b. P6 x0 M5 u  @一般设置为3,即±2000°/S,因为陀螺仪的ADC为16位分辨率,所以灵敏度为:65536/4000=16.4LSB/(°/S)。
. q2 l) i4 s1 R0 W8 ?0 i( L/ S$ f- c
  i  X2 T5 g/ ]2 P* K: ]5 X% F5.3)加速度传感器配置寄存器(0X1C)& C7 \  p% _* j: J( q3 `" w

/ ?- e$ b! _7 y5 E3 q& `1 {5 G 20201202124906190.png
2 p6 R$ Z' v/ `8 A/ z$ Y9 V* x4 B0 [+ o& Y9 R3 v2 ?
主要关注AFS_SEL[1:0]这两个位,用于设置加速度传感器的满量程范围:: L# Q$ p; U7 }5 S7 E  f& d( k
0,±2g;1,±4g;2,±8g;3,±16g;3 C0 ^- p; u) R4 ]+ P8 T
一般设置为0,即±2g,因为加速度传感器的ADC是16位,所以灵敏度为:65536/4=16384LSB/g。
& Z8 j& a7 E8 E1 d8 V9 l; x6 z: V/ l& O+ K; ]. p$ h
5.4)FIFO使能寄存器(0X23)
4 H9 W+ C! s5 f) ~9 p3 v
. ?; r, f$ u+ w, |1 w+ l7 D, u6 t 20201202124951209.png   A) G- k: e* @* o/ C

: B+ a! [8 c- j: {% k5 N该寄存器用于控制FIFO使能,在简单读取传感器数据的时候,可以不用FIFO,设置对应位为:0,即可禁止FIFO,设置为1,则使能FIFO。+ ?4 e+ I- p  B3 _: J# v6 y8 o
注意:加速度传感器的3个轴,全由1个位(ACCEL_FIFO_EN)控制,只要该位置1,则加速度传感器的三个通道都开启FIFO了。( N7 K) O* l; L4 d

& n5 @  V6 i2 K, q' I2 {7 g) u5.5)陀螺仪采样率分频寄存器(0X19)
6 U/ K4 o+ o0 |+ a. |8 ]4 t+ Q) `: v: @( b% X
2020120212502194.png 6 I) A5 G$ w8 y: C9 S/ h: L, d

6 h: E2 i+ \- ^+ `$ T3 `5 Y4 {该寄存器用于设置MPU6050的陀螺仪采样频率,计算公式为:  D' D4 C: h! o; r
采样频率 = 陀螺仪输出频率 / (1+SMPLRT_DIV)
. v' t  g, L9 R  S- `, W3 Z$ @% @这里陀螺仪的输出频率,是1Khz或者8Khz,与数字低通滤波器(DLPF)的设置有关,当DLPF_CFG=0或7的时候,频率为8Khz,其他情况是1Khz。而且DLPF滤波频率一般设置为采样率的一半。采样率,我们假定设置为50Hz,那么:SMPLRT_DIV=1000/50-1=19。# G; h( }+ i8 \: S6 o
* d! V+ e' ?6 A/ |* N
5.6)配置寄存器(0X1A)
! y. N* W  @3 N7 G/ B8 V0 C3 H9 A+ Q
20201202125111514.png
6 u8 {3 @, p) e# \. H, E* N7 U) O$ K( d1 z! ]
重点看数字低通滤波器(DLPF)的设置位:DLPF_CFG[2:0],加速度计和陀螺仪,都是根据这三个位的配置进行过滤的,如下表所示:
, \( A2 i0 _9 z' ]: d% t) r7 e. S
20201202125128497.png 0 c0 A  k( N; }9 A

; L2 c& z1 k" B* s备注:带宽=1/2采样率. n* |! M, R' @$ l$ X
1 c+ b1 o4 d$ D% Q+ `; L
5.7)电源管理寄存器2(0X6C)
  J3 m' p6 [0 i3 P& W- q- L/ Q  m, b/ m- J& e" F3 C: d
20201202125210534.png
$ ]( E2 N) x! ^' k1 X; }  a+ R& ^5 N0 v# e- T) t* g7 o
该寄存器的LP_WAKE_CTRL用于控制低功耗时的唤醒频率;
5 o8 p5 A+ B+ `! k$ [7 w剩下的6位,分别控制加速度和陀螺仪的x/y/z轴是否进入待机模式;
! _9 F( Y. u1 y1 t& u3 p0 W本例程全部设置为:0 ,即可。. Y0 }3 {1 o+ S% f0 L
6 g6 J: Y) v; q" c# |9 J
5.8)加速度传感器数据输出寄存器(0X3B~0X40)! a8 c4 o8 E* g. P0 d' F

  K) M# q% B; Q 20201202125232456.png / w- Z4 q" I3 H0 B2 n% }# B
! d" j# l3 I# U1 n% u
总共由6个寄存器组成,输出X/Y/Z三个轴的加速度传感器值,高字节在前,低字节在后。
/ z# j' F0 T3 b* g* H* o) t7 r. I3 T% a
5.9)陀螺仪数据输出寄存器(0X43~0X48)4 a* ^6 O6 u$ k7 t7 G

" h" \9 a+ I% E, y/ f 20201202125315716.png 5 a1 J; x, K& i: s7 r
( r- a( M* g& x: p; n
总共由6个寄存器组成,输出X/Y/Z三个轴的陀螺仪传感器数据,高字节在前,低字节在后。$ W, ^, ]2 U& r( d5 T$ t* k# F$ @0 b

+ o. s& O% P, M  _! G6 a5.10)温度传感器数据输出寄存器(0X41~0X42)7 X% `4 W2 T5 d' m
3 O4 j4 w. R; Y
20201202125336901.png
( I0 W6 b2 r- K7 x
% J: _& c) B; p9 @+ K通过读取0X41(高8位)和0X42(低8位)寄存器得到,温度换算公式为:
" G! w& t. M+ q, m& KTemperature = 36.53 +regval/340% f( |' @0 f8 t5 }
其中,Temperature为计算得到的温度值,单位为℃,regval为从0X41和0X42读到的温度传感器值。7 e9 Z: _) V% m! X, ]; M

# y  I* x3 u' n1 U* r六、DMP使用介绍& \# W" g$ p6 n& m
实际使用时(比如做四轴),我们更希望得到姿态数据,即欧拉角:航向角(yaw)、横滚角(roll)和俯仰角(pitch)。, m  N* ^; k8 a* J) y. X" i( r6 G
要利用原始数据,需要进行姿态融合解算。MPU6050自带数字运动处理器,即DMP,并且InvenSense提供了一个MPU6050的嵌入式运动驱动库,结合MPU6050的DMP,可以基于原始数据直接转换成四元数输出,而得到四元数之后,便可很方便的计算出欧拉角,从而得到yaw、roll和pitch。
6 B2 @. X5 s1 Z$ \备注:InvenSense提供的MPU6050运动驱动库是基于MSP430的,需要将其移植后才可以用到STM32上面。8 t: E, S& u1 v/ R( C7 ?

! u: a, `; M$ H$ @( u. \4 q移植细节:
0 C& {" f+ O8 M/ N4 W官方DMP驱动库移植,主要是实现这4个函数:i2c_write、i2c_read、delay_ms和get_ms。
& q1 [" i5 O3 K$ f$ J, L移植后的驱动代码如下图:
) c3 c0 O  d( Z. B+ ~8 O  h! u: p- P8 e" l, g9 r! b$ V: V
20201202125526501.png
' g2 b) f3 K. }% u1 r* p/ r8 m& k+ }
MPU6050 DMP输出的是姿态解算后的四元数,采用q30格式,即2的30次方,要得到欧拉角,需要做一个转换,代码如下:% V4 W. S9 ^& Z

; f) o" ]# o. A$ M# I# I9 \- |
  1. q0=quat[0] / q30;   // q30格式转换为浮点数; \4 }0 w5 B9 b
  2. q1=quat[1] / q30;   // q30格式转换为浮点数
    2 a; e) }7 a9 y2 i
  3. q2=quat[2] / q30;   // q30格式转换为浮点数( r/ [* j& P' e  b
  4. q3=quat[3] / q30;   // q30格式转换为浮点数
    ! ~4 Z" Z) d+ ^: u! a- M9 ]" q
  5. // 计算得到俯仰角/横滚角/航向角( ~9 h4 e3 F3 S$ D# D/ d7 }7 g- G; c
  6. pitch=asin(-2 * q1 * q3 +2 * q0* q2)* 57.3;      // 俯仰角
    : Z6 l! C; f' f1 V4 ?6 s
  7. roll=atan2(2 * q2 * q3 +2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // 横滚角yaw=atan2(2*(q1*q2 +
    ) _/ ]3 j$ H+ b* t9 p  I
  8. q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3;          // 航向角
复制代码

6 r8 }% s7 U7 @. a* v* }/ y+ d上述代码中:quat[0]~quat[3]:是MPU6050的DMP解算后的四元数,q30格式; q30:是一个常量:1073741824,即2的30次方; 57.3:是弧度转换为角度,即180/π,这样结果就是以度(°)为单位的。
0 }: k3 T4 L6 m% c# z1 V$ Z
- g3 I1 X, z% E/ t' M/ A" P七、ATK-MPU6050模块
6 d. h- h$ R& U8 r4 k) ]2 F8 yATK-MPU6050模块主要由MPU-6050芯片和RT9193-33芯片组成,原理图如下图所示:" G# z. C% L* `, c% W) |. A
7 l5 A8 o9 S# T+ u% Q! F9 G8 |9 D
20201202125803667.jpg $ q" [' i. x( ?

) C1 D/ b7 V$ q( K# ^2 G开发板通过ATK-MODULE接口外接MPU6050模块,硬件连接原理图如下:" T5 J2 ~. ~7 o# j3 N, w

, a  a5 I( H* \# F! w 20201202125834118.jpg
! @" E. C# Q6 w5 _5 B2 ?& G. d5 N* A
八、重点关注的相关代码3 H( u: Z( {- {6 e
8.1)MPU-6050驱动代码
% p; |1 i' o" A7 q+ S% l+ n1,MPU6050 IIC接口驱动代码% p+ n8 ^4 Y0 d3 z" u
2,MPU_Init函数
& {. ^: }; {6 P; x# W7 l4 D6 B3,MPU_Get_Gyroscope函数( w; R9 U, V5 Z; f% i! B0 q; k
4,MPU_Get_Accelerometer函数1 ?9 |% ~4 @/ D) Z: [: l+ X8 Q0 x
5,MPU_Get_Temperature函数, G3 R) S$ T8 I  n* P9 n6 J" x
8.2)DMP驱动代码
1 v: |# o) N* A* e4 C! G1,DMP移植相关代码
7 P! V# r' f$ z# gi2c_write、i2c_read、delay_ms和get_ms.
  @1 }9 ]0 z' R' t% t- w2, mpu_dmp_init函数# G6 x. E6 j4 l( ?
3, mpu_dmp_get_data函数
& l& B: w) T  t$ j8 o5 }9 o; q$ u( X/ O' k( ~; z
九、MPU6050读写时序( k( @' S: n  t
9.1)单字节写入时序
/ O6 u- J8 F" h" P  H( [
: v9 M7 }- n% e7 }% u+ A- m 20201202130030646.png
; \, u, ?3 ~1 n- L
0 i8 N6 m$ o  _& }; L) F4 E, w2 y9.2)连续写入时序2 J4 u; m0 [' A) F% R6 u

3 r6 x* s4 p8 E4 H$ } 2020120213005560.png
# w0 H  F2 |/ Z  k0 O9 g% a9 O. [# B4 \0 r$ s
9.3)单字节读出时序
0 e2 c2 w- d: ?8 W% O4 E" r
3 Y0 o2 p7 M' W" a+ Z9 q; {. Q 20201202130110852.png * q7 n7 O  z' R9 f7 p+ s

3 |! S* T* E1 f3 q% \! w( R9 i5 u9.4)连续读出时序
8 W% Y! ]( m$ o2 r; Q( I7 g( w$ [8 A. Q  [: R- N$ {. n0 b
20201202130123583.png
6 t# `  k) A" g  m" Q
6 o) J- d, p) c+ v& L1 ]' _0 Z十、部分实验代码解读
7 B9 t4 u- |1 K2 O; S+ {; T10.1 mpuiic.h头文件函数! F$ Z9 b" F3 r; q1 v& `* e" E
1 |# c  w( V( I  C
  1. /**! E; c: f/ s" a, X% `$ e4 _2 M! J
  2. ********************************  STM32F10x  *********************************/ p- L& V0 w, b: F4 t1 j
  3. * @文件名称: mpuiic.h
    ) v" q3 k- t0 z- a# k" L: z
  4. * @修改作者: Aaron9 ?- l; v. L* _* B+ V
  5. * @库版本号: V3.5.0: \. k9 b+ w7 S. \
  6. * @工程版本: V1.0.0
    ! L& [2 O5 N( n: P
  7. * @开发日期: 2020年11月30日! H* I. {5 n( v" Q$ |
  8. * @摘要简述: mpuiic头文件,主要跟MPU-6050模块进行IIC通讯时用, I$ `5 w# X1 [. x) N
  9. ******************************************************************************/
      i5 R9 W' a+ _% `2 Z& P# D
  10. /*-----------------------------------------------------------------------------4 q5 e( {- f2 f4 C+ U: y
  11. * @更新日志:
    " l- M* U/ v$ I& T8 r- ?
  12. * @无9 `+ v2 ^6 e8 o, b
  13. * ---------------------------------------------------------------------------*/. ]) }; r! {+ x+ P* z
  14. #ifndef __MPUIIC_H( n% x7 K6 z, N% W6 f) ~$ r
  15. #define __MPUIIC_H4 P* A2 D' l, ~3 y( O
  16. /* 包含的头文件 --------------------------------------------------------------*/
    : l+ D* n: `) I8 B+ k% ?
  17. #include "sys.h"
    4 S; v; O" D2 w  k1 V( d& T$ m
  18. #include "stm32f10x.h"
    * b# [- W( Q  ?% s% S
  19. /* 寄存器方法控制GPIO管脚输入输出模式 ----------------------------------------*/! T2 G, Y8 g3 G
  20. #define MPU_SDA_IN()  {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=8<<12;}   // PB11 上拉输入模式  ^% z. b3 b* p+ j
  21. #define MPU_SDA_OUT() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=3<<12;}   // PB11 通用推挽输出模式,50MHz5 g" s7 d2 \4 S+ s6 V, p2 I
  22. /* 位操作方法定义 ------------------------------------------------------------*/
    / t8 j4 D1 ]+ L9 H- p: r
  23. #define MPU_IIC_SCL    PBout(10)   // PB10对应SCL
    2 Q0 c0 h* s' _! f+ S0 z
  24. #define MPU_IIC_SDA    PBout(11)   // PB11对应SDA,输出SDA  
    ' N" {+ x$ P" c/ p  Q6 Q( K* q" D6 A
  25. #define MPU_READ_SDA   PBin(11)    // PB11对应SDA,输入SDA
    0 D0 S/ ?" ~) d$ Q: J$ P6 L% j2 ^
  26. /* 定义IIC底层驱动程序 -------------------------------------------------------*/- U# R5 q& h( h' a. C4 y
  27. void MPU_IIC_Delay(void);                         // MPU IIC延时函数,延时 2 us/ a4 S6 K! W$ O2 @* @0 p' a, n
  28. void MPU_IIC_Init(void);                   // 初始化IIC的IO口
    ) y, S. A( s# U$ o
  29. void MPU_IIC_Start(void);                  // 发送IIC开始信号
    " {8 |4 X3 B! r" `! e# q
  30. void MPU_IIC_Stop(void);                              // 发送IIC停止信号
    % e% F* L/ n% t$ x
  31. u8 MPU_IIC_Wait_Ack(void);                 // IIC等待ACK信号/ V3 C* B: g- d9 m# |/ S$ x
  32. void MPU_IIC_Ack(void);                    // IIC发送ACK信号   
    2 Y/ `- s' U, y0 q* T2 N
  33. void MPU_IIC_NAck(void);                   // IIC不发送ACK信号
    . z% q! `2 r8 O. K! Q$ T* ]0 e: F
  34. void MPU_IIC_Send_Byte(u8 txd);            // IIC发送一个字节
    + A4 Y% h  O$ k+ m1 [. J# P( X0 l
  35. u8 MPU_IIC_Read_Byte(unsigned char ack);   // IIC读取一个字节
    & F: V  O8 I8 @' f& x1 h. N1 m
  36. #endif /* __MPUIIC_H */
      G/ ?7 U- L0 ^: m
  37. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码
" M7 x* h7 a' X* h6 W# ^: }) y
10.2 mpuiic.c源文件函数! s1 k: t+ W; m# j" `% U

7 u) K6 ]" J1 P" r" D# j
  1. /**! D: }; t( t3 {/ T
  2. ********************************  STM32F10x  *********************************
    : N4 {$ g* f6 {8 W0 q, ?) c
  3. * @文件名称: mpuiic.c# ?  \' ?( j1 Q1 p: P8 y" d
  4. * @修改作者: Aaron  ~+ F% i+ N) r7 Y% {
  5. * @库版本号: V3.5.00 c+ W7 @, W! z5 J- W+ _* J9 k
  6. * @工程版本: V1.0.0
    / U9 l) B# u  a' M4 }; M5 u, S
  7. * @开发日期: 2020年11月30日
    ; {2 x! Q* |. Y
  8. * @摘要简述: mpuiic源文件,主要包含与MPU-6050进行IIC通讯的IIC底层驱动程序7 M0 q4 k) O) `) ^7 b$ D8 `: ^
  9. ******************************************************************************/
    ' Z1 T5 |- Z: e7 W2 k
  10. /*-----------------------------------------------------------------------------
    + d# v: n- n. \$ @, d* h9 C
  11. * @更新日志:$ U. ~3 ]3 [" j( S% q! w
  12. * @无$ P5 t8 @" I9 @* V" p
  13. * ---------------------------------------------------------------------------*/, u9 y# _0 o0 g& f1 b
  14. /* 包含的头文件 --------------------------------------------------------------*/! g8 H! S- S  Y5 p& {
  15. #include "mpuiic.h"% ]: Z+ i2 h2 _1 l% C$ V2 G( B# A
  16. #include "delay.h"$ ~: x, ?: z( v
  17. /*********************************************************************
    - c6 W/ r& M, R- b' ~0 H$ ?* N
  18. 函数名称:MPU_IIC_Delay()% i0 v0 m( x  u% z0 z- g' m/ R2 v1 m% N
  19. 函数功能:延时函数,延时2微秒(us)
    ( z# v- j" z: o8 a% Z
  20. 入口参数:无) J+ V6 O+ x$ t0 Z$ [- p( C
  21. 返回参数:无
    $ p" g! Y% A& u( t4 W
  22. 修改开发:Aaron
    $ {1 a3 [2 }) q9 ]9 n2 g! h3 w0 x
  23. **********************************************************************/, j4 F; m, E4 p: B5 P
  24. void MPU_IIC_Delay(void)/ }/ h' |2 m, \. A  Z3 I# ]
  25. {3 s" i! a/ M+ S  }; [
  26. delay_us(2);
    $ w% y3 x. f+ M+ I2 {$ [
  27. }
    3 E8 H5 N( m7 [# }1 V2 L( p, |
  28. /*********************************************************************7 U1 k) @7 a4 b, x1 r
  29. 函数名称:MPU_IIC_Init()& L; I. V( j9 y0 h% x  z; {
  30. 函数功能:MPU_IIC管脚初始化配置0 P3 |. X1 h. G) R, t
  31. 入口参数:无
    ) Y& F, w% c, w" X
  32. 返回参数:无
    2 k( w4 J3 b7 R
  33. 修改作者:Aaron/ F* @" r( N& _
  34. **********************************************************************/6 @9 P7 }/ ~. x9 `9 Y; M
  35. void MPU_IIC_Init(void)6 C2 ?* l* {8 K2 B
  36. {          + B: z3 e& C5 x% L
  37.   GPIO_InitTypeDef  GPIO_InitStructure;
    4 t5 c! Z3 H( r/ w
  38.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);     // 使能外设IO PORTB时钟   0 L# O% U1 C. r9 I9 ?  W' W7 y/ J/ j
  39.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;   // 端口配置,管脚10和管脚11( `# U: H, V, K
  40.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         // 推挽输出8 |3 z: a4 H' ^; c/ P
  41.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        // IO口速度为50MHz
    8 y) ^' K8 q; B6 N1 h% }5 M& a5 z! V
  42.   GPIO_Init(GPIOB, &GPIO_InitStructure);            
    1 N/ J7 }3 {2 q6 J! ?( n) \- t
  43.   GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);             // PB10(SCL),PB11(SDA) 输出高 6 K! r  T, \+ k6 \; {- P
  44. }
    6 j$ R; q9 L' q9 l. H2 X& a0 ]
  45. /*********************************************************************
    # N2 \/ s8 a, r' M9 ~- L1 }5 }
  46. 函数名称:MPU_IIC_Start()
    , b4 Q* y5 ?1 m5 M, o1 }0 L
  47. 函数功能:MPU_IIC起始信号% d4 F7 m9 C; a- c- V0 H: Q3 j
  48. 入口参数:无
    4 K; g/ h/ P5 D( H  R
  49. 返回参数:无
    / U; z3 a7 q2 N: `0 V' q- s$ ]' p
  50. 修改作者:Aaron5 a: T  N# k7 b' }
  51. **********************************************************************/
    : Z( N! |  X7 K) e& i2 A
  52. void MPU_IIC_Start(void)
    ! ?2 E3 X! W; k5 E
  53. {4 `2 \" @$ R5 O) s# x7 f
  54. MPU_SDA_OUT();      // SDA线输出模式
    4 ~1 a) e  L" e' l* ^
  55. MPU_IIC_SDA=1;      // SDA输出高
    ! R& x& g7 q6 S. N1 K6 C
  56. MPU_IIC_SCL=1;      // SCL输出高,此时为空闲状态  N2 ]- t$ Y( k
  57. MPU_IIC_Delay();    // 延迟 2 us
    & z6 L, m0 D' a# d% S$ x
  58. MPU_IIC_SDA=0;      // 在SCL输出高的状态下,SDA由高至低跳变,IIC开始( O# o5 l+ ]  |
  59. MPU_IIC_Delay();    // 延迟 2 us7 z; C& }0 s. Q. C4 k9 P% C
  60. MPU_IIC_SCL=0;      // 钳住I2C总线,准备发送或接收数据 1 J- F. o8 H. A# J! N6 b* z) O) W
  61. }  
    0 u5 }$ V" R% a; F9 O
  62. /*********************************************************************
    ; q: z1 K* h* K3 _
  63. 函数名称:MPU_IIC_Stop()
    / j+ S" d1 p7 ]5 A" ^
  64. 函数功能:MPU_IIC停止信号2 x) _! R; K0 d- G  ^
  65. 入口参数:无
      }' V6 E2 P, @; r, Z/ W
  66. 返回参数:无8 A, y0 {$ J4 h" P, G) |
  67. 修改作者:Aaron; D5 X, @+ O* c3 v
  68. **********************************************************************/
    5 K! f/ [* y7 y* L* }6 C! f
  69. void MPU_IIC_Stop(void)2 K4 K3 S& l- m. f
  70. {! V! C* y9 D3 W# C# W' C: t( K
  71. MPU_SDA_OUT();      // SDA线输出模式
    3 u/ r/ S/ P8 I" R
  72. MPU_IIC_SCL=0;      // SCL输出低
    1 F* ^7 v! g* M  L2 E2 Y+ I
  73. MPU_IIC_SDA=0;      // SDA输出低
    5 x$ m& x4 l& R& q2 s
  74. MPU_IIC_Delay();    // 延迟 2 us
    & c# D5 B9 A5 a# o+ h! q1 V' y
  75. MPU_IIC_SCL=1;      // 先SCL输出高,在SCL输出高的状态下,SDA一直是低电平6 `( A0 H. x8 _  e  M# r* P# u: _4 p
  76. MPU_IIC_SDA=1;      // SDA输出高,发送I2C总线结束信号( @* a# x6 t$ L/ t
  77. MPU_IIC_Delay();    // 延迟 2 us        
    $ y0 P( i0 ~2 e& q
  78. }
    . P9 _, _/ r: A3 u* U( g
  79. /*********************************************************************( H3 S# h: q( v( b2 _/ a+ `8 ]
  80. 函数名称:u8 MPU_IIC_Wait_Ack()
    7 ~$ s. E4 b/ o; I! W9 h: ]6 u- T
  81. 函数功能:等待应答信号到来6 F) \/ t: G# x) c. ]. i* T
  82. 入口参数:无8 C/ z* Q8 c8 t% z' ]
  83. 返回参数:u8,1,接收应答失败,0,接收应答成功
    & w6 S8 ?  y6 `: W
  84. 修改作者:Aaron
    & b' H, b" J, P" e$ m, ~2 _
  85. **********************************************************************/4 I1 m, z! r8 n4 d; U
  86. u8 MPU_IIC_Wait_Ack(void)/ \; B8 }. J; Q1 K- R0 k' ]" i4 @
  87. {: E! {  q6 v  w
  88. u8 ucErrTime=0;! e/ b  h, O* ]& Y; c
  89. MPU_SDA_IN();         // SDA设置为输入  
    # v' V3 z, `" @; q3 T' i2 ~0 J
  90. MPU_IIC_SDA=1;        // SDA设高电平
    7 e7 s. Z' X& A- b; a3 y
  91. MPU_IIC_Delay();      // 延迟 2 us
    4 y! h# X1 r" ~% ~
  92. MPU_IIC_SCL=1;        // SCL设高电平% ~1 E# m7 x% W' ?1 }
  93. MPU_IIC_Delay();      // 延迟 2 us 8 u3 ], j# r2 C' X% u9 y
  94. while(MPU_READ_SDA)   // 读取PB11的值,一直读PB11=1,高电平,则不断循环,直到溢出
    8 {; d5 d% m- S$ Y) S" J
  95. {
    # j! b- H: W$ J& {# x$ A0 C
  96.   ucErrTime++;
    4 q# B; ]* v+ m. q  ?0 G) @/ b. o
  97.   if(ucErrTime>250)
    % R! D/ {! ]; L
  98.   {+ R1 y3 S+ Y/ O! K+ p
  99.    MPU_IIC_Stop();
    2 H* b8 \* W, \% G0 G/ t8 z# U0 p
  100.    return 1;
    ' h. m9 V2 P3 ^# A- y' t/ N5 z" @
  101.   }
    + n7 g( M: x( N& k3 u
  102. }
    ' H; l$ m, O1 q6 `
  103. MPU_IIC_SCL=0;        // SCL设低电平     
    , a* C2 Y' ^4 y8 i) k! ?+ E/ `
  104. return 0;  / I9 M' B( g# }5 w7 m# @: M
  105. } $ X/ U  K4 M: K8 |5 ]1 w" P" i4 @
  106. /*********************************************************************
    7 h* I# \0 C; B$ d5 E5 \% b) k
  107. 函数名称:MPU_IIC_Ack()
    ) d. l, h+ m* I5 i
  108. 函数功能:产生ACK应答
      d) J7 @8 D; g. G
  109. 入口参数:无
    ! F% |9 t4 x1 f( X: i
  110. 返回参数:无
    ) ~: n' B& X- O8 D  {
  111. 修改作者:Aaron
    , Q0 y+ Y$ M( f4 S+ l7 q; b
  112. **********************************************************************/
    " Z, K+ {4 Z. c" _" r9 s
  113. void MPU_IIC_Ack(void)% [0 Z* E# ?  s/ Z' U2 C
  114. {. A0 I& p: Z- b7 ^& O. D
  115. MPU_IIC_SCL=0;       // SCL设低电平  r! n& ?+ H: T& C2 P, ]* B
  116. MPU_SDA_OUT();       // SDA输出模式- H, I, G' s$ `
  117. MPU_IIC_SDA=0;       // SDA设低电平
    5 i8 J( X. t) O. ?  M
  118. MPU_IIC_Delay();     // 延时 2 us
    & w; q9 L7 o  j" K# P
  119. MPU_IIC_SCL=1;       // SCL设高电平! ^7 S2 ?3 m+ q$ k
  120. MPU_IIC_Delay();     // 延时 2 us
    # w7 ]' J& H  E
  121. MPU_IIC_SCL=0;       // SCL设第电平,在SCL高电平期间,SDA为低电平,则说明有效应答& ?* t' Z' c+ E1 ?& _+ i
  122. }
    ) c) _1 C1 C4 h/ f
  123. /*********************************************************************) d7 q/ [. f0 t- X% g! [
  124. 函数名称:MPU_IIC_NAck(); B/ {0 N" F) k; t  W; e
  125. 函数功能:不产生ACK应答
    & c; h" H3 f7 [) v7 _5 ^
  126. 入口参数:无" H" D- j5 \8 y7 S
  127. 返回参数:无8 T( @/ n8 ^' v: m- f. D
  128. 修改作者:Aaron
    / v8 k9 v+ m; c: t6 i
  129. **********************************************************************/
    ; Q$ D9 H2 e, L( x( {! w
  130. void MPU_IIC_NAck(void)7 A1 e& J' E8 B9 g
  131. {
    4 h  `) i7 U8 y
  132. MPU_IIC_SCL=0;       // SCL设低电平
    ) I$ S* N0 A/ ?8 H" Z7 K
  133. MPU_SDA_OUT();       // SDA输出模式
    6 _* V8 H; E1 h2 ]
  134. MPU_IIC_SDA=1;       // SDA设高电平
    ( G( ^8 D/ }) I, T
  135. MPU_IIC_Delay();     // 延时 2 us# y% ]' v2 n, G) y; S
  136. MPU_IIC_SCL=1;       // SCL设高电平
    ) ~9 C. I) R0 @1 H% e6 H" F8 D
  137. MPU_IIC_Delay();     // 延时 2 us
    % B) F" u- I6 V' Q: A, g/ y
  138. MPU_IIC_SCL=0;       // SCL设低电平,在SCL高电平期间,SDA为高电平,则说明无效应答: c8 R  U0 K; o$ G. Q/ a0 D
  139. }
    ( w: j4 Y1 ?! `" T& o  q9 y' D
  140. /*********************************************************************8 o! ~, C- y; [; t# M
  141. 函数名称:MPU_IIC_Send_Byte(u8 txd)
    : z6 }" o, @7 k, u# H7 k
  142. 函数功能:IIC发送一个字节
    ( L! e3 G8 ]2 ~; `1 i) E
  143. 入口参数:u8 txd- ]! N# _% R8 B1 K7 r5 j
  144. 返回参数:无( i2 v. f* R" y8 k; U
  145. 修改作者:Aaron' [- c3 p* C2 b; c1 `* b
  146. **********************************************************************/
    # ?' `, k7 u# {9 _
  147. void MPU_IIC_Send_Byte(u8 txd)
    - ^/ J8 w) y  {3 S; \2 b" L4 y& b7 {
  148. {                        
    ; g; I* Y4 }- X
  149. u8 t;   0 B4 h5 f2 O+ ^5 o4 E6 }: t
  150. MPU_SDA_OUT();       // SDA输出模式
    / _" e2 }  z0 }$ F- s% L- t
  151. MPU_IIC_SCL=0;       // SCL设低电平,此时可改变SDA,以实现数据的有效传输
    ; O& p" x  X* e! I( g" f" o
  152. for(t=0;t<8;t++)     // 发送一个字节,即8个bit
    3 x2 _; y" ]* A& T1 ]
  153. {              # F' I- e& D8 _. [3 o
  154.   MPU_IIC_SDA=(txd&0x80)>>7;  // 获取u8 txd的最高位(0或1),并右移7位,将最高位值给MPU_IIC_SDA. [) Q+ R1 ^. g: p1 z
  155.   txd<<=1;    , f7 O4 q2 c1 b7 ^
  156.   MPU_IIC_SCL=1;              // SCL设高电平, `% Q4 @( _- A5 `0 B! h
  157.   MPU_IIC_Delay();            // 延时 2 us
    0 S" U  L8 C' x, A, h# U* D
  158.   MPU_IIC_SCL=0;              // SCL设低电平,传输SDA完成. y4 d' c) k6 z9 U7 k! Y
  159.   MPU_IIC_Delay();            // 延时 2us1 u0 M! {' `. n
  160. }  6 h+ P7 B; y- o
  161. } ' H3 g0 {) U9 h& G& w. X/ Y3 i
  162. /*********************************************************************
    2 N  Z/ e  }2 u6 ^5 c
  163. 函数名称:u8 MPU_IIC_Read_Byte(unsigned char ack)" B! y- m! e' ^4 Y1 P
  164. 函数功能:IIC读取一个字节,ack=1时,发送ACK,ack=0,发送nACK
    ; a, ~6 f6 B3 ^' ^+ T, j
  165. 入口参数:ack' D0 Z3 W' Z' I) ]  H3 G
  166. 返回参数:u8,
    ( T) g8 `/ ]' K6 r) U, ~
  167. 修改作者:Aaron' B: y- I* r0 F, |) k# x' V+ v9 b
  168. **********************************************************************/( V2 n* L, _# ?+ b
  169. u8 MPU_IIC_Read_Byte(unsigned char ack)
    4 u$ B0 z, @7 |4 A. t+ w
  170. {! T% u  Q) ^9 Z% o3 J
  171. unsigned char i,receive=0;
    % S: U5 k9 L7 ?! W" {( N
  172. MPU_SDA_IN();                 // SDA设置为输入模式
    " ]- o9 V) v" f; |0 N0 i# r
  173. for(i=0;i<8;i++ )             // 读取一个字节,即8个bit3 w8 c7 \* j1 n$ p% ]( o. k
  174. {
    7 e8 k  d* x/ P) p
  175.   MPU_IIC_SCL=0;               // SCL设为低电平9 {$ T' E7 P5 J% I* U
  176.   MPU_IIC_Delay();             // 延时 2us
    & |* g: ?' b6 l$ D' t* K; Z3 {+ d
  177.   MPU_IIC_SCL=1;               // SCL设为高电平
    " v- N5 p8 K, g( o9 w( G1 E
  178.   receive<<=1;7 I0 c* O* _5 a% D+ P% m, U9 e
  179.   if(MPU_READ_SDA)             // 如果读取的SDA为1,则receive最低值+1,若读取的SDA为0,则receive最低值不变,即0
    * ~' Q* P8 c1 E$ n
  180.    receive++;   
    : a/ W6 J# |8 B0 H2 q2 I4 ]
  181.   MPU_IIC_Delay();             // 延时 2us
    ' Y% {: r9 w- b3 d' i- L7 @5 Q4 D
  182. }      # W3 u& [( U. [# S1 Q* w
  183. if (!ack)3 ?# R$ T: I/ n2 U" n2 F
  184.   MPU_IIC_NAck();              // 发送nACK  R* A# a+ b3 J+ o) A! i
  185. else. l$ ?: E! m  E5 H4 p8 E
  186.   MPU_IIC_Ack();               // 发送ACK   * c, k$ z, m. S; u6 S" m$ u
  187. return receive;1 h9 I2 D" d1 \3 `' E9 ~# N/ N
  188. }( y; I) O: Y2 m- ]) g) W8 Z
  189. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码
$ a' K' c% @) w4 I( f0 G" C
10.3 mp6050.h头文件函数
: _/ X/ A% |% r1 g代码中标记“初学”的说明是前面寄存器介绍时讲到的。5 K- Z/ W1 z% I
: G' z  j" d1 ?
  1. /**
    1 X3 e5 ], @/ J" |! R! o% u
  2. ********************************  STM32F10x  *********************************( ], n" Z! b+ Z+ T' l
  3. * @文件名称: mpu6050.h
    # ~" |4 @% q$ N3 o
  4. * @修改作者: Aaron' h4 M* a9 d2 ^* x
  5. * @库版本号: V3.5.0
    # R3 [) {  W* H! Y( @% e# Z" p4 a
  6. * @工程版本: V1.0.0
    7 b/ ^$ ?! R- E! `5 X
  7. * @开发日期: 2020年11月30日) b. w& G6 Z. v2 ~# e
  8. * @摘要简述: mpu6050头文件
    # ^. `$ s# M! b; v
  9. ******************************************************************************/- M" u5 V5 o( U; s8 q4 @
  10. /*------------------------------------------------------------------------------ ?8 g  N7 [' j' R* v
  11. * @更新日志:( h, T8 F2 w: n3 V6 u5 ~4 j' i
  12. * @无
    " ]) i5 X  a4 z/ y5 B( f
  13. * ---------------------------------------------------------------------------*/  o2 z, m0 r, J: ~0 p
  14. #ifndef __MPU6050_H5 h9 j8 h* b0 H, @0 B8 R
  15. #define __MPU6050_H
    5 }( Z9 S+ S* t& M& r
  16. /* 包含的头文件 --------------------------------------------------------------*/; F2 ]% k) d' Q9 z2 U6 D
  17. #include "mpuiic.h"   $ t& U  @" `7 V
  18. /* 位操作控制PA15,对应MPU6050 AD0的高低电平 ----------------------------------*/
    # m/ ~/ X" S2 U, B! K; `
  19. #define MPU_AD0_CTRL   PAout(15) // 控制AD0电平,从而控制MPU-6050地址, A( V* m% [4 _- K
  20. /* MPU6050 寄存器ID定义 ------------------------------------------------------*/+ U7 i5 Z* l' S2 j( X
  21. // #define MPU_ACCEL_OFFS_REG 0X06 // accel_offs寄存器,可读取版本号,寄存器手册未提到- A% E8 ^1 K) t3 O
  22. // #define MPU_PROD_ID_REG    0X0C // prod id寄存器,在寄存器手册未提到* U2 v% Z% Q+ u- n
  23. #define MPU_SELF_TESTX_REG    0X0D // 自检寄存器X ACC和G$ w' N! B5 z8 `. h4 _  O( s0 |
  24. #define MPU_SELF_TESTY_REG    0X0E // 自检寄存器Y ACC和G
    + J7 R! L' h$ |( ?# C
  25. #define MPU_SELF_TESTZ_REG    0X0F // 自检寄存器Z ACC和G
    ; K  y# H5 @; I1 H6 T$ Q) y
  26. #define MPU_SELF_TESTA_REG    0X10 // 自检寄存器X,Y,Z only ACC
    . n! W, S  I4 g2 j
  27. #define MPU_SAMPLE_RATE_REG   0X19 // 陀螺仪采样频率分频器    **初学**3 _4 }& w) ~+ `$ X- J
  28. #define MPU_CFG_REG           0X1A // 配置寄存器              **初学**- L4 B; |0 `" t8 G8 y
  29. #define MPU_GYRO_CFG_REG      0X1B // 陀螺仪配置寄存器        **初学**
    ) w( K9 N5 r$ p1 y: S& S
  30. #define MPU_ACCEL_CFG_REG     0X1C // 加速度计配置寄存器      **初学**0 @5 ]7 V  ]: n( O  d/ X7 d: E
  31. #define MPU_MOTION_DET_REG    0X1F // 运动检测阀值设置寄存器
    , o6 T% T6 L9 E9 X1 H) D6 C
  32. #define MPU_FIFO_EN_REG       0X23 // FIFO使能寄存器          **初学**
    / D( I, w2 ?% t- {# r: H
  33. #define MPU_I2CMST_CTRL_REG   0X24 // IIC主机控制寄存器
    1 O. L! o8 `+ e$ d0 R+ @
  34. #define MPU_I2CSLV0_ADDR_REG  0X25 // IIC从机0器件地址寄存器
    7 N3 h( e! c& d0 O" |: H4 C
  35. #define MPU_I2CSLV0_REG       0X26 // IIC从机0数据地址寄存器
    7 J7 f: Y' T$ U5 H5 i2 m
  36. #define MPU_I2CSLV0_CTRL_REG  0X27 // IIC从机0控制寄存器
    ) \4 F$ f0 z0 t' Q' ?
  37. #define MPU_I2CSLV1_ADDR_REG  0X28 // IIC从机1器件地址寄存器) |* z) [6 m. H( M
  38. #define MPU_I2CSLV1_REG       0X29 // IIC从机1数据地址寄存器
    ' J6 b5 J8 J/ F1 d/ H
  39. #define MPU_I2CSLV1_CTRL_REG  0X2A // IIC从机1控制寄存器
    8 ~3 L$ W" _4 h! n
  40. #define MPU_I2CSLV2_ADDR_REG  0X2B // IIC从机2器件地址寄存器2 q$ x1 r5 t+ c0 k$ e
  41. #define MPU_I2CSLV2_REG       0X2C // IIC从机2数据地址寄存器$ Z. z# _1 N" i  g7 D6 M
  42. #define MPU_I2CSLV2_CTRL_REG  0X2D // IIC从机2控制寄存器8 e; f+ z$ v' I; o$ ?' M9 H+ l1 U
  43. #define MPU_I2CSLV3_ADDR_REG  0X2E // IIC从机3器件地址寄存器
    / A% j/ v2 Z4 P: Y- h6 e! X+ Z
  44. #define MPU_I2CSLV3_REG       0X2F // IIC从机3数据地址寄存器& Y6 c4 X* D3 c% K" t! I
  45. #define MPU_I2CSLV3_CTRL_REG  0X30 // IIC从机3控制寄存器4 q% u! H! f/ p5 L) Q
  46. #define MPU_I2CSLV4_ADDR_REG  0X31 // IIC从机4器件地址寄存器; x* P0 K1 A0 }0 {
  47. #define MPU_I2CSLV4_REG       0X32 // IIC从机4数据地址寄存器5 d/ M1 q, E" k! ]+ e
  48. #define MPU_I2CSLV4_DO_REG    0X33 // IIC从机4写数据寄存器3 I% ]+ a: V- K' R
  49. #define MPU_I2CSLV4_CTRL_REG  0X34 // IIC从机4控制寄存器$ Q# r/ p( L! F5 v2 Z
  50. #define MPU_I2CSLV4_DI_REG    0X35 // IIC从机4读数据寄存器
    & E& w4 ?; Z/ R2 [" E' u
  51. #define MPU_I2CMST_STA_REG    0X36 // IIC主机状态寄存器
    . `% R9 d* P* Y
  52. #define MPU_INTBP_CFG_REG     0X37 // 中断/旁路设置寄存器
    . @- E; k! b/ w( `0 }
  53. #define MPU_INT_EN_REG        0X38 // 中断使能寄存器/ S% j. X9 z4 r. W4 h
  54. #define MPU_INT_STA_REG       0X3A // 中断状态寄存器; B7 }+ L0 E, @1 u
  55. #define MPU_ACCEL_XOUTH_REG   0X3B // 加速度值,X轴高8位寄存器  **初学**
    ' J! C3 T- K6 J( v# g, j7 B3 |
  56. #define MPU_ACCEL_XOUTL_REG   0X3C // 加速度值,X轴低8位寄存器  **初学**& U. q5 Z7 p+ d' V! ~7 Q
  57. #define MPU_ACCEL_YOUTH_REG   0X3D // 加速度值,Y轴高8位寄存器  **初学**
    5 K' r$ V1 Z5 Y# x8 C+ X
  58. #define MPU_ACCEL_YOUTL_REG   0X3E // 加速度值,Y轴低8位寄存器  **初学**( h2 V( {/ X; w! U6 Y, P1 A- j8 N# n
  59. #define MPU_ACCEL_ZOUTH_REG   0X3F // 加速度值,Z轴高8位寄存器  **初学**! H, ?- F+ H2 b" ^( U1 ?$ F
  60. #define MPU_ACCEL_ZOUTL_REG   0X40 // 加速度值,Z轴低8位寄存器  **初学**" n/ R1 D# F# v$ Q* k- a
  61. #define MPU_TEMP_OUTH_REG     0X41 // 温度值高八位寄存器    **初学**" X% P0 w0 [$ h) K# r# A( X3 F
  62. #define MPU_TEMP_OUTL_REG     0X42 // 温度值低八位寄存器    **初学**
    5 ]* D& N3 G, Q* A& f
  63. #define MPU_GYRO_XOUTH_REG    0X43 // 陀螺仪值,X轴高8位寄存器 **初学**
    : S8 `+ m; ?2 S( S; j9 q
  64. #define MPU_GYRO_XOUTL_REG    0X44 // 陀螺仪值,X轴低8位寄存器 **初学**
    5 P- s4 Y- S3 _2 o4 v* C4 C: T
  65. #define MPU_GYRO_YOUTH_REG    0X45 // 陀螺仪值,Y轴高8位寄存器 **初学**
    2 C! T- }, f1 J# A$ g, {5 C
  66. #define MPU_GYRO_YOUTL_REG    0X46 // 陀螺仪值,Y轴低8位寄存器 **初学**
    5 ^3 a3 P0 {# p( S% Y/ w$ B4 {9 \
  67. #define MPU_GYRO_ZOUTH_REG    0X47 // 陀螺仪值,Z轴高8位寄存器 **初学**
    " h) C: ^7 l- s8 F6 Z- e4 f1 B
  68. #define MPU_GYRO_ZOUTL_REG    0X48 // 陀螺仪值,Z轴低8位寄存器 **初学**
    ( _% g2 ]) K& h1 L" b  N
  69. #define MPU_I2CSLV0_DO_REG    0X63 // IIC从机0数据寄存器
    $ i% [; Q$ V+ h: q4 C
  70. #define MPU_I2CSLV1_DO_REG    0X64 // IIC从机1数据寄存器
    2 H  _  R9 r( R; @) h' i( B- `2 h
  71. #define MPU_I2CSLV2_DO_REG    0X65 // IIC从机2数据寄存器" j! [! U1 B: Z  f* G
  72. #define MPU_I2CSLV3_DO_REG    0X66 // IIC从机3数据寄存器
    & \5 i; L& E: |6 q% o3 [1 P
  73. #define MPU_I2CMST_DELAY_REG  0X67 // IIC主机延时管理寄存器
    4 y' \) R. t$ f1 v0 {
  74. #define MPU_SIGPATH_RST_REG   0X68 // 信号通道复位寄存器" e( T& ~& R: c  g! T
  75. #define MPU_MDETECT_CTRL_REG  0X69 // 运动检测控制寄存器
    6 l1 ^6 f4 M# ~. Y! Z
  76. #define MPU_USER_CTRL_REG     0X6A // 用户控制寄存器
    6 f3 R1 H' G2 x/ B
  77. #define MPU_PWR_MGMT1_REG     0X6B // 电源管理寄存器1      **初学**! H9 k, t, k% x. f0 H5 D
  78. #define MPU_PWR_MGMT2_REG     0X6C // 电源管理寄存器2      **初学**
    / v" u5 O, Z) Q
  79. #define MPU_FIFO_CNTH_REG     0X72 // FIFO计数寄存器高八位
    . T2 x9 Q- L0 s5 U4 o  M
  80. #define MPU_FIFO_CNTL_REG     0X73 // FIFO计数寄存器低八位6 z; T0 B% t1 e* P3 M
  81. #define MPU_FIFO_RW_REG       0X74 // FIFO读写寄存器
    ( A4 h! k* U, q) {
  82. #define MPU_DEVICE_ID_REG     0X75 // 器件ID寄存器& {" r" T4 H6 D; h% b7 c
  83. // 备注:如果AD0脚(9脚)接地,0,IIC地址为0X68(不包含最低位);
    7 h$ [9 l& q* |, |5 q
  84. // 如果接V3.3,则IIC地址为0X69(不包含最低位),$ q, z* |3 _4 I, z2 d7 h* I
  85. // 本开发板由PA15管脚控制,另PA15为低电平
    1 w) b; T' z4 O0 j5 |; _
  86. #define MPU_ADDR       0X68
    ) U4 A  ]! x0 J3 ^
  87. /* 函数申明 -----------------------------------------------------*/4 ~; U: B! f' j. J
  88. u8 MPU_Init(void);                                 // 初始化MPU60504 Y7 l9 H. k4 D, c1 v; c4 Y+ o$ V
  89. u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf);   // IIC连续写
    8 b+ @5 R* M5 X( t3 @, C# _, e- W
  90. u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf);    // IIC连续读
    5 M, q- ^+ _! _) V. Z
  91. u8 MPU_Write_Byte(u8 reg,u8 data);                 // IIC写一个字节; \, D9 [1 ?9 u6 z/ v
  92. u8 MPU_Read_Byte(u8 reg);                          // IIC读一个字节
    3 C6 z- b" \0 c
  93. u8 MPU_Set_Gyro_Fsr(u8 fsr);
    " ?% b* {+ ]5 p4 Z( y: A; J5 H. _6 d
  94. u8 MPU_Set_Accel_Fsr(u8 fsr);' p! J, y3 w2 {) k% c5 U
  95. u8 MPU_Set_LPF(u16 lpf);
    ( ~9 S9 J; J4 i' C" u
  96. u8 MPU_Set_Rate(u16 rate);; \0 l4 o/ T0 @' O3 y& o4 {
  97. u8 MPU_Set_Fifo(u8 sens);
    % ^) w2 t  M7 P2 N: r
  98. short MPU_Get_Temperature(void);
    * C8 k3 f( v, X5 |
  99. u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz);
    & H% ?7 z: C7 D( j! N
  100. u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az);
    ; q0 K1 N0 l! \2 {: ?% @
  101. #endif /* __MPU6050_H */
    ) x+ V; H2 ^9 E: N( q! e
  102. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码
  N% S( `- M1 u3 F
10.4 mpu6050.c源文件函数
( \% _! Q3 L4 @' w# K& I9 u
4 p! M9 c6 U9 x) b
  1. /**
    . L/ x' ]6 `' m& C
  2. ********************************  STM32F10x  *********************************0 e5 l. W8 H( \& d# Z0 l1 I
  3. * @文件名称: mpu6050.c, e3 Z) m: Z1 P  r7 ]- L1 q
  4. * @修改作者: Aaron
    3 b4 [/ e: B3 C
  5. * @库版本号: V3.5.05 P- c" c( |& q8 s
  6. * @工程版本: V1.0.0
    ) E% z2 T) t0 [; Z
  7. * @开发日期: 2020年11月30日
    5 O/ b3 d6 E9 \7 |/ [6 @9 T9 R( k
  8. * @摘要简述: mpu6050源文件3 }) h) i8 ?! o
  9. ******************************************************************************/
    7 S+ {( y, b' {& q
  10. /*-----------------------------------------------------------------------------6 J* v; x+ \: o9 k
  11. * @更新日志:
    # Y% p5 [* ^: f7 J' m* O. z. N
  12. * @无
    1 ]' {  {0 u( w! U
  13. * ---------------------------------------------------------------------------*/
    7 r$ ^! U/ ]. d* g$ I) E: E) _
  14. /* 包含的头文件 --------------------------------------------------------------*/
    $ U! @' P4 L3 {
  15. #include "mpu6050.h"; B( G% X- T8 ]/ v) @4 G3 z
  16. #include "delay.h"
    / _6 W; P9 S  c9 R
  17. /*********************************************************************" k( ?2 g' i5 [* q# c1 Q" \
  18. 函数名称:u8 MPU_Init()
    ' W( k9 y( }- d& x' t+ g2 L1 o0 K; {
  19. 函数功能:初始化MPU6050: S/ C# s3 x: w: J: b
  20. 入口参数:无
    # \3 Y( h( x: a+ {
  21. 返回参数:0,成功,1失败6 A5 m6 W. g" m0 d
  22. 修改作者:Aaron
    ; n3 u2 o# p7 y
  23. **********************************************************************/. l# ?5 s, t0 q0 I1 ~7 t
  24. u8 MPU_Init(void)
    7 X& z  [" d; o; A8 l) R# {" P
  25. {
    ; n- g( F+ D3 N' M+ q
  26. u8 res;! u+ l! D9 I9 m3 s' |0 Y
  27. GPIO_InitTypeDef  GPIO_InitStructure;( g5 r! F7 F! b% J/ L& C/ A
  28. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);      // 使能AFIO时钟 9 K0 N, X6 O' ~' c
  29. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);     // 使能外设IO PORTA时钟  ; f$ C& X  O: I1 ~2 j' [  J
  30. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;               // 管脚15
    7 Y0 l* |4 Z) F& ^9 Y
  31. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         // 推挽输出' t, p0 j* K' @7 N: y- b
  32. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        // IO口速度为50MHz
    6 E( X2 ^9 J% e' x/ v" @
  33. GPIO_Init(GPIOA, &GPIO_InitStructure);                   // 根据设定参数初始化PA15,对应MPU-6050芯片的AD0地址管脚! Y" S5 W' v9 j+ n9 H9 s
  34. GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);  // 禁止JTAG,从而PA15可以做普通IO使用,否则PA15不能做普通IO!!!8 M* T* ?. m4 D$ y6 u' c- c
  35. MPU_AD0_CTRL=0;                                          // 控制MPU6050的AD0脚为低电平,则从机地址为:0X68" ^* n) W& \; @
  36. MPU_IIC_Init();                                          // 初始化IIC总线4 S2 H/ Q. I6 m1 O7 ]
  37. MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);                  // 对电源管理寄存器1输入0x80,复位MPU6050; t' @8 Z* c# @  i0 Z
  38. delay_ms(100);
    3 S( [, |; f, t( i- ]
  39. MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);                  // 对电源管理寄存器1输入0x00,主要令[6]位设0,正常工作模式,即唤醒MPU6050
    8 K$ {$ N9 a( u* E% U/ F: W+ [4 f$ @
  40. MPU_Set_Gyro_Fsr(3);                                     // 设置陀螺仪传感器满量程范围,±2000dps4 q9 l+ ?- h+ l. P, O4 Y! J
  41. MPU_Set_Accel_Fsr(0);                                    // 设置加速度传感器满量程范围,±2g
    5 G, {- K$ e) _9 [1 q
  42. MPU_Set_Rate(50);                                        // 设置采样率50Hz
    5 d4 [$ a. x- G8 k7 j1 O/ y
  43. MPU_Write_Byte(MPU_INT_EN_REG,0X00);                     // 对中断使能寄存器输入0x00,关闭所有中断+ ^9 [4 }6 r  U/ ~
  44. MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);                  // 对用户控制寄存器输入0x00,I2C主模式关闭3 P9 [' S2 J6 F! x/ a7 ]
  45. MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);                    // 对FIFO使能寄存器输入0x00,关闭FIFO1 N& V; X" L' K+ q) b& a3 b8 ^* p
  46. MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80);                  // 中断/旁路设置寄存器输入0x80,INT引脚低电平有效
    ) L# |5 C# @% q
  47. res=MPU_Read_Byte(MPU_DEVICE_ID_REG);                    // 读取器件ID寄存器值,传至res里: L! V- v! F; ?  U$ l5 I7 \$ h2 ^6 D
  48. if(res==MPU_ADDR)                                        // 如果res=0x68,则器件ID正确
    # n* _( \+ g/ j3 I; M
  49. {! O' J. V" l- L; o8 [# I
  50.   MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);                 // 对电源管理寄存器1输入0x01,设置CLKSEL,001,PLL X轴为参考
    8 e, r4 H" b* s) i3 S
  51.   MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);                 // 对电源管理寄存器2输入0x00,加速度与陀螺仪都工作(都不待机)) b1 J* g7 q0 ?
  52.   MPU_Set_Rate(50);                                       // 设置采样率为50Hz2 t- S1 D0 e* M4 a
  53.   }
    ) F( G/ l- u- Q  h' k: u
  54. else
    9 j. W7 o9 I- f4 a  {: v; W
  55.   return 1;, q. _9 ?% {9 f2 }2 o
  56. return 0;: P) ~* u- F, v: H& [/ @' t' J$ h
  57. }6 ]  ], j1 B1 |6 V7 p
  58. /*********************************************************************
    + s& t' w) Q1 f. O- u
  59. 函数名称:u8 MPU_Set_Gyro_Fsr(u8 fsr)' Q, T( n' t. S" i; w
  60. 函数功能:设置MPU6050陀螺仪传感器满量程范围
    2 h5 @3 y7 a* R( U4 `' D2 v
  61. 入口参数:u8 fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps& {  X9 v& o( |( h( U! N( o7 K
  62. 返回参数:0,成功,1失败! A2 x. N* P2 W1 Y  C
  63. 修改作者:Aaron) V/ T8 t' m4 z5 x$ c
  64. **********************************************************************/8 b1 p$ T+ W0 u4 D; d
  65. u8 MPU_Set_Gyro_Fsr(u8 fsr)
    + E0 R) f7 A' W, q$ V: {
  66. {) z3 {: ^, z; \+ n/ u2 r/ C  u% }
  67. return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);  // 设置陀螺仪满量程范围为±2000dps  , J* r# k0 o3 @" ^8 w
  68. }
    ( r8 @/ q. p# q* S# F
  69. /*********************************************************************5 y- j. |: O3 n: r$ H4 k5 L' y
  70. 函数名称:u8 MPU_Set_Accel_Fsr(u8 fsr): u, ?: g* b6 G' k5 V3 Z5 p
  71. 函数功能:设置MPU6050加速度传感器满量程范围
    + a7 u  t3 `, I8 O7 x1 d, u/ ]
  72. 入口参数:fsr:0,±2g;1,±4g;2,±8g;3,±16g: A' E* D& O6 j1 [
  73. 返回参数:0,成功,1失败; F1 q% n0 x' }! n+ P
  74. 修改作者:Aaron* J9 @' E5 X6 w  S' N0 v3 m
  75. **********************************************************************/
    % `1 Z; G+ t+ j+ e! L) S5 q* Y
  76. u8 MPU_Set_Accel_Fsr(u8 fsr)
    & `6 f& P4 V$ s- a" J
  77. {1 B$ [6 T8 D! E& _8 R  b* D
  78. return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3); // 设置加速度传感器满量程范围为±2g  
    $ o* ]( U4 m: R# c
  79. }2 y+ a4 `7 T7 N' w
  80. /*********************************************************************
    0 x) C5 u. b* q. l
  81. 函数名称:u8 MPU_Set_LPF(u16 lpf)0 x0 w& X! g+ q
  82. 函数功能:设置MPU6050的数字低通滤波器1 z0 W8 m' B" {) w! {
  83. 入口参数:lpf:数字低通滤波频率(Hz)+ p) G+ U' D( d! A# E6 J6 v, ^
  84. 返回参数:0,成功,1失败
    ; a7 ~2 {. ^+ [6 t
  85. 修改作者:Aaron
    ! a5 }( p& I  t: m6 P3 c: ?  A
  86. **********************************************************************/9 P* A/ X4 Z+ Z8 Y
  87. u8 MPU_Set_LPF(u16 lpf)( K% W" o7 Y" w. C$ d
  88. {& u' v) M. A5 C. p0 j5 r0 `, A
  89. u8 data=0;
    & P, p& V6 Y- }2 m7 h+ g' G
  90. if(lpf>=188)                                // 如果lpf≥188Hz,则data=14 W. G" k/ |3 _
  91.   data=1;1 L0 d$ o9 H" F
  92. else if(lpf>=98)) y9 r" O; B/ a& C. E& N% [2 E7 Y2 V
  93.   data=2;8 j2 G2 W/ Z1 ]& y. D* g- i; u5 M; a
  94. else if(lpf>=42)
    % x6 q8 D; P  ]' Z! F3 {
  95.   data=3;
    ' D% G: |: S7 [0 m
  96. else if(lpf>=20)
    ) E' o6 ]* Y# }% K& U
  97.   data=4;
    ' c2 }4 R" g8 n# ]! l
  98. else if(lpf>=10)) V6 \; I% R* M8 S: m: F, w$ F
  99.   data=5;
    ; W0 |9 B% h' a$ m- T, S
  100. else
    1 J* e4 ]- k* A  ~1 u. J
  101.   data=6;
    $ H9 E  B% R9 T# P
  102. return MPU_Write_Byte(MPU_CFG_REG,data);    // 设置数字低通滤波器  8 F. _- M5 e& ?( K
  103. }' g' y8 Q, l7 a/ W) M$ ^& O5 }

  104. 1 u, n7 s3 m% j/ @" @" X6 F1 o6 P
  105. /*********************************************************************3 v: @) I5 G& A3 [
  106. 函数名称:u8 MPU_Set_Rate(u16 rate)( |  a7 h4 n8 D) e6 j$ e& f- n
  107. 函数功能:设置MPU6050的陀螺仪采样率(只在陀螺仪输出频率Fs=1KHz时成立)
    5 S3 h& \2 Z* E
  108. 入口参数:rate:4~1000(Hz),陀螺仪采样频率
    2 ~6 M( J# o/ P+ `
  109. 返回参数:0,成功,1失败
    ; \- Y% l  w" l. r4 s/ Y- I
  110. 修改作者:Aaron
    5 n2 M5 L0 D* ]" p
  111. **********************************************************************/, o- x, Z( O* `$ N1 v) B
  112. u8 MPU_Set_Rate(u16 rate)# f. B& ~7 Q% s, N# s7 k# i" b) q
  113. {( v/ v+ T: k$ }: f% e7 n
  114. u8 data;+ f' a& G9 p' [2 d1 X) c, ?0 W5 [
  115. if(rate>1000)% A2 W% R6 O" r! Q- R
  116.   rate=1000;
    0 ~, Z. s$ f' r+ p* F2 i# W3 T
  117. if(rate<4). _0 v- ]% _# Y+ ~: i% y# [# z
  118.   rate=4;
    $ i! Y1 z8 }7 _9 _3 e% Q
  119. data=1000/rate-1;- G( j! U( U" b8 o/ a& j
  120. data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data);
    # u% C% a6 ?! B; M8 W
  121.   return MPU_Set_LPF(rate/2);                // 自动设置LPF为采样率的一半5 }( N8 y, G- ^1 S2 F3 E& R3 q
  122. }
    / T$ u* k* A# q/ @! R
  123. /********************************************************************** S: Q/ N3 W- M3 N& d
  124. 函数名称:short MPU_Get_Temperature()
    ( F9 e5 O1 _# _8 L6 l6 ~
  125. 函数功能:得到温度值2 e- K7 h1 h* R. X( y
  126. 入口参数:rate:4~1000(Hz),陀螺仪采样频率
    2 Y" \* f" {6 x9 M: \
  127. 返回参数:温度值(扩大了100倍)4 ]* |  U5 K  L
  128. 修改作者:Aaron
    4 V( L# G# d' l+ ~. c) o
  129. **********************************************************************/; ]5 B0 b+ Q$ K# F# d
  130. short MPU_Get_Temperature(void)
    4 R- Q& b2 W( y1 v5 W, f2 B
  131. {
    1 X8 O' g6 ?# D# p" c5 W
  132. u8 buf[2];
    $ s. W/ P6 x) L; z# y
  133. short raw;
    8 e$ |4 j- Q0 ~- K! \- m
  134. float temp;
    # q" x3 V: n5 s0 N' F5 g( d; ~
  135. MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); // addr:器件地址;reg:寄存器地址;len:写入长度;buf:数据区1 L7 [  O1 _1 o
  136. raw=((u16)buf[0]<<8)|buf[1];  4 m- e& Y6 L! K. ^( b# p2 j3 z
  137. temp=36.53+((double)raw)/340;  1 }* C" ]4 r9 x* b; T2 g7 E
  138. return
    9 p, a; _: ]. U$ ~! r/ C
  139.   temp*100;;
    " I0 ]6 k7 D1 M( E
  140. }4 l7 E2 J" E3 h; \( d: q1 I5 A
  141. /*********************************************************************6 C( b# U! C4 x  Z- V5 p
  142. 函数名称:u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)7 O, a: t! p# D% n! i
  143. 函数功能:得到陀螺仪值(原始值)1 |5 z; x' F. \
  144. 入口参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号): E. C8 j4 s4 z# V
  145. 返回参数:u8 0成功,1失败
    4 I5 P- o7 w6 \  E/ n4 y( \' |
  146. 修改作者:Aaron
    8 k/ P* [+ j  ?/ f7 g7 }& S
  147. **********************************************************************/) _/ y$ s( \/ S! R- N8 _
  148. u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
    7 n/ f9 D* Y' {# V& i
  149. {
    8 r& ^7 b- Z5 l
  150. u8 buf[6],res;  
    % J$ E2 J  p6 y" v9 m
  151. res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);; L* I* F# K: l, L
  152. if(res==0). ^1 ^1 K7 ]- B+ T8 m
  153. {
    & ]2 ^# P- d  `6 F1 s) o
  154.   *gx=((u16)buf[0]<<8)|buf[1];  , e. G7 R9 j/ g4 R+ X5 o
  155.   *gy=((u16)buf[2]<<8)|buf[3];  
    ) f+ C) d8 r1 O/ K5 \
  156.   *gz=((u16)buf[4]<<8)|buf[5];4 Y- s8 @6 R2 W/ \6 r7 u
  157. }  3 ~8 S  Y( i, p" J0 V+ d$ F  a0 I/ y5 c& Y
  158. return res;;
    7 i8 E! G  H" }# h
  159. }
    ; \9 U' ^, ?% A4 S
  160. /*********************************************************************) j3 \2 h% y, Y7 y( C: T+ Q
  161. 函数名称:u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
    5 n8 ^. I" V& Z
  162. 函数功能:得到加速度值(原始值)
    0 }" W2 a# n7 S% E* i6 E! e. q2 d5 J
  163. 入口参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
    * d3 k8 b# `. S& \4 K2 G
  164. 返回参数:u8 0成功,1失败
    / j$ R2 Z( M& O# j7 l, k4 t; N
  165. 修改作者:Aaron
    0 @' o' P% y" G3 e( [$ f7 v# u
  166. **********************************************************************/
    $ O" S# I$ x7 C$ S
  167. u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
    % B, [: f6 M, l' V
  168. {
    $ T# F$ w" L( K" |4 P5 |( p
  169. u8 buf[6],res;  
    & I4 u. Q, H5 {( q3 u5 U" I( M; n* |2 o/ y
  170. res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);- K7 Q% r5 t1 _  }1 U
  171. if(res==0)
    & f5 q& x) W4 f
  172. {: w" {7 u- Z+ H( k0 t6 K4 b8 V
  173.   *ax=((u16)buf[0]<<8)|buf[1];  
    . y3 w0 f& M8 n% @
  174.   *ay=((u16)buf[2]<<8)|buf[3];  
      t0 k. ^. W: v! \' i) A1 E
  175.   *az=((u16)buf[4]<<8)|buf[5];
    1 W4 `' ]$ X3 G! e, U0 G
  176. }  0 X5 e! h3 `, m) u. T: e2 o
  177. return res;;" m, X4 w0 ~! h( H0 o. H" C
  178. }
    $ Z4 Q0 A9 U4 E- U7 t
  179. /*********************************************************************
    7 G% I$ F" H+ p, K; R: ^/ _9 ~
  180. 函数名称:u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
    ( Q( z& P  f. o, @$ Z
  181. 函数功能:向MPU6050连续写入数据7 G! |- y" a# ?
  182. 入口参数:addr:器件地址;reg:寄存器地址;len:写入长度;buf:数据区: z3 z+ K* ?7 U5 ~' j# C
  183. 返回参数:u8 0成功,1失败
    + ]4 P9 P6 Y% Z9 N9 b
  184. 修改作者:Aaron
    9 L- I+ @7 d& t- `
  185. **********************************************************************/& e0 G% K( j: J7 Q* W
  186. u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)& C- s& L2 T0 s" I# v
  187. {$ e( V& z8 X  t% T+ x* q. T' Y  c
  188. u8 i; * O, M4 N) s4 W8 {1 H. K( h6 i
  189. MPU_IIC_Start();
    . ^( W4 H! _) d/ ]7 I  h
  190. MPU_IIC_Send_Byte((addr<<1)|0);   // 发送器件地址+写命令
    7 @9 F0 S8 }9 X
  191. if(MPU_IIC_Wait_Ack())               // 等待应答( E1 x: f, F) c6 _% b
  192. {: n, V! F3 j: D: _: Y
  193.   MPU_IIC_Stop();     c( W$ O) q+ _) v4 M  _" l
  194.   return 1;  6 {% C$ F% J; ~* {1 w! _
  195. }+ A9 v2 j+ X. W/ [& K
  196. MPU_IIC_Send_Byte(reg);              // 写寄存器地址
    9 `/ x; y  W" R0 @& l- y
  197. MPU_IIC_Wait_Ack();              // 等待应答
    8 o8 \6 }0 O5 i  G( `2 W
  198. for(i=0;i<len;i++)
    4 ^/ [% Q4 ^, ?% e6 R7 W9 w
  199. {
    : t* N& ]5 _: e+ X" n' m6 D2 V
  200.   MPU_IIC_Send_Byte(buf);      // 发送数据
    % O' [6 W$ r- X$ A5 i9 ?/ j
  201.   if(MPU_IIC_Wait_Ack())          // 等待应答
    $ n. X4 D& w1 w2 V% p
  202.   {
    $ A# v" v5 K- V
  203.    MPU_IIC_Stop();  
    3 `( W, u5 s8 _8 v. u2 c# a
  204.    return 1;   
    + t0 H& [; Y, p% p+ m% ?# C( S
  205.   }  5 O0 T: [( m, s! C
  206. }    , i9 H3 g7 z3 Q4 p- ~$ _8 g
  207. MPU_IIC_Stop();  4 }7 N, U/ D' g" p7 N
  208. return 0;
    # a# U! d2 M- e; c
  209. }
    , x! F3 A( Q7 {; ?9 t. v
  210. /*********************************************************************
    $ g/ p) Z% J1 Z8 O9 A
  211. 函数名称:u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)* L# L7 j, e% h+ e
  212. 函数功能:从MPU6050连续读数据* q) v! F# @# f8 l+ H
  213. 入口参数:addr:器件地址;reg:要读取的寄存器地址;len:要读取的长度;buf:读取到的数据存储区* L5 ?) i! I2 [/ A: x( b
  214. 返回参数:u8 0正常,1错误
    0 f8 D6 L" c9 p, l0 _6 J
  215. 修改作者:Aaron0 \+ a& F. i( B2 l# d2 U; J" x
  216. **********************************************************************/% m9 }% F. r4 F
  217. u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
    8 e$ N1 s) \7 |, B  Z. \
  218. {
    / G  I, M. b  e# z, U: w
  219. MPU_IIC_Start(); , I$ j' y  c" p, e+ U) _$ t" K- B8 S
  220. MPU_IIC_Send_Byte((addr<<1)|0);    // 发送器件地址+写命令 9 W$ S* l( ^2 B8 d
  221. if(MPU_IIC_Wait_Ack())             // 等待应答
    " k+ z8 [5 u9 x+ ^0 H
  222. {1 g/ F( `) u+ p2 L9 P- l
  223.   MPU_IIC_Stop();   
    , z4 _* P" P: i* w' h3 U% Z
  224.   return 1;  
    6 L' J5 c' S& n- w
  225. }: t( d, k+ n7 d0 e
  226. MPU_IIC_Send_Byte(reg);            // 写寄存器地址
    . H" g. C9 ]$ V9 n! I4 E: e+ s0 P7 a
  227. MPU_IIC_Wait_Ack();                // 等待应答) ?" g/ c* `; w# `* R* m& ^: B
  228. MPU_IIC_Start();
    # _( s+ M+ k: R
  229. MPU_IIC_Send_Byte((addr<<1)|1);    // 发送器件地址+读命令 $ ^. F( x: c/ Z" o
  230. MPU_IIC_Wait_Ack();                // 等待应答 1 N5 g% t+ w0 M
  231. while(len)2 f4 k$ i& k5 h' s& `+ ]6 R7 `! @: v( [
  232. {
    0 T# c0 Y0 q. b' W7 W
  233.   if(len==1)*buf=MPU_IIC_Read_Byte(0); // 读数据,发送nACK
    : Q9 f2 h) ?: x( D- j/ O
  234.   else *buf=MPU_IIC_Read_Byte(1);      // 读数据,发送ACK  
    5 B5 \* N4 B, k
  235.   len--;
      S# C2 z; g5 {& y
  236.   buf++;
    8 R* C& [7 p7 U' e: P0 j
  237. }    2 d5 k/ N2 Q) B# g) n: g
  238.     MPU_IIC_Stop();  // 产生一个停止条件
    2 Q# f5 \: `6 u4 N4 \( S; s
  239. return 0; 4 I. d# |% u6 a' w
  240. }- E$ o4 P# Y: b, ~" r
  241. /*********************************************************************
    . @) R; ?+ x' R& t
  242. 函数名称:u8 MPU_Write_Byte(u8 reg,u8 data) 6 L) T$ X- F7 _/ [
  243. 函数功能:向MPU6050写一个字节 0 T8 p; A! ^( p* n
  244. 入口参数:reg:寄存器地址;data:数据7 y$ X3 ]; l, ]7 f9 H0 q9 K
  245. 返回参数:0,正常;1,失败7 s. n3 G8 e: [5 h
  246. 修改作者:Aaron. N3 k' q) Y) B# P& t: w2 S
  247. **********************************************************************/
    4 Y- C8 Q4 p; D
  248. u8 MPU_Write_Byte(u8 reg,u8 data)      " c9 Z. u. A7 W
  249. { ; c& j' h$ W' i0 n0 S: t" k1 S
  250. MPU_IIC_Start(); * X) E5 e: _& e/ K! O4 H
  251. MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);  // 发送器件地址+写命令
    & O" C/ y; N3 F
  252. if(MPU_IIC_Wait_Ack())                     // 等待应答,0接收应答成功,1接收应答失败( A* T/ v* n4 y6 R1 u/ L
  253. {% B6 g( M3 e; ]: O1 ]+ f
  254.   MPU_IIC_Stop();                             // MPU_IIC停止信号
    $ y# B0 L+ Q8 A; K, r& u
  255.   return 1;  
    / O/ u) m/ r# W% o/ I/ Y
  256. }' ~' I  C; E0 Z
  257. MPU_IIC_Send_Byte(reg);              // 写寄存器地址
    " l- W$ X% H( D& c+ \
  258. MPU_IIC_Wait_Ack();                  // 等待应答 9 I" B- E- ~& w$ D4 @+ K& _
  259. MPU_IIC_Send_Byte(data);             // 发送数据1 P) G& b: k  e6 Q: m
  260. if(MPU_IIC_Wait_Ack())               // 等待应答
    0 ~/ w  G* x! B* U% v; a
  261. {
    2 T' T4 [2 @2 y
  262.   MPU_IIC_Stop();  5 [; [( S" @4 C& F: ~8 F: K
  263.   return 1;   % U/ q$ D8 b" O+ _/ ^9 V' G4 V
  264. }   ) Q0 k0 Q. g% [: v1 _5 u
  265.     MPU_IIC_Stop();  5 K3 Y9 T! W8 }2 C7 C6 l
  266. return 0;* n& O' Q1 u' O, H, a6 i5 B* ]
  267. }( t9 h/ T7 \0 V) [# t
  268. /*********************************************************************' l7 M6 l, E0 Y) r4 k9 r( }
  269. 函数名称:u8 MPU_Read_Byte(u8 reg)
    . ]) {. v" S2 Z. I3 k7 K4 ?! B
  270. 函数功能:从MPU6050读一个字节
    4 s  A: ~: o6 p+ ]$ d7 r8 ^9 v" O
  271. 入口参数:reg:寄存器地址
    8 u/ [& v4 N; u, m' \' g
  272. 返回参数:u8 读到的数据
    $ n  H. C$ ~' _
  273. 修改作者:Aaron7 M% J& a' _% W5 U# I6 q5 s, d4 @
  274. **********************************************************************/) a5 O% U* i7 \. e6 D
  275. u8 MPU_Read_Byte(u8 reg)
    6 }! k1 ?! t5 t
  276. {
    + o0 G# Q- Z. ~0 a- q; c/ N: r
  277. u8 res;1 q) d8 g* ^; y* o( W8 B! f6 P  a
  278. MPU_IIC_Start(); : F, F4 f" X2 n' ~/ C0 m& {
  279. // 开始标志(S)发出后,主设备会传送一个 7 位的 Slave 地址,并且后面跟着一个第 8 位,称为 Read/Write 位。 0写,1读。3 D4 w6 \! i0 d$ U
  280. MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);   // 发送器件地址+写命令
    ' k, \- y9 w. y( ~+ _6 h
  281. MPU_IIC_Wait_Ack();                           // 等待应答 $ y2 u: [! F" @( X
  282. MPU_IIC_Send_Byte(reg);                         // 写入要读取字节的寄存器首地址
      s* m& A( J; z3 F; Z+ F
  283. MPU_IIC_Wait_Ack();                          // 等待应答& e: a6 W( r% z0 P+ u9 f+ l$ O# X1 _
  284. MPU_IIC_Start();  [$ U7 d$ P! R) z8 k
  285. MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);   // 发送器件地址+读命令 & k  p  m+ L8 @1 [0 v4 Q) v. Y
  286. MPU_IIC_Wait_Ack();                           // 等待应答 2 A8 C2 I, g. o8 R
  287. res=MPU_IIC_Read_Byte(0);                        // 读取一个字节的数据,发送nACK % }3 t3 u% c4 N
  288. MPU_IIC_Stop();                                    // 产生一个停止条件
    ( H& \9 U: e  z  k6 b+ z8 Q8 }
  289. return res;  , k& x5 _" I6 D2 m- z
  290. }  U4 ^( o5 J: r+ J, x
  291. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码
% f* y9 a/ Q" E& C- Y0 f
10.5 main.c主函数, m# K2 G4 y/ U$ l1 j( g
8 M+ J2 ?) X/ u5 K
  1. /**& O* m- V9 t  W
  2. ********************************  STM32F10x  *********************************& e+ ^9 Y/ |9 n3 A2 s. I) ^5 ~
  3. * @文件名称: main.c; t) O$ q( i9 `
  4. * @修改作者: Aaron
    % `5 b% j- q" Y8 s- @
  5. * @库版本号: V3.5.0
    $ Y  g# L8 j+ X
  6. * @工程版本: V1.0.0, z6 v7 n/ ^1 F! m. N6 ~
  7. * @开发日期: 2020年11月30日; x! b6 k. P: s( J. u+ N& q0 ]2 Q
  8. * @摘要简述: 主函数,增加了在LCD显示6轴的原始数据4 u. c% |) v$ V& C
  9. ******************************************************************************/  S2 S/ q. j9 A/ E" K
  10. /*-----------------------------------------------------------------------------
    3 n" y" u( }, `
  11. * @更新日志:
    3 ]% N, ^* e/ @8 Z& l/ l
  12. * @无  l" d% |' a! W1 i
  13. * ---------------------------------------------------------------------------*/7 g0 S/ ?/ X1 U) o* I2 l8 A* j% ?
  14. /* 包含的头文件 --------------------------------------------------------------*/5 ]+ e: u# T; a" O$ A3 M! i
  15. #include "led.h"% C6 |, A: c( V* x6 I
  16. #include "delay.h"
    1 o3 a5 l) R( m7 s$ F. \: @. A
  17. #include "key.h"1 y  j; e( U2 x& D
  18. #include "sys.h"% [/ l# R$ [4 H. Q
  19. #include "lcd.h"/ c6 R1 R( l, |4 V: A
  20. #include "serial_communication.h"
    : Q) k2 `( S4 K4 t3 j$ O6 g! W
  21. #include "mpu6050.h"
    $ t( P9 L1 L8 D& M! a) f9 S
  22. #include "inv_mpu.h"
      r: x* r( _; `# E8 q  q
  23. #include "inv_mpu_dmp_motion_driver.h"
    ( e. q1 y$ f' ?
  24. /*********************************************************************) z2 m, P6 V. M  v; J& `
  25. 函数名称:usart1_send_char(u8 c)
    ) c" k6 H5 Y- }6 ?' `
  26. 函数功能:串口1发送1个字符6 @6 M$ b( O9 L( B
  27. 入口参数:c:要发送的字符$ O4 ^% n% r1 {' s
  28. 返回参数:0,成功,1失败
    $ E4 o# u" M0 p4 g7 b8 W7 `7 H
  29. 修改作者:Aaron3 R/ p1 w; i, M' R2 {; F; C9 D5 `/ @) _
  30. **********************************************************************/
    - r5 p' j0 e% `% i+ G
  31. void usart1_send_char(u8 c)
    % x0 M1 `2 a! r9 m
  32. {           
    9 W# ~4 I# R4 y* s9 a# o
  33.         while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); // 循环发送,直到发送完毕   6 [& B4 c7 k/ Q* [2 `* N/ {# `3 ]
  34.         USART_SendData(USART1,c);  
      c7 Q5 j# w- ]5 h5 D
  35. }
    5 |8 Y6 t4 J, C: C3 o4 ^, F
  36. /*********************************************************************
    8 D& U7 J) V2 Q7 U
  37. 函数名称:usart1_niming_report(u8 fun,u8*data,u8 len)
    : ~4 f4 _+ Q4 [
  38. 函数功能:传送数据给匿名四轴上位机软件
    4 d5 ~9 L" W. B
  39. 入口参数:fun:功能字.0XA0~0XAF;data:数据缓存区,最多28字节;len:data区有效数据个数: L' a* o7 j/ b! m, s( n# I
  40. 返回参数:无1 D( ~0 v5 p) S) K2 e7 h! ^2 A+ Q$ H
  41. 修改作者:Aaron
    * ^8 p: W0 N" @7 v. x8 I5 F
  42. **********************************************************************/
    ; Q* U- x: U% \" I% ]. H- b1 X
  43. void usart1_niming_report(u8 fun,u8*data,u8 len)
    ; Q& @! j7 H8 K  N
  44. {% @2 m! G3 C  s0 y1 N, v( y1 P' m6 q) h: B
  45.         u8 send_buf[32];) y+ @0 E4 o# ?
  46.         u8 i;6 |% b! Z2 a! p- ]/ O
  47.         if(len>28)return;                // 最多28字节数据 ' H- W4 }: A2 u8 D# ]& ^
  48.         send_buf[len+3]=0;                // 校验数置零, d1 {9 E% v- g# E
  49.         send_buf[0]=0X88;                // 帧头
    & g; C* f2 l; D/ [$ u2 y" o
  50.         send_buf[1]=fun;                // 功能字4 z! |8 ~2 r9 C
  51.         send_buf[2]=len;                // 数据长度
    : T1 L7 g2 m/ t. P& Z% n' `3 f
  52.         for(i=0;i<len;i++)send_buf[3+i]=data;                                                // 复制数据
    4 i$ E, l8 C. g8 @
  53.         for(i=0;i<len+3;i++)send_buf[len+3]+=send_buf;                                // 计算校验和        & r( p7 O- b% A5 z6 ^% Q
  54.         for(i=0;i<len+4;i++)usart1_send_char(send_buf);                                // 发送数据到串口1 * P9 ?- m# O/ B# c5 O, `" X. Y5 O
  55. }
    ' L/ ?. X3 \" m6 @2 f9 I: E
  56. /*********************************************************************  I- j8 b. _: k! u
  57. 函数名称:mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)4 O: V  K- I5 D' V
  58. 函数功能:发送加速度传感器数据和陀螺仪数据8 R5 X6 k4 ~* [
  59. 入口参数:aacx,aacy,aacz:x,y,z三个方向上面的加速度值;gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值
    3 o3 E- H/ g; q: Q. }# K$ m4 A
  60. 返回参数:无9 [4 c$ j7 g! ~' m9 H
  61. 修改作者:Aaron9 ^2 G7 k3 `9 f  S4 l7 m  q. j
  62. **********************************************************************/
    ) g8 D1 |. y5 P9 g7 S. [
  63. void mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz), \2 U& G- L. r
  64. {' N4 A+ L/ C; [# N# U, G% c) y
  65.         u8 tbuf[12];
    & p# k( y6 f/ d0 E5 j0 h
  66.         tbuf[0]=(aacx>>8)&0XFF;
    / b/ R' l5 x+ z5 a. p/ F* E% u. V
  67.         tbuf[1]=aacx&0XFF;
    8 u' G7 t* H! G" m6 L
  68.         tbuf[2]=(aacy>>8)&0XFF;2 U* ?0 Y' }" i# t- Z
  69.         tbuf[3]=aacy&0XFF;
    ! Z$ |. J. _) q$ ~
  70.         tbuf[4]=(aacz>>8)&0XFF;  N2 ?3 E3 U" w2 b. z' S
  71.         tbuf[5]=aacz&0XFF;
    ) c; K' D* e1 {; K5 L; O
  72.         tbuf[6]=(gyrox>>8)&0XFF;
    ' q/ t8 B- u# g+ l
  73.         tbuf[7]=gyrox&0XFF;
    " t; B8 o6 W3 y+ p+ X. H
  74.         tbuf[8]=(gyroy>>8)&0XFF;
    5 ]5 M  Q2 K% w5 P% \6 h) k# }
  75.         tbuf[9]=gyroy&0XFF;( F2 w' }# k2 C! a1 u
  76.         tbuf[10]=(gyroz>>8)&0XFF;
    # u. s% C* o2 E, c! x/ I. o5 P
  77.         tbuf[11]=gyroz&0XFF;5 `4 j0 y. u( r! |& c7 U' C- g
  78.         usart1_niming_report(0XA1,tbuf,12);                // 自定义帧,0XA1
    " t6 c. ?+ M9 W: P% s( E  L+ M
  79. }        
    1 L0 ]4 w" y# k1 G( s% m
  80. /*********************************************************************
    6 b2 c+ c- J& x. h+ V1 p
  81. 函数名称:mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)# M+ B( Y; b9 V
  82. 函数功能:通过串口1上报结算后的姿态数据给电脑
    ; r: Z( A- ]- q( C3 W  M9 \/ [+ q  R
  83. 入口参数:aacx,aacy,aacz:x,y,z三个方向上面的加速度值;gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值;
    7 P4 _: v8 J+ f( b
  84.                                         roll:横滚角.单位0.01度。 -18000 -> 18000 对应 -180.00  ->  180.00度;
    $ O9 i& X: o+ L
  85.                                         pitch:俯仰角.单位 0.01度。-9000 - 9000 对应 -90.00 -> 90.00 度
    8 R0 ^$ ~; }, U
  86.                                         yaw:航向角.单位为0.1度 0 -> 3600  对应 0 -> 360.0度
    / }. |4 [9 h2 [( C' u
  87. 返回参数:无6 R# ^  V. g/ S/ X- \& o0 A
  88. 修改作者:Aaron
    # {( r+ p8 B! h
  89. **********************************************************************/
    5 c" U% ~9 B7 b4 I' \
  90. void usart1_report_imu(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz,short roll,short pitch,short yaw)' I+ d9 e  U) r0 M
  91. {+ a+ _1 l  n$ J
  92.         u8 tbuf[28];
    6 b4 X. d9 }1 g- S0 z2 G/ D' ]
  93.         u8 i;
    4 o9 f) ]) W' R. z  S3 |* `
  94.         for(i=0;i<28;i++)tbuf=0;                                        // 清0. X6 _' K+ Y4 K0 q; ?
  95.         tbuf[0]=(aacx>>8)&0XFF;
      Y3 a$ t+ f  B
  96.         tbuf[1]=aacx&0XFF;1 B: j9 g$ z+ U
  97.         tbuf[2]=(aacy>>8)&0XFF;" M$ Q; [: X4 w# b
  98.         tbuf[3]=aacy&0XFF;6 @6 X, R3 Y$ a! m$ l* E$ j0 \
  99.         tbuf[4]=(aacz>>8)&0XFF;' X3 ]* w0 f; e5 d6 z! u( y3 E: a
  100.         tbuf[5]=aacz&0XFF;
    / P! h' b0 Y! @/ i- z
  101.         tbuf[6]=(gyrox>>8)&0XFF;
    * T% I# E0 n2 {0 _
  102.         tbuf[7]=gyrox&0XFF;
    . ~5 U" s9 R" j& U' b: _4 z" N
  103.         tbuf[8]=(gyroy>>8)&0XFF;
    / U' P) r* m6 r3 k5 R7 \/ O' L. h
  104.         tbuf[9]=gyroy&0XFF;0 r1 j* U0 r, j7 V3 z6 o
  105.         tbuf[10]=(gyroz>>8)&0XFF;
    0 \: j/ q$ y8 w. I% S* e
  106.         tbuf[11]=gyroz&0XFF;        
    1 n4 s/ U' m; t# x
  107.         tbuf[18]=(roll>>8)&0XFF;1 ?: V$ m# x  v, `: m5 Y8 E8 J' p, N
  108.         tbuf[19]=roll&0XFF;$ k& G7 @/ S! \1 u3 K, G; j
  109.         tbuf[20]=(pitch>>8)&0XFF;
    - l6 c" M. _4 V2 b( w; }
  110.         tbuf[21]=pitch&0XFF;
    # Q0 E1 {6 {9 T  s" J
  111.         tbuf[22]=(yaw>>8)&0XFF;1 k+ D9 o; y% w7 r
  112.         tbuf[23]=yaw&0XFF;
    8 J& `9 f! B. ]& t# Z+ p# v) l
  113.         usart1_niming_report(0XAF,tbuf,28); // 飞控显示帧,0XAF$ U" D5 W' }2 W
  114. }  
    5 y3 z- i# w& V7 M; e
  115. /*********************************************************************, W8 s" Z. }2 W6 e* r, z8 H' U& o. ~2 [
  116. 函数名称:int main()7 }6 X" W+ e0 k0 s2 e
  117. 函数功能:主函数,增加了在LCD屏上显示6轴原始数据的功能$ J/ N+ m' \* g/ `; P7 \2 [8 Z4 [
  118. 入口参数:无
    % N4 }5 h/ b+ K# I% S9 i6 A
  119. 返回参数:无1 V. s1 u; P6 Y: O$ \/ p& H* U
  120. 修改作者:Aaron
    4 x* z+ \% s5 V
  121. **********************************************************************/
    0 {+ I4 b1 [  _2 k7 h  b% Z
  122. int main(void)
    2 J! e2 q4 m* g" a  R- {1 ]
  123. {         
    7 E: m' H8 V8 V+ ?+ B" F/ V
  124.         u8 t=0,report=1;                                                // 默认开启上报,发给匿名四轴上位机软件. _( D$ a5 w4 n% k) n) G
  125.         u8 key;/ `1 p& r* v% H; Q
  126.         float pitch,roll,yaw;                                         // 欧拉角
    9 g8 r6 U9 x6 n* B$ H" d. {
  127.         short aacx,aacy,aacz;                                        // 加速度传感器原始数据
    3 M4 U2 M) b" N( P* T# v# Q
  128.         short gyrox,gyroy,gyroz;                                // 陀螺仪原始数据
    . E7 C8 v# p1 B8 V; v7 R$ J; A( I+ A
  129.         short temp;                                                                // 温度         
    % {0 _6 p# {3 y/ D1 |, B/ q3 @
  130.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                         // 设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    ( u( Z! w% v. b5 a+ u) @
  131.         My_USART1_Init();                                                                                  // 串口初始化为500000
    3 L3 }' x9 o% j* M3 d7 \: s
  132.         delay_init();                                                                                         // 延时初始化
    0 w7 Q. h7 ?" j* R6 t- I0 A
  133.         LED_Init();                                                                                                   // 初始化与LED连接的硬件接口. T' J* k2 Y8 u1 \3 a' {4 X2 F5 k
  134.         KEY_Init();                                                                                                 // 初始化按键
    $ A3 H: y+ d0 p2 h1 j2 E  W
  135.         LCD_Init();                                                                                                    // 初始化LCD  $ z2 W: A2 `( T6 k5 w1 V
  136.         MPU_Init();                                                                                                 // 初始化MPU6050
    8 a" C4 t6 b9 h- W' d
  137.          POINT_COLOR=RED;                                                                                 // 设置字体为红色         . E% F) A5 G0 z9 M- h9 Q0 W
  138.         LCD_ShowString(30,70,200,16,16,"MPU6050 TEST");        
    " t  j& ~1 Q7 b0 S& X
  139.         LCD_ShowString(30,90,200,16,16,"2020/11/30"); 8 ?8 [; W; R% M) R
  140.         while(mpu_dmp_init())
    ) W& k9 m+ ?4 |1 `* q4 y: _
  141.          {
    ) u" m5 d" d/ |+ t# A
  142.                 LCD_ShowString(30,110,200,16,16,"MPU6050 Error");
    ) ^' P  F$ G9 j- s" _& ]" L
  143.                 delay_ms(200);
    + j3 W- [3 G4 J- v% Z4 _% E  P
  144.                 LCD_Fill(30,110,239,130+16,WHITE);7 n0 v, f, e+ f( F2 {
  145.                  delay_ms(200);
    4 H: I3 M+ m9 d' o  F& n
  146.         }  ! I! d6 ?2 H; a- v. r& W0 g; q; H+ F
  147.         LCD_ShowString(30,110,200,16,16,"MPU6050 OK");
      b4 r* O) m( {  C6 Q, `8 |" q# V5 e  N
  148.         LCD_ShowString(30,130,200,16,16,"KEY0:UPLOAD ON/OFF");
    & M5 j- N7 A( A7 u* U
  149.         POINT_COLOR=BLUE;                                                                                                                                 // 设置字体为蓝色
    / X# V) |7 F  B; h. |- x
  150.          LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");         
    3 D* J/ U5 H6 o" @* f
  151.          LCD_ShowString(30,200,200,16,16," Temp:    . C");        
    % r" l0 b# g# ]5 T" s# F
  152.          LCD_ShowString(30,220,200,16,16,"Pitch:    . C");        
    $ a2 a  N0 J' R
  153.          LCD_ShowString(30,240,200,16,16," Roll:    . C");         1 @" m, R. f- ~/ |$ Z
  154.          LCD_ShowString(30,260,200,16,16," Yaw :    . C");           k% C! [' a0 p
  155.          while(1)$ P& r; W: [7 v1 @9 I
  156.         {
    4 o" U& t$ }0 m( u2 R, |
  157.                 key=KEY_Scan(0);
    / o/ ^: C9 T, V" N
  158.                 if(key==KEY0_PRES)6 G) J8 x9 Q+ h# ~# g+ U5 k
  159.                 {
    ; D: f( v+ N/ X! N' Y% c
  160.                         report=!report;! k# ]9 I9 d' Y
  161.                         if(report)
    ' C: A7 N) F" C7 S* e: Y4 Y! R
  162.                                 LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");9 X* t. l* j- J( ^
  163.                         else . o2 n# v" ]. }, J3 t  P8 C
  164.                                 LCD_ShowString(30,170,200,16,16,"UPLOAD OFF");
    $ i  \5 b( z* S* Z
  165.                 }
    $ Z- J, \1 \+ Z6 M
  166.                 if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
    ' m  ^( m  M: P* f( e5 x
  167.                 {
    6 @- s0 k" x+ F
  168.                         temp=MPU_Get_Temperature();                                                                        // 得到温度值                 7 T1 r8 F1 i" L0 I" {! a( z
  169.                         MPU_Get_Accelerometer(&aacx,&aacy,&aacz);                                        // 得到加速度传感器数据
    + u; q/ y2 u6 m. T7 m
  170.                         MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);                                        // 得到陀螺仪数据6 m3 E' E- s; k  U
  171.                         if(report)
    ' _( I! m6 B8 q  x% v) g
  172.                                 mpu6050_send_data(aacx,aacy,aacz,gyrox,gyroy,gyroz);        // 用自定义帧发送加速度和陀螺仪原始数据" w2 G1 y- O  V# L1 `' J
  173.                         if(report)
    4 t; B+ Q8 `! M+ R, g8 h5 ]6 |
  174.                                 usart1_report_imu(aacx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),(int)(pitch*100),(int)(yaw*10));/ y! J- }: _& |% f
  175.                         LCD_ShowString(30,300,200,16,16," aacx:    ");                                                                  ! ~3 c. s/ `+ @
  176.                         if(aacx<0)* c  V+ i) M7 E. N0 Q% T
  177.                         {
    * J& K& X. c" e$ c6 F
  178.                                 LCD_ShowChar(30+48,300,'-',16,0);                         // 显示负号
    3 k( ^& _) @- P- \  s
  179.                                 aacx=-aacx;                                                                        // 转为正数- `# O5 \- i, M: j: y( X0 l8 X
  180.                         }$ N" J. u/ i( u5 L. g& w
  181.                         else ' i. X0 p) g4 h" G; \1 n5 W
  182.                                 LCD_ShowChar(30+48,300,' ',16,0);                        // 去掉负号
    ! l7 ~- y' i( i% Q0 t
  183.                         LCD_ShowNum(30+48+8,300,aacx,10,16);                        // 显示aacx                           
    % F6 r* x  f8 U( ?( i; Y. Q, T
  184.                         LCD_ShowString(30,320,200,16,16," aacy:    ");        
    2 w8 C2 p3 q  O' i
  185.                         if(aacy<0)
    ) ]: j5 L7 P- E- _  Z
  186.                         {! y5 h' Z* G! A4 s+ @4 ^/ t; H
  187.                                 LCD_ShowChar(30+48,320,'-',16,0);                          // 显示负号
    2 \9 N- B: D9 Z4 X" Z5 |/ Y* W
  188.                                 aacy=-aacy;                                                                        // 转为正数* k6 {0 O: L' f
  189.                         }7 V2 ~! X* O) q) {% ?
  190.                         else
    * d0 b* N. T7 F0 T
  191.                                 LCD_ShowChar(30+48,320,' ',16,0);                        // 去掉负号 - S$ V7 A0 D1 i1 t4 U( n
  192.                         LCD_ShowNum(30+48+8,320,aacy,10,16);                        // 显示aacy            $ @6 I' k3 ~4 W& P6 i& b1 |% i
  193.                         LCD_ShowString(30,340,200,16,16," aacz:    ");         5 x* j- j  Y( W
  194.                         if(aacz<0)
    & i" W; I  x5 q
  195.                         {
    % z; s8 m- z( }$ b# b# l9 Q# w
  196.                                 LCD_ShowChar(30+48,340,'-',16,0);                          // 显示负号
    4 p4 F  J1 d5 \: v( G; l
  197.                                 aacz=-aacz;                                                                        // 转为正数
    . Y% J) d, K. W6 y5 `- z6 N
  198.                         }
    $ w/ |1 d% ?+ C0 D  E0 J
  199.                         else
    ! E4 ~2 Z# }6 O- Y; h$ @$ l
  200.                                 LCD_ShowChar(30+48,340,' ',16,0);                        // 去掉负号 6 ?. {! E3 B  N9 x( W
  201.                         LCD_ShowNum(30+48+8,340,aacz,10,16);                        // 显示aacz           , Z6 K1 F5 |1 A: J, D
  202.                         LCD_ShowString(30,360,200,16,16,"gyrox:    ");        
    9 {: x( o# Z' Z, z$ }
  203.                         if(gyrox<0)% P1 r( j6 w  S  s
  204.                         {
    4 g2 h% [3 @/ ]1 A
  205.                                 LCD_ShowChar(30+48,360,'-',16,0);                          // 显示负号3 T$ C* F9 |! d) j! f  g
  206.                                 gyrox=-gyrox;                                                                // 转为正数
    : S3 t( ?, T4 A# P! y
  207.                         }
    . _/ W0 T2 k* b# s' |$ N
  208.                         else + i+ B/ P& a; l5 b  g
  209.                                 LCD_ShowChar(30+48,360,' ',16,0);                        // 去掉负号
    & s. k& e1 l$ j0 l* U- K
  210.                         LCD_ShowNum(30+48+8,360,gyrox,10,16);                        // 显示gyrox    - r. u* Z$ w- j- u
  211.                         LCD_ShowString(30,380,200,16,16,"gyroy:    ");        
    7 i, L" ~/ ?" r% M3 u
  212.                         if(gyroy<0)- {& H  A/ u% [+ T, |
  213.                         {
    ' G7 G+ a& Q6 y: G- T' ^* i0 T1 d' A& t
  214.                                 LCD_ShowChar(30+48,380,'-',16,0);                          // 显示负号
    ; P+ t# e0 a4 R% ^. }8 E
  215.                                 gyroy=-gyroy;                                                                // 转为正数
    + ]' M. g% M$ U+ M3 W
  216.                         }0 T& S. M- l+ F, t6 V1 I
  217.                         else
    % X7 q( M. K4 x; S5 J
  218.                                 LCD_ShowChar(30+48,380,' ',16,0);                        // 去掉负号 , j6 P0 H: m2 R
  219.                         LCD_ShowNum(30+48+8,380,gyroy,10,16);                        // 显示gyroy                   0 i- f" Y/ m/ D' A' O5 x
  220.                         LCD_ShowString(30,400,200,16,16,"gyroz:    ");
    / g* {# N( H( f, t: |- V1 `
  221.                         if(gyroz<0): ^4 A' `* x- ?6 Y, \! E
  222.                         {
    ! J3 T3 g  Z& o- P7 K9 h* [
  223.                                 LCD_ShowChar(30+48,400,'-',16,0);                          // 显示负号
    # Z+ {, h1 [% Z& Y7 c7 r
  224.                                 gyroz=-gyroz;                                                                // 转为正数/ d8 y+ B/ u- N' z+ _7 E0 O
  225.                         }
    + y5 N, @' T; B- E5 f! `+ E
  226.                         else
      @  \% z9 @4 ]4 B
  227.                                 LCD_ShowChar(30+48,400,' ',16,0);                        // 去掉负号 # g: E5 R: A0 b8 S8 ]* N4 g
  228.                         LCD_ShowNum(30+48+8,400,gyroz,10,16);                        // 显示gyroz                           
    5 x0 [% w" q# X, k
  229.                         if((t%10)==0)
    9 O3 V+ @3 W/ }4 x# l3 }
  230.                         { 5 D2 T8 u) C+ y: x' s, q4 \# C
  231.                                 if(temp<0)
    1 ?- Q; C% }2 O7 Y- s* m
  232.                                 {$ e# C; O3 j+ {' n0 K
  233.                                         LCD_ShowChar(30+48,200,'-',16,0);                // 显示负号
    6 }6 M: A6 e( h6 E9 n  S- P7 k
  234.                                         temp=-temp;                                                                // 转为正数1 b0 H: B1 j- A( v2 x5 _
  235.                                 }
      P& _' r) x/ X' U/ |2 T
  236.                                 else $ K3 |" b, j0 w9 }2 a
  237.                                         LCD_ShowChar(30+48,200,' ',16,0);                // 去掉负号
    ' R! a2 ^) \( Q+ s7 e4 k+ _
  238.                                 LCD_ShowNum(30+48+8,200,temp/100,3,16);                // 显示整数部分            5 J9 `6 i  k$ U7 d5 _
  239.                                 LCD_ShowNum(30+48+40,200,temp%10,1,16);                // 显示小数部分 # @! H9 B: T$ n% O+ A' ~4 {
  240.                                 temp=pitch*10;
    $ \: ]) l- W1 m! k
  241.                                 if(temp<0)/ a1 q" n- O& D: d4 v+ V1 p0 |
  242.                                 {, U4 D+ T: z  B: f3 K, m
  243.                                         LCD_ShowChar(30+48,220,'-',16,0);                // 显示负号5 F, o2 p) v0 N! z+ M/ _
  244.                                         temp=-temp;                                                                // 转为正数
    9 [# j( s0 u6 q; i
  245.                                 }
    ; D# U; }+ C1 {0 ]& u2 @$ B& I
  246.                                 else + z5 U- s4 a; p: o' K
  247.                                         LCD_ShowChar(30+48,220,' ',16,0);                // 去掉负号 7 d1 C% s1 B5 Y$ A# }; z. k
  248.                                 LCD_ShowNum(30+48+8,220,temp/10,3,16);                // 显示整数部分            
    # _' V4 }3 m- p6 y( v( a
  249.                                 LCD_ShowNum(30+48+40,220,temp%10,1,16);                // 显示小数部分 0 T! r0 {2 P4 J
  250.                                 temp=roll*10;; D- u6 O1 H: C( ]" g4 S
  251.                                 if(temp<0)
    ' s' ?. K7 u4 X
  252.                                 {
    0 z3 f% E" u: m/ y
  253.                                         LCD_ShowChar(30+48,240,'-',16,0);                // 显示负号
    # p. X2 t4 N3 [5 H9 A9 j- b
  254.                                         temp=-temp;                                                                // 转为正数1 }: X" ~3 s% g/ r) p: y- o
  255.                                 }0 T, ~& m: G) y. ?1 e" {
  256.                                 else
    9 @3 z( k% v+ Z$ @; ~+ z! {
  257.                                         LCD_ShowChar(30+48,240,' ',16,0);                // 去掉负号
    7 ^/ c. U: X  A* D" E+ X7 A2 b
  258.                                 LCD_ShowNum(30+48+8,240,temp/10,3,16);                // 显示整数部分            3 R+ H" @. e+ W$ X. V! p3 ?
  259.                                 LCD_ShowNum(30+48+40,240,temp%10,1,16);                // 显示小数部分
    0 y/ h7 Y$ ?* A( J+ w: H
  260.                                 temp=yaw*10;
    - K. j) w" i% X: C
  261.                                 printf("temp=%d\r\n",temp);
    + X% B, y8 w6 l5 Q
  262.                                 if(temp<0)
    ) V1 j3 E# a, T9 K& y6 J" V; t8 B
  263.                                 {
    & F- H2 Q/ A. b  D  o( Z$ [# T0 ^
  264.                                         LCD_ShowChar(30+48,260,'-',16,0);                // 显示负号: @0 E. E2 V" H; a* J
  265.                                         temp=-temp;                                                                // 转为正数; x# Y/ J  e$ ^, N" b
  266.                                 }3 _# A# \1 }( x4 S" x- s* Z
  267.                                 else $ l8 v& f/ ]  W4 ?" N; M
  268.                                         LCD_ShowChar(30+48,260,' ',16,0);                // 去掉负号 & [) R2 j; ~: y+ I5 t$ x' I, A
  269.                                 LCD_ShowNum(30+48+8,260,temp/10,3,16);                // 显示整数部分            
    - }7 ]* \8 w7 g* m5 @8 _& K
  270.                                 LCD_ShowNum(30+48+40,260,temp%10,1,16);                // 显示小数部分  4 T& z9 Y. o6 m5 u
  271.                                 t=0;8 p2 N: U( ?! `: [0 g
  272.                                 DS0=!DS0;                                                                        // LED闪烁
    4 j: z# ?1 U1 L; q+ Z
  273.                         }) [/ ^" m- l' `- n( R- ^
  274.                 }
      H" U. {; a) G! U- A, k1 c" D
  275.                 t++; 9 }. `/ ~  V. D! c* o: u3 P1 u
  276.         }         , S' @+ \  R$ e" ?# Z  d7 S0 g
  277. }
    8 M3 D. g; A; o/ d4 ]  ?/ z
  278. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码

% S) r0 c: _+ A! m0 }1 E& M10.6 移植文件
% i! j! `# p  v文件中代码太多,这里主要关注:
  F# m/ @+ [% W! ~5 e8 U; }1)inv_mpu.c源文件中定义了四个函数:+ O  I# @& s. D8 I& o& `
/ m# t, F- C/ z3 S, J+ N
  1. #define i2c_write   MPU_Write_Len  // 对应mpu6050.c源文件里的MPU_Write_Len
    ( M0 S$ _2 D+ ?. o, z4 z" f
  2. #define i2c_read    MPU_Read_Len   // 对应mpu6050.c源文件里的MPU_Read_Len! x/ |9 F) p: u  O/ t6 M
  3. #define delay_ms    delay_ms       // 对应delay.c源文件里的delay_ms
    & P2 O; T* s' D2 a% Z
  4. #define get_ms      mget_ms        // 这是一个空函数
复制代码
6 \7 _4 q9 T7 S9 }  Q# f
2)inv_mpu.c源文件中u8 mpu_dmp_init()初始化函数:
+ o" v; B8 J4 G! q: f& d
* _0 j# `! g' P3 \2 `2 X. x
  1. u8 mpu_dmp_init(void)
    3 m  x$ X' u9 C0 P3 _0 b- M( {2 a: Q
  2. {
    * S) H- B2 L2 k, v+ m- y. N
  3. u8 res=0;
    ! {$ f- T0 Z2 U8 R, t. Q
  4. MPU_IIC_Init();   // 初始化IIC总线; u. l) L& n. q. C. ]
  5. if(mpu_init()==0) // 初始化MPU6050
    6 d) |" f5 y  [
  6. {  
    , p0 X5 b4 ?9 w7 Y
  7.   res=mpu_set_sensors(INV_XYZ_GYRO|INV_XYZ_ACCEL);     // 设置所需要的传感器
      |/ }1 X' V- P: f: ]! y% r0 [
  8.   if(res)return 1; 2 H  {4 q, ~3 R6 x* n
  9.   res=mpu_configure_fifo(INV_XYZ_GYRO|INV_XYZ_ACCEL);  // 设置FIFO
    2 v2 G7 }2 e  v: ~' I* G
  10.   if(res)return 2; ! t4 d4 ^8 ^: I3 b; |
  11.   res=mpu_set_sample_rate(DEFAULT_MPU_HZ);             // 设置采样率% u) t9 q. U% x! l* s
  12.   if(res)return 3;
      e- Y* d- N5 x8 q
  13.   res=dmp_load_motion_driver_firmware();               // 加载dmp固件
    9 M. o* k  ~# I% ?! z* n8 v
  14.   if(res)return 4; . G" n0 x' Y7 f8 y% B
  15.   res=dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation)); // 设置陀螺仪方向3 Z. |( D4 ^: b1 }( u2 ]
  16.   if(res)return 5;
    5 t7 X( d8 a* I- L9 J6 t
  17.   res=dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT|DMP_FEATURE_TAP|               // 设置dmp功能% ?8 s8 B4 d4 v8 k8 Q. @$ I9 S
  18.       DMP_FEATURE_ANDROID_ORIENT|DMP_FEATURE_SEND_RAW_ACCEL|DMP_FEATURE_SEND_CAL_GYRO|
    ; _' s) q& m! c9 G
  19.       DMP_FEATURE_GYRO_CAL);# x$ g* F9 }0 l7 L- B* X
  20.   if(res)return 6; 0 t* O# j' \, X5 W# t" c* `2 q
  21.   res=dmp_set_fifo_rate(DEFAULT_MPU_HZ);  // 设置DMP输出速率(最大不超过200Hz)
    0 D8 l( r' m4 u% z, O; I: I. o
  22.   if(res)return 7;   
    8 K6 Y) F4 Q% g* Y9 s" h$ J6 {
  23.   res=run_self_test();                    // 自检0 A+ j. I7 I2 I2 K2 e9 y
  24.   if(res)return 8;    6 G; J/ K- [: h' {& c
  25.   res=mpu_set_dmp_state(1);               // 使能DMP
    ' \4 z- u# w. D& G  U& Z5 ^# Q; y
  26.   if(res)return 9;     
    " N7 v3 g- Q& @/ V( \
  27. }else return 10;
    ' X& e8 g5 A. C
  28. return 0;
    + }6 _2 ?' y! ]* y( u/ x9 O  d0 W- c
  29. }
复制代码

$ z# C" }9 h" r$ G* i3)inv_mpu.c源文件中u8 mpu_dmp_get_data(float *pitch,float *roll,float *yaw)获取欧拉角的函数:6 l4 Q' k, x6 s4 t- b7 x$ E3 e
. G; u  w8 b! p; _# \
  1. u8 mpu_dmp_get_data(float *pitch,float *roll,float *yaw)
    : U6 y' K" W, L9 N: }
  2. {0 r, ~$ g- v( N" z1 O
  3. float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;# o! Y  X% W+ ~
  4. unsigned long sensor_timestamp;0 _7 b8 X( r+ n) w" h
  5. short gyro[3], accel[3], sensors;; L5 _2 P! _- ~0 c* l
  6. unsigned char more;
    & X# `" o" ?8 D$ j+ U, W6 L
  7. long quat[4]; % A( i" f* M2 W$ i- c4 g
  8. if(dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more))  z9 [1 O7 a) J4 ~8 d4 J
  9.    return 1;  
    * F" w+ ~. W) ]/ q" g. x0 ~
  10. ors&INV_WXYZ_QUAT) 6 ]  d5 A( V9 }% T$ B
  11. {
    - s* F6 ^" e9 K% c( W! \
  12.   q0 = quat[0] / q30;    // q30格式转换为浮点数
    , Y5 {+ Z: L2 m6 f; q
  13.   q1 = quat[1] / q30;
      r8 e4 J- L" G: [! G3 `+ y  N3 X
  14.   q2 = quat[2] / q30;
    ; R- W( k3 p0 o  B( R9 W. Q
  15.   q3 = quat[3] / q30;
    7 }. z' Q3 v# f+ g8 q3 l/ B- i8 r
  16.   // 计算得到俯仰角/横滚角/航向角
    4 _" f  T/ q& m4 y$ J# t1 ^% Z
  17.   *pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch2 n' W, H+ J9 c1 A# R
  18.   *roll  = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
    3 q" C7 d2 b4 M* H' r( X
  19.   *yaw   = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3; //yaw
    ! K( X# F! Z1 m8 j: ?
  20. }
    % t* o  D$ g, o& @
  21. else
      G9 D9 h# U8 t7 j
  22.    return 2;' X1 Q4 Z( K5 l
  23. return 0;7 p. w7 c1 Y) h, ^% m) W* g
  24. }
复制代码
% F0 c1 Q) _; B6 J: t/ E
十一、实验结果

- e. D1 E! C, ^. b7 j" q& j该程序可用匿名四轴上位机软件实时查看6轴的原始数据和姿态数据,即欧拉角:航向角(yaw)、横滚角(roll)和俯仰角(pitch)。(这里就不放截图了)。
; |+ E8 v  p- w% l4 @另外在LCD屏上,也可实时查看6轴的原始数据和姿态数据,如下图:. c- l; _1 }) ?$ ?$ }
20201204235655599.png
7 [6 O1 f* u. ~8 ^( h
1 P  F' U. n7 w% Q2 d- ^# \9 j% {————————————————* D, K2 n7 Q2 m* G1 ]9 ~# T
版权声明:天亮继续睡
4 \; \3 ^& h# j. V& k# v. T0 z1 ~; {9 I8 }( T( h) o

; b% o0 W3 `0 f. V4 n; R, V( D) l7 R5 t) s# B
收藏 评论0 发布时间:2022-11-18 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版