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

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

[复制链接]
STMCU小助手 发布时间:2022-11-18 19:00
主要内容:
& i5 M5 K- U7 K: J" ^1)MPU6050简介;$ ^6 D- j/ S9 u/ M) I$ M1 c- c4 Q
2)MPU6050相关寄存器介绍;: a( [" E" c/ s. `& ^2 ?$ _
3)相关实验代码解读(除了案例可实现的功能外,主函数增加了在LCD屏上显示6轴的原始数据(含正负号)的功能)。& G0 A9 G4 O9 o* F

* X2 p- k6 G3 o) k2 A: f" _一、什么是MPU6050?5 X% O9 c; z, s' p: ?
MPU6050是InvenSense公司推出的全球首款整合性6轴运动处理组件,内带3轴陀螺仪和3轴加速度传感器,并且含有一个第二IIC接口,可用于连接外部磁力传感器,利用自带数字运动处理器(DMP: Digital Motion Processor)硬件加速引擎,通过主IIC接口,可以向应用端输出完整的9轴姿态融合演算数据。, }$ a+ [& |' K/ B# e: c$ Y; Y+ h

3 x6 N) h$ T3 T9 l  c% _% v1 M1 t二、MPU6050特点8 J/ Q! v6 k% m4 Z
1)自带数字运动处理(DMP: Digital Motion Processing),输出6轴或9轴(需外接磁传感器)姿态解算数据;
( s8 O1 {8 e! k8 _# }9 J2)集成可程序控制,测量范围为±250、±500、±1000与±2000°/sec 的3轴角速度感测器(陀螺仪);
, p0 ]; n4 n" h3)集成可程序控制,范围为±2g、±4g、±8g和±16g的3轴加速度传感器;
) V- K0 g& h/ u3 W) ^; q. N, F4)自带数字温度传感器;
0 n+ i2 x5 R) N% q; n% _$ @5)可输出中断(interrupt),支持姿势识别、摇摄、画面放大缩小、滚动、快速下降中断、high-G中断、零动作感应、触击感应、摇动感应功能;
6 P3 \+ ?. J! m1 ^8 x% `" l6)自带1024字节FIFO,有助于降低系统功耗;  [) H# A9 ~5 o3 F( K6 ]. g- o% E  A
7)高达400Khz的IIC通信接口;
# B7 I# K3 L8 k6 h8)超小封装尺寸:4x4x0.9mm(QFN)。
% p% W! {* o1 O- D: a+ p  e% W6 N1 L
- O/ y& W# D3 G( h9 p- f三、MPU6050框图* A9 H% T6 u/ a* `/ ^
20201202115316729.png
5 g) u, F. i3 Y6 h% {AD0=0对应器件物理地址=0X68" D, u# I8 P$ o
AD0=1对应器件物理地址=0X696 b9 |% S) K/ F: ~8 T/ l" r

9 T. ]2 V; h- e$ p四、MPU6050初始化. S0 n$ X- ?% w6 H6 b
1)初始化IIC接口;
6 i7 s% j# b7 m! m0 i; g! m7 I2)复位MPU6050,由电源管理寄存器1(0X6B)控制;1 G. S  t% z; z
3)设置角速度和加速度传感器的满量程范围,由陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置 ;9 i1 R% B' \, I: \9 Z# l7 `) `  U
4)设置其他参数:
# o# d+ \: V& b/ S" N设置中断,由中断使能寄存器(0X38)控制;/ }( ^% s5 @6 u9 b; A0 w
设置AUX IIC接口,由户控制寄存器(0X6A)控制;
1 q7 ]: G/ b* ]+ W* |设置FIFO,由FIFO使能寄存器(0X23)控制;
& ?' z/ c4 t& x) n设置陀螺仪采样率 ,由采样率分频寄存器(0X19)控制;' I; r! ~* A5 o1 k( i) i% {8 n2 u1 V. t5 U
设置数字低通滤波器,由配置寄存器(0X1A)控制;
: E1 N  J: Y9 r8 ~& ]% j2 g5)设置系统时钟。由电源管理寄存器1(0X6B)控制。一般选择x轴陀螺PLL作为时钟源,以获得更高精度的时钟;* f: y; j) ^& V+ g* t. x4 l7 ]
6)使能角速度传感器(陀螺仪)和加速度传感器。由电源管理寄存器2(0X6C)控制。
) ^6 h+ U4 @, T/ A! X初始化完成后,即可读取陀螺仪、加速度传感器和温度传感器的数据了!!' f; s! w$ ~8 G% \3 u$ G) x: c

5 Y' v2 _! N4 i8 Y五、主要的寄存器介绍2 _' h/ l* v  o7 u9 V
5.1)电源管理寄存器1(0X6B)- F9 Z  e$ i) s- @% z! X
" h! g' B" x1 C) k" L  l( a
20201202124650455.png ; Y* x- O) ^& r
: W9 w4 m7 m5 @6 W
DEVICE_RESE=1,复位MPU6050,复位完成后,自动清零;
# g6 B; M3 @( \; B3 L' ?/ kSLEEP=1,进入睡眠模式;SLEEP=0,正常工作模式;! R6 G' u6 E+ G  j# }9 u' ]1 C
TEMP_DIS,用于设置是否使能温度传感器,设置为0,则使能;
; B  ]9 S& E4 W% CCLKSEL[2:0],用于选择系统时钟源,如下表所示:- ]8 L/ j( `0 L8 x2 C2 Q1 ^
  B" j6 h2 q  {9 ^( m: O- n3 A4 v% \
20201202124734929.png
6 k! ~# v, J7 v! _
, l' K2 f$ s% O" N; S5.2)陀螺仪配置寄存器(0X1B)
5 X$ C$ A) G" F2 N8 `( `0 w) G
6 ~$ r, t7 d+ s0 H2 o0 F. N  h5 h 20201202124826207.png
2 n* R6 n% c, k) G+ M$ c& E
% T5 ~( e' E- E. }( Q& O主要关注FS_SEL[1:0]这两个位,用于设置陀螺仪的满量程范围:# }4 X2 ]* S3 V$ ~
0,±250°/S;1,±500°/S;2,±1000°/S;3,±2000°/S;
2 m# k7 H" w& v+ u一般设置为3,即±2000°/S,因为陀螺仪的ADC为16位分辨率,所以灵敏度为:65536/4000=16.4LSB/(°/S)。" U0 q: \8 W) n. I5 c
  @. a0 p: d: g2 P
5.3)加速度传感器配置寄存器(0X1C)
# r- r' P" s0 U+ d
# r& d  H+ h6 B1 C 20201202124906190.png 4 C  G! Q9 L* i4 d" b' m6 E

# @7 E$ B' B2 S8 ?/ L, b主要关注AFS_SEL[1:0]这两个位,用于设置加速度传感器的满量程范围:
& Z/ c( _! D! b. G- F$ U0,±2g;1,±4g;2,±8g;3,±16g;
7 H3 m0 o5 V! c! H) M一般设置为0,即±2g,因为加速度传感器的ADC是16位,所以灵敏度为:65536/4=16384LSB/g。+ V$ C) N; u5 u/ X1 Y

; ^+ F) |% M4 R5.4)FIFO使能寄存器(0X23)
% I% ^0 h$ ~8 P5 |* `1 p! G4 h! y1 y/ H$ ~7 C
20201202124951209.png
% ~& x0 ~/ n, u& H+ K/ v; s/ x& }: s6 n4 g" }0 P7 {2 s( s
该寄存器用于控制FIFO使能,在简单读取传感器数据的时候,可以不用FIFO,设置对应位为:0,即可禁止FIFO,设置为1,则使能FIFO。8 z1 e( [" s5 M( H8 `
注意:加速度传感器的3个轴,全由1个位(ACCEL_FIFO_EN)控制,只要该位置1,则加速度传感器的三个通道都开启FIFO了。
, @1 u" \  l3 k' \0 `
: A" u1 j4 d5 O( |8 b# g0 O5.5)陀螺仪采样率分频寄存器(0X19)7 o' N, n. _4 L) ]$ R- a% V8 _
& l. F. ~& v+ J
2020120212502194.png ) `( `4 N. f, C

9 h* O& l4 S8 E0 a) O6 k$ f6 H1 g3 D2 e该寄存器用于设置MPU6050的陀螺仪采样频率,计算公式为:
( V7 C: I  N* B7 x5 \采样频率 = 陀螺仪输出频率 / (1+SMPLRT_DIV)
9 a% I' g0 p0 ^# K这里陀螺仪的输出频率,是1Khz或者8Khz,与数字低通滤波器(DLPF)的设置有关,当DLPF_CFG=0或7的时候,频率为8Khz,其他情况是1Khz。而且DLPF滤波频率一般设置为采样率的一半。采样率,我们假定设置为50Hz,那么:SMPLRT_DIV=1000/50-1=19。. i1 U3 Z; ~0 s- _" S: T
' i; `4 Y8 O- ]
5.6)配置寄存器(0X1A)
; Y+ t$ D1 p  A* x% G: ]5 J1 O
6 Y2 I. ^5 _" N  G' Y 20201202125111514.png 0 F2 |5 t) Y2 b( @' Y
- n" n0 I2 Z6 i/ o4 o
重点看数字低通滤波器(DLPF)的设置位:DLPF_CFG[2:0],加速度计和陀螺仪,都是根据这三个位的配置进行过滤的,如下表所示:1 d6 p0 I% t8 I

' O; f+ C+ }8 w. r5 V 20201202125128497.png
3 \; x3 g7 ^; I' D& h1 G. w+ I7 l- ?) Z' b' M2 U
备注:带宽=1/2采样率9 i% X& T& A0 \2 O! j# `
; k# T+ l7 ?5 H8 K& ^$ R" x- \
5.7)电源管理寄存器2(0X6C), ]) _! s2 W6 D! \- j

* F8 A$ n4 t) {+ u5 G  A 20201202125210534.png
, _7 r* {% T* [% a- p" K
  U7 v1 x9 `0 f; F: b# s% l# @该寄存器的LP_WAKE_CTRL用于控制低功耗时的唤醒频率;
8 [! e, h' z& T" l剩下的6位,分别控制加速度和陀螺仪的x/y/z轴是否进入待机模式;0 V; h7 g" A" l. K$ b& x4 b9 S) B: L
本例程全部设置为:0 ,即可。
1 W" c! Z; H2 c0 B, |. s5 t
, R# c& A/ l% U7 e2 u, H0 X* ^5.8)加速度传感器数据输出寄存器(0X3B~0X40); x1 ]; H$ U7 o$ r; k
" O  U6 l$ C4 [7 t3 h* w8 Y3 N/ S
20201202125232456.png
- M( O" Z* _; h) }! G$ |  r  H7 ?: S9 x/ f* {
总共由6个寄存器组成,输出X/Y/Z三个轴的加速度传感器值,高字节在前,低字节在后。- U8 ^3 ^# r6 f7 r3 j. M
( x7 O5 l" O. n' }2 F
5.9)陀螺仪数据输出寄存器(0X43~0X48)
& F0 A/ w8 v% e% l, z! A4 j* e9 i0 @3 i4 d2 ^
20201202125315716.png 9 D  v& X) M9 B
8 L" y/ t" {- x! m1 h4 W! @0 k* M
总共由6个寄存器组成,输出X/Y/Z三个轴的陀螺仪传感器数据,高字节在前,低字节在后。2 _% I# C( x7 C; N

, \8 A; X+ b5 A% j6 |! }# q3 t5.10)温度传感器数据输出寄存器(0X41~0X42)- C8 q% s. c/ L6 h' Q5 w
- M/ M- `6 o8 r! s6 U# q' p
20201202125336901.png
4 R# B  h/ ]8 R4 w& V' n: C( U
, d6 J; ?( p  ^0 i通过读取0X41(高8位)和0X42(低8位)寄存器得到,温度换算公式为:
0 P- ~' u, P( v' a$ h: ZTemperature = 36.53 +regval/340  X3 X+ W3 r; ^, o; X" Y
其中,Temperature为计算得到的温度值,单位为℃,regval为从0X41和0X42读到的温度传感器值。( V6 W; u' J& L0 X. o1 G9 s+ T

, c0 m/ G. a7 \& s& V$ t  P0 E六、DMP使用介绍
  s* b* y* o  X. @7 B实际使用时(比如做四轴),我们更希望得到姿态数据,即欧拉角:航向角(yaw)、横滚角(roll)和俯仰角(pitch)。
9 p; V$ S( U! C& T  i, F) r要利用原始数据,需要进行姿态融合解算。MPU6050自带数字运动处理器,即DMP,并且InvenSense提供了一个MPU6050的嵌入式运动驱动库,结合MPU6050的DMP,可以基于原始数据直接转换成四元数输出,而得到四元数之后,便可很方便的计算出欧拉角,从而得到yaw、roll和pitch。8 `9 {1 @  o" p9 X" P
备注:InvenSense提供的MPU6050运动驱动库是基于MSP430的,需要将其移植后才可以用到STM32上面。! M9 `! G/ o$ g) j8 U) i& m  }
4 h4 n) Q4 v) ?; d* ^, l9 b
移植细节:
* T7 @: t! t# E4 n4 L. U: Z官方DMP驱动库移植,主要是实现这4个函数:i2c_write、i2c_read、delay_ms和get_ms。
4 R6 t. A/ Z5 p; H8 E" N移植后的驱动代码如下图:- j; Y! o) K. ~

7 t4 s4 z! B# g 20201202125526501.png
; T: e6 e7 W8 A$ @$ j( {! S! ^9 h3 x3 l* x0 Y7 @; I) |
MPU6050 DMP输出的是姿态解算后的四元数,采用q30格式,即2的30次方,要得到欧拉角,需要做一个转换,代码如下:  Z  }  ^, w; Q4 z7 ]
; }! H% V6 l" A4 ?) L( t/ m
  1. q0=quat[0] / q30;   // q30格式转换为浮点数; |; ?0 [- l8 c0 n: z1 O
  2. q1=quat[1] / q30;   // q30格式转换为浮点数
    : @! k! y1 M, A: i' W; k$ K$ {5 j
  3. q2=quat[2] / q30;   // q30格式转换为浮点数) E. ~' g1 @0 }8 y; U
  4. q3=quat[3] / q30;   // q30格式转换为浮点数1 a( D4 ~6 ~2 t' N4 E; s
  5. // 计算得到俯仰角/横滚角/航向角. |$ |) \2 D% c
  6. pitch=asin(-2 * q1 * q3 +2 * q0* q2)* 57.3;      // 俯仰角, _0 |4 W  u: O' x6 Y
  7. roll=atan2(2 * q2 * q3 +2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // 横滚角yaw=atan2(2*(q1*q2 +2 D+ R$ O3 X" n4 E8 U8 s+ B) \+ [
  8. q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3;          // 航向角
复制代码

! \# b, C5 q+ }5 l上述代码中:quat[0]~quat[3]:是MPU6050的DMP解算后的四元数,q30格式; q30:是一个常量:1073741824,即2的30次方; 57.3:是弧度转换为角度,即180/π,这样结果就是以度(°)为单位的。/ u8 g7 B2 q5 o3 b! _

$ @2 P5 b4 l* b- A& z七、ATK-MPU6050模块% S, w! f1 Y- Q1 f) O* U4 h+ E
ATK-MPU6050模块主要由MPU-6050芯片和RT9193-33芯片组成,原理图如下图所示:
9 Z& U* l' e, Q& {* d& @5 G4 o& H5 J
20201202125803667.jpg
$ N$ N! l0 F7 W- I) s9 w8 s3 y+ O' m
开发板通过ATK-MODULE接口外接MPU6050模块,硬件连接原理图如下:
. {9 V3 Y0 n0 G& i. i( `( Z. \" f1 T2 m; l9 I4 i' E: p
20201202125834118.jpg 1 A) W& R. y" V

% O+ q' g: f: L  e  j$ u' [. N  C6 ?八、重点关注的相关代码
- w+ K  X- n6 d/ \' \% n" o8.1)MPU-6050驱动代码' C4 G4 D6 u( L* _  B
1,MPU6050 IIC接口驱动代码
3 K" x- h% C1 T, j* T0 J& b2,MPU_Init函数
$ ]; w2 R* ]" k  N2 Q- k6 s0 Z3,MPU_Get_Gyroscope函数5 Y/ a0 K$ F( g8 @6 j
4,MPU_Get_Accelerometer函数: a" v" j& N4 C3 I9 N# i5 Y7 m
5,MPU_Get_Temperature函数
1 _# x( D9 }  M0 T' _, P; i8.2)DMP驱动代码
) I1 d" r3 s# |, u, B1,DMP移植相关代码' ]0 s8 {' ]8 s7 R  L1 f" W. R
i2c_write、i2c_read、delay_ms和get_ms.
, M' A* D. S# q3 l, h+ F2, mpu_dmp_init函数) B+ F  v+ B( V2 o7 d
3, mpu_dmp_get_data函数
- L0 I* N. j; W& U, f
( g1 Q) U8 j) n8 g4 Z九、MPU6050读写时序3 E4 G  z8 j- p5 ?
9.1)单字节写入时序
/ H2 Q* g; X! m! D7 w) P; _, U1 e% d5 U2 j
20201202130030646.png $ j% X8 V# e$ w

7 W; T& ]6 `; x- [9.2)连续写入时序8 d' ]& d$ B6 s6 L( r& a. t

6 o: E9 G& S2 i) Z2 t2 a/ e 2020120213005560.png & x. i/ p4 V' p/ i

5 `5 l! E' O8 Y' U/ I! r+ l9.3)单字节读出时序9 d9 o4 A) O& |2 V- K8 _

& y4 z( l' m1 u# n( J1 E 20201202130110852.png
) y5 \  o( J3 r) U6 N/ T. d1 h, Y$ v" l: Y  d% c; X  X
9.4)连续读出时序. B5 t0 F$ m( S. b# u

- E8 y9 {7 j- a 20201202130123583.png
/ V- O1 v( e/ i& ^( ]' ]* W: L9 w- ^
十、部分实验代码解读% x& q2 g" j7 J
10.1 mpuiic.h头文件函数" v( A6 @0 f" r# J$ X/ A
1 e, b& z2 P/ a( H8 J0 T0 o
  1. /**
    7 h- l, t/ ]2 f# A
  2. ********************************  STM32F10x  *********************************' Y( V- j- X; G* ^0 a% B
  3. * @文件名称: mpuiic.h
    7 j: p: I( Z% J0 z
  4. * @修改作者: Aaron
    7 `" S$ E' W' x. l6 c
  5. * @库版本号: V3.5.0
    , l* P+ _/ L) f
  6. * @工程版本: V1.0.0
    9 A1 B" D, m6 M! n( z; A5 ^
  7. * @开发日期: 2020年11月30日* S! {3 J1 X9 K6 j- p$ B
  8. * @摘要简述: mpuiic头文件,主要跟MPU-6050模块进行IIC通讯时用2 Q$ z$ t+ ~, |
  9. ******************************************************************************/
    5 B1 o( T5 n# Q: q- p* t6 P  T
  10. /*-----------------------------------------------------------------------------
    , \* f9 w7 J  w9 ]
  11. * @更新日志:
    ) q. |6 @! E( Q; O
  12. * @无8 W0 v6 g+ K4 G* W6 c+ N
  13. * ---------------------------------------------------------------------------*/
    * V' F/ F. z3 E+ x3 o
  14. #ifndef __MPUIIC_H- @' Y: B% v  n% L) y
  15. #define __MPUIIC_H
    1 ~7 E  b) z* u- n3 C% W
  16. /* 包含的头文件 --------------------------------------------------------------*// p0 b7 w6 n' F8 V- |
  17. #include "sys.h"
    7 B# H; _4 O: p) d
  18. #include "stm32f10x.h"
    6 [$ v6 K! G; w- g# \" {
  19. /* 寄存器方法控制GPIO管脚输入输出模式 ----------------------------------------*/
    9 u% f# O5 D: w  c& q
  20. #define MPU_SDA_IN()  {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=8<<12;}   // PB11 上拉输入模式* N) j# z0 Y; V7 n1 k
  21. #define MPU_SDA_OUT() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=3<<12;}   // PB11 通用推挽输出模式,50MHz
    2 P# Z  X- Z9 V6 o/ s
  22. /* 位操作方法定义 ------------------------------------------------------------*/ ( K, h0 T" u; ^  ~
  23. #define MPU_IIC_SCL    PBout(10)   // PB10对应SCL
    " B5 q, x) D$ H  K+ \2 ?& {- W) s/ R
  24. #define MPU_IIC_SDA    PBout(11)   // PB11对应SDA,输出SDA  
    " f# D3 Z& o- |4 ~* Z/ B  S
  25. #define MPU_READ_SDA   PBin(11)    // PB11对应SDA,输入SDA
    ; M; ]2 m3 G1 ~
  26. /* 定义IIC底层驱动程序 -------------------------------------------------------*/! i" R' R. N2 b* G' Y/ p9 d
  27. void MPU_IIC_Delay(void);                         // MPU IIC延时函数,延时 2 us
    - m/ b6 c7 K. o# Q; d8 x1 z7 s2 T4 v
  28. void MPU_IIC_Init(void);                   // 初始化IIC的IO口
    . i6 s# t7 e$ g% G# S0 ~4 R: v
  29. void MPU_IIC_Start(void);                  // 发送IIC开始信号
    " R2 K. ?) }& M
  30. void MPU_IIC_Stop(void);                              // 发送IIC停止信号0 U+ y7 [* Y. ]- \, B& \" s8 w
  31. u8 MPU_IIC_Wait_Ack(void);                 // IIC等待ACK信号/ k* h/ Y- t8 M" [7 m3 X
  32. void MPU_IIC_Ack(void);                    // IIC发送ACK信号   - ^- K7 l5 L0 M- T3 i0 C( q: ^
  33. void MPU_IIC_NAck(void);                   // IIC不发送ACK信号
    ( U7 \# t* c& A" \( T! U* O
  34. void MPU_IIC_Send_Byte(u8 txd);            // IIC发送一个字节
    ; d! ?. u( b  @& J$ Y, n* i1 D$ \
  35. u8 MPU_IIC_Read_Byte(unsigned char ack);   // IIC读取一个字节
    / L0 ~  K- m8 G$ a# K( G$ M/ c
  36. #endif /* __MPUIIC_H *// [4 l+ q/ C+ T: c
  37. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码
5 O) I2 w0 Q4 F# Z' l! b3 s- `
10.2 mpuiic.c源文件函数5 v% N  m7 j2 @/ r- |% T# _) |

, x( Q  ^" g% [8 s. w3 W# W
  1. /*** P/ D3 X0 j$ r* |; d' S
  2. ********************************  STM32F10x  *********************************) `, s9 W" H8 G% A9 b1 {8 ?
  3. * @文件名称: mpuiic.c
    8 g  @! m1 S2 e8 l; v& H
  4. * @修改作者: Aaron
    5 ~  j0 s& T/ }
  5. * @库版本号: V3.5.0
    - {) r# p% l' Y8 [9 H+ m( X3 i
  6. * @工程版本: V1.0.09 Z$ ~0 a% Z) c, m+ `( u
  7. * @开发日期: 2020年11月30日
    ; k# ]/ }. Y5 R, ?" J( F! C
  8. * @摘要简述: mpuiic源文件,主要包含与MPU-6050进行IIC通讯的IIC底层驱动程序
    3 ]9 n$ w) E+ V( v1 C$ U
  9. ******************************************************************************/
    ' I- }& @4 C% t. G: y
  10. /*-----------------------------------------------------------------------------2 L: _& K' O  Q2 x: c
  11. * @更新日志:
    ( R& l& i0 H8 ?) E4 S, R% d! f4 _
  12. * @无& e) `/ O5 p7 B$ b& S
  13. * ---------------------------------------------------------------------------*/
    7 i! m5 h5 `0 D* Q3 @: s; y  D# n
  14. /* 包含的头文件 --------------------------------------------------------------*/4 N; W$ ^* \8 V" Y/ g: v/ s3 k
  15. #include "mpuiic.h"
    - M% ~& b+ Y1 J, C5 [8 Q/ M( c- z
  16. #include "delay.h"8 P; z* P& c# @2 T- H( |* W( ~
  17. /*********************************************************************2 a0 b: G7 M5 Y$ r- [
  18. 函数名称:MPU_IIC_Delay()
    0 J. \/ h- ~6 W( J' {
  19. 函数功能:延时函数,延时2微秒(us)
      I" j9 a+ s5 n' P/ L/ m
  20. 入口参数:无, A$ q3 k7 C: g
  21. 返回参数:无
    4 a" y* A1 v8 w4 b
  22. 修改开发:Aaron% |1 d: B7 H! _5 R+ V: L
  23. **********************************************************************/  [4 R  \) o* |
  24. void MPU_IIC_Delay(void)& j  g9 l) _5 [' l+ o
  25. {3 V( b' D( i8 n' L% V
  26. delay_us(2);% [0 K+ v* v4 e: c
  27. }
    ; M3 P) R3 J( E
  28. /*********************************************************************1 K9 M% @$ E. v
  29. 函数名称:MPU_IIC_Init()/ k! N. W$ l7 w! |" ?7 @2 y
  30. 函数功能:MPU_IIC管脚初始化配置
    ; i% Z2 ~% _: g. Q: ?( T. `
  31. 入口参数:无
    8 J6 A+ m( t4 a3 {
  32. 返回参数:无
    2 q2 o3 @4 W, Q% Y6 H  }. t% {
  33. 修改作者:Aaron3 a+ ]% B& \! N' `' T) d: k# W/ A
  34. **********************************************************************/
    ; y6 P. Q3 G: o7 B
  35. void MPU_IIC_Init(void)
    & z: f) Y, v# K+ I' M$ F# p
  36. {         
    7 x& @& r! T0 Y
  37.   GPIO_InitTypeDef  GPIO_InitStructure;: M7 G$ j5 Q- f2 X8 ]
  38.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);     // 使能外设IO PORTB时钟   
    7 ^7 A$ l' ^  Z/ P
  39.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;   // 端口配置,管脚10和管脚11
    9 \7 B) I4 Q- j+ F. a* K, X
  40.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         // 推挽输出
    4 k; H0 `6 V4 E) Z- \
  41.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        // IO口速度为50MHz
    0 B! i6 k1 M3 p# D  N
  42.   GPIO_Init(GPIOB, &GPIO_InitStructure);              C9 I0 X+ _. ?
  43.   GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);             // PB10(SCL),PB11(SDA) 输出高 % u7 t" I0 z  ?! d. Q) [
  44. }
    3 L$ {- }) ]6 Q( C* O- W- w
  45. /*********************************************************************( d: V& U  D! r- w
  46. 函数名称:MPU_IIC_Start()* M. t" X3 n/ u" [: q/ p
  47. 函数功能:MPU_IIC起始信号
    0 u  R& |) i! r5 I- l' V( M
  48. 入口参数:无
    ! r# Y5 S* k' J" j7 a: C
  49. 返回参数:无
    0 u( Q2 J% l6 y3 p5 R+ s& p$ U7 _2 w
  50. 修改作者:Aaron
    3 a) ?* ?/ w& D. Y- Z$ W# q9 L7 Q
  51. **********************************************************************/* t" x# y3 B! |3 |/ T  T# U
  52. void MPU_IIC_Start(void)
    2 K3 ]4 m9 C) X
  53. {
    6 w" \9 `/ s. q4 i5 F! t# o, E
  54. MPU_SDA_OUT();      // SDA线输出模式" f% K7 f' j  e! [" b9 ]  s& W
  55. MPU_IIC_SDA=1;      // SDA输出高 9 U2 ?5 m  B) g" p( K  @
  56. MPU_IIC_SCL=1;      // SCL输出高,此时为空闲状态
    0 v0 \, v3 h  ~
  57. MPU_IIC_Delay();    // 延迟 2 us, N' d5 W- H) L) a
  58. MPU_IIC_SDA=0;      // 在SCL输出高的状态下,SDA由高至低跳变,IIC开始* f) p1 h! M" ^( H; p* [- C1 c& N
  59. MPU_IIC_Delay();    // 延迟 2 us
    ; F* n$ G! v# ]' v
  60. MPU_IIC_SCL=0;      // 钳住I2C总线,准备发送或接收数据 : a' P+ M: |0 @/ s% t' Z! B% w
  61. }  1 B+ M( l4 m+ l/ |
  62. /*********************************************************************
    7 s0 q1 Y6 P4 T+ |' O0 _0 p9 `1 I& m. D
  63. 函数名称:MPU_IIC_Stop()$ ]6 F) R  W9 B8 C  S8 ]& q
  64. 函数功能:MPU_IIC停止信号  U5 ?9 y' Z  v% }% p4 K
  65. 入口参数:无1 s& D# ~( q9 o/ b4 F# _
  66. 返回参数:无- O3 t- ~, X6 F5 N
  67. 修改作者:Aaron1 Y" m. m* Y5 G2 J9 W2 T" D
  68. **********************************************************************/
    ' q# W+ ~( M7 ]0 `; A
  69. void MPU_IIC_Stop(void)
    + a; P4 A8 K5 [& z. m( s! L$ b
  70. {7 e4 \3 o+ p% g- v9 V6 n" R) r& |
  71. MPU_SDA_OUT();      // SDA线输出模式4 L% H5 d/ `+ w
  72. MPU_IIC_SCL=0;      // SCL输出低
    % }) k, H/ B2 n
  73. MPU_IIC_SDA=0;      // SDA输出低- G3 B* w" H  Q. b. f, {% Z& ^# h
  74. MPU_IIC_Delay();    // 延迟 2 us% N" C0 C7 F0 n0 A. X- c3 I
  75. MPU_IIC_SCL=1;      // 先SCL输出高,在SCL输出高的状态下,SDA一直是低电平
    5 j( a/ n; b8 P# Y; J( O! k& M
  76. MPU_IIC_SDA=1;      // SDA输出高,发送I2C总线结束信号
    + G" F4 ]; n+ I3 @2 k0 `
  77. MPU_IIC_Delay();    // 延迟 2 us        
    / \# S. b0 n$ }* l' b! {, ]
  78. }
    . P- {5 W7 ^8 v0 c( R+ R, K2 W
  79. /*********************************************************************2 k% m* L  |7 f7 J
  80. 函数名称:u8 MPU_IIC_Wait_Ack()9 j- {, F! N2 v  R3 \
  81. 函数功能:等待应答信号到来* j: u, n5 a7 S# f! e4 m* _
  82. 入口参数:无7 d, a3 B, {/ s9 o+ l: Z8 I1 ^
  83. 返回参数:u8,1,接收应答失败,0,接收应答成功$ I6 c- ~! ~9 p" S5 D6 J3 V" K* K# K  g
  84. 修改作者:Aaron
    . b: R3 `3 P# F, t, c
  85. **********************************************************************/. u+ s1 S: A2 f6 R
  86. u8 MPU_IIC_Wait_Ack(void)# H' [$ R9 }7 ?
  87. {
    7 A! R- l( ?8 y% u! R" M
  88. u8 ucErrTime=0;
    ) H! i0 x/ P3 x' H8 i
  89. MPU_SDA_IN();         // SDA设置为输入  
    . U2 S5 a& ?3 R# ^) \( a* z- i
  90. MPU_IIC_SDA=1;        // SDA设高电平# w( [5 C9 @, I! L4 k/ d, w, O
  91. MPU_IIC_Delay();      // 延迟 2 us * N+ K7 r5 b1 w% A+ [+ Y# h
  92. MPU_IIC_SCL=1;        // SCL设高电平& g, u* o4 V) S& \
  93. MPU_IIC_Delay();      // 延迟 2 us
    " \: Q/ L; C1 Y' K; m$ }, Q
  94. while(MPU_READ_SDA)   // 读取PB11的值,一直读PB11=1,高电平,则不断循环,直到溢出
    & y; p9 Y$ S0 ?  p, @
  95. {
    ) u9 d' t' V; _4 n8 P9 F) V
  96.   ucErrTime++;
    2 X3 u# u  K  v2 b* f
  97.   if(ucErrTime>250)) U# H/ N0 G2 K
  98.   {: l/ J) m4 k! s  e9 e( T- r. F' d, C
  99.    MPU_IIC_Stop();' r& ]* y6 L3 h
  100.    return 1;! b0 a! y8 A( _' X8 K
  101.   }/ @$ q/ N% j( H
  102. }
    7 J8 K, y( J0 I2 a+ @+ e/ F
  103. MPU_IIC_SCL=0;        // SCL设低电平     
    ' n( ~4 D$ H. ~7 B
  104. return 0;  
    4 A7 _# Z! @3 M7 Z+ e) n6 M
  105. }
    + @& Z5 p- H5 i# a: i- F; N0 ^& a7 n  F
  106. /*********************************************************************
    9 s1 l6 w! M9 G( P% g0 T
  107. 函数名称:MPU_IIC_Ack()8 K% S5 G" `, l' G' C) `# [
  108. 函数功能:产生ACK应答0 d' v- s& _& u) d  [. h
  109. 入口参数:无
    2 Z6 m  x2 O5 C% i
  110. 返回参数:无# W' F2 C) S! |
  111. 修改作者:Aaron) z, _7 d( L( J# i6 |- d
  112. **********************************************************************/
    # H+ ?7 p" T6 Q- Z
  113. void MPU_IIC_Ack(void)
    ' K1 |& n; |( ^- E6 c. E8 n
  114. {
    & Y1 [7 u* W% h6 ^6 W
  115. MPU_IIC_SCL=0;       // SCL设低电平! g1 ?, U+ V& n5 e) [* P4 p
  116. MPU_SDA_OUT();       // SDA输出模式& X3 A3 D5 ~/ S2 z
  117. MPU_IIC_SDA=0;       // SDA设低电平
    & _5 t+ O0 d, h3 j7 L  t7 _
  118. MPU_IIC_Delay();     // 延时 2 us
    & Y  k4 F& v: ?$ c, K
  119. MPU_IIC_SCL=1;       // SCL设高电平
    * y% b1 k8 o# N% A7 q: P9 [' c" m
  120. MPU_IIC_Delay();     // 延时 2 us9 O" m" x+ U; \, T2 }* E* \
  121. MPU_IIC_SCL=0;       // SCL设第电平,在SCL高电平期间,SDA为低电平,则说明有效应答
    7 z7 ^# E$ R* G
  122. }! M; N+ c7 m6 C' c9 [8 F( i
  123. /*********************************************************************
    / }8 z  U% f7 t  o! y+ u
  124. 函数名称:MPU_IIC_NAck()+ o$ G5 @( U9 m/ Y0 G
  125. 函数功能:不产生ACK应答
    ( }" w8 M1 p: V2 H2 E( F- H
  126. 入口参数:无" ]/ g1 m; R6 G
  127. 返回参数:无
    5 {3 ]  j& L9 z
  128. 修改作者:Aaron
    ; ~# l8 U5 |" p1 V( s4 `, z  O) S
  129. **********************************************************************/
    ) i0 s( @5 `( o2 w+ o- j. B
  130. void MPU_IIC_NAck(void)
      K3 A; D# E: |' \) l
  131. {. _8 F. h! H. O
  132. MPU_IIC_SCL=0;       // SCL设低电平
    6 @' w" Z, W% A) a1 T+ D  u
  133. MPU_SDA_OUT();       // SDA输出模式( x) U8 O' q3 T
  134. MPU_IIC_SDA=1;       // SDA设高电平: V$ h) K( U+ c+ Q# [
  135. MPU_IIC_Delay();     // 延时 2 us5 B: P& v: L4 c7 a8 x, S8 _) d
  136. MPU_IIC_SCL=1;       // SCL设高电平
    6 D. c+ y, b; E
  137. MPU_IIC_Delay();     // 延时 2 us/ v# k, d. o) p: k
  138. MPU_IIC_SCL=0;       // SCL设低电平,在SCL高电平期间,SDA为高电平,则说明无效应答
    4 U- |  N' N0 f- m
  139. }
    6 Q: }7 ^) \6 d1 Q7 V! G
  140. /*********************************************************************
    $ K8 m% R3 I/ \! C& c* i6 ^
  141. 函数名称:MPU_IIC_Send_Byte(u8 txd)
    ! r  Z0 u( r' m% i' K
  142. 函数功能:IIC发送一个字节; V1 z5 F4 k$ _& B- [8 w1 s  v* \
  143. 入口参数:u8 txd" p0 i! l6 ?  k. e% u/ Q( q
  144. 返回参数:无
    - B( h( E. R  C8 M; q" `
  145. 修改作者:Aaron
    * ~- w% M  B# M/ X
  146. **********************************************************************/
    8 S$ z- h! t. E; c! c
  147. void MPU_IIC_Send_Byte(u8 txd)4 d) N/ M0 O7 ]; E" p& s! |
  148. {                        ) Z+ L$ T  Q9 Y1 m2 ?" |" A
  149. u8 t;   
    4 O2 q+ I% B5 s) F: c1 F# c
  150. MPU_SDA_OUT();       // SDA输出模式
    9 _3 f( B' v5 L+ R% a  b
  151. MPU_IIC_SCL=0;       // SCL设低电平,此时可改变SDA,以实现数据的有效传输) e: E9 _+ B& |* }9 z8 x/ @
  152. for(t=0;t<8;t++)     // 发送一个字节,即8个bit
    7 C' `2 z% e% N9 M" [
  153. {              
    - D. {& p+ c# a
  154.   MPU_IIC_SDA=(txd&0x80)>>7;  // 获取u8 txd的最高位(0或1),并右移7位,将最高位值给MPU_IIC_SDA
    * M' E4 }) Z! M  W
  155.   txd<<=1;    : Q; G- I( f; l1 \* o
  156.   MPU_IIC_SCL=1;              // SCL设高电平/ s3 ]/ |6 \4 M4 I. E% w
  157.   MPU_IIC_Delay();            // 延时 2 us# _2 M# D' P+ E. b
  158.   MPU_IIC_SCL=0;              // SCL设低电平,传输SDA完成( [8 F  ]  z* e5 h* P
  159.   MPU_IIC_Delay();            // 延时 2us
    & v9 G7 x& e2 R4 z9 h. V
  160. }  
    6 Z8 h4 M( f* n$ k8 y
  161. }
    ; o. L+ {5 s2 d- |
  162. /*********************************************************************" w! K; Q( H9 c  }5 A# z
  163. 函数名称:u8 MPU_IIC_Read_Byte(unsigned char ack)
    % p) a- G! O: [! u! ^
  164. 函数功能:IIC读取一个字节,ack=1时,发送ACK,ack=0,发送nACK 8 ?9 t$ S' m" }& \) d
  165. 入口参数:ack! l& n' {' W" C0 h5 O9 l0 W
  166. 返回参数:u8,
    5 F! V5 X+ l& z) }
  167. 修改作者:Aaron5 i# e( j7 O; r5 {0 y7 T* Q+ `% ~
  168. **********************************************************************/  W) t2 {) v" U
  169. u8 MPU_IIC_Read_Byte(unsigned char ack), e4 s# h% w6 {: v
  170. {" E2 w: O; L" _) V" l3 f( Z
  171. unsigned char i,receive=0;
    6 ?9 Q+ f2 ?5 [
  172. MPU_SDA_IN();                 // SDA设置为输入模式
    0 ?8 ~* N; h+ o3 t7 y) |4 o5 r
  173. for(i=0;i<8;i++ )             // 读取一个字节,即8个bit
    & L, x8 \7 D% h4 F' v
  174. {
    3 A! G0 {1 M9 w6 y
  175.   MPU_IIC_SCL=0;               // SCL设为低电平& V" Z; t. G5 \5 F* L
  176.   MPU_IIC_Delay();             // 延时 2us
    + b0 \) M( M# l8 }% G5 `2 z
  177.   MPU_IIC_SCL=1;               // SCL设为高电平
    3 W$ ?1 i, i1 A+ @" ^2 ?# A7 l
  178.   receive<<=1;
    0 u2 t. z/ B) @0 h  H3 K
  179.   if(MPU_READ_SDA)             // 如果读取的SDA为1,则receive最低值+1,若读取的SDA为0,则receive最低值不变,即0
    ' F7 d. Z# G. C/ |4 Z+ Z* a- q) Y
  180.    receive++;     L# S. H  v) Z+ V
  181.   MPU_IIC_Delay();             // 延时 2us
    6 ^  J' r2 P, a2 w! k
  182. }      % R) d. E8 H( D- H- U; a; D
  183. if (!ack)
    ) ^& z5 V9 i" Y$ b# p
  184.   MPU_IIC_NAck();              // 发送nACK9 m. _4 J0 O0 x; i4 X8 f2 n6 ]) i" F
  185. else
    , j' A& v4 a2 P4 ?8 u& q( `4 [$ `
  186.   MPU_IIC_Ack();               // 发送ACK   % D7 m- ?) j: n8 b3 n" s1 v7 P
  187. return receive;
    % @+ d" h$ f- g, o' {3 h
  188. }
      {* H' I8 q; R7 E1 x. u- S( |* @
  189. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码
) ^2 ~5 U3 [0 P5 w
10.3 mp6050.h头文件函数
  D' b1 g" P0 u" ?+ E代码中标记“初学”的说明是前面寄存器介绍时讲到的。
# l+ w% f( ~/ d" L
- N4 n% @- T$ b$ Z
  1. /**
    2 y# u' E) H. A. Q
  2. ********************************  STM32F10x  *********************************1 M7 v- H- ]( V2 ~9 d! @/ U: e
  3. * @文件名称: mpu6050.h
    9 r! M, s8 H7 R1 I; _
  4. * @修改作者: Aaron' ?5 x6 @9 D, l* M" T- {' [
  5. * @库版本号: V3.5.0
    7 p% ]$ z$ [/ t9 F0 w, i$ v- e( s
  6. * @工程版本: V1.0.0
    1 u1 t, {, t( \& {
  7. * @开发日期: 2020年11月30日1 i3 F$ W" t# Y) C# ]
  8. * @摘要简述: mpu6050头文件7 C0 z* O6 W. d' r- H* w7 W
  9. ******************************************************************************/8 V, C, c- h0 R- ^
  10. /*------------------------------------------------------------------------------ O2 ]! v" h1 l
  11. * @更新日志:2 C/ Z9 N, g7 _0 j# P
  12. * @无. P9 d/ y& C, j  g3 o, S
  13. * ---------------------------------------------------------------------------*/
    0 @& [7 N, @% E9 m
  14. #ifndef __MPU6050_H, D9 ^( M( A6 w: N9 O0 e$ d0 V
  15. #define __MPU6050_H
    6 D! S3 @% Y& }6 D( }
  16. /* 包含的头文件 --------------------------------------------------------------*/4 }8 l* d) k# A: v6 `" ?$ q9 M6 E
  17. #include "mpuiic.h"   
    % d6 j: @; V! \- ~, a
  18. /* 位操作控制PA15,对应MPU6050 AD0的高低电平 ----------------------------------*/3 G; z  w9 ?" h$ c- k" U+ E1 ]
  19. #define MPU_AD0_CTRL   PAout(15) // 控制AD0电平,从而控制MPU-6050地址& V& s0 R. Y. E1 K
  20. /* MPU6050 寄存器ID定义 ------------------------------------------------------*/
    ) j) n9 A( t) O  b* D3 f6 L
  21. // #define MPU_ACCEL_OFFS_REG 0X06 // accel_offs寄存器,可读取版本号,寄存器手册未提到
    : D" O$ _5 y3 j
  22. // #define MPU_PROD_ID_REG    0X0C // prod id寄存器,在寄存器手册未提到; u% Z; N5 G+ _+ u
  23. #define MPU_SELF_TESTX_REG    0X0D // 自检寄存器X ACC和G1 V; Q! e$ F! }6 ~, I. B3 j
  24. #define MPU_SELF_TESTY_REG    0X0E // 自检寄存器Y ACC和G2 U$ {  h, L, B0 A5 P3 @- J
  25. #define MPU_SELF_TESTZ_REG    0X0F // 自检寄存器Z ACC和G
    6 B' G3 M$ F. K; |* ?$ T1 f7 T' q
  26. #define MPU_SELF_TESTA_REG    0X10 // 自检寄存器X,Y,Z only ACC" ], A. j$ V- U! |$ z' F& _2 T
  27. #define MPU_SAMPLE_RATE_REG   0X19 // 陀螺仪采样频率分频器    **初学**
    8 h+ q# h8 t6 _4 j. C3 F
  28. #define MPU_CFG_REG           0X1A // 配置寄存器              **初学**
      H* u2 r% i0 o) \
  29. #define MPU_GYRO_CFG_REG      0X1B // 陀螺仪配置寄存器        **初学**
    % G0 I  |. K0 @# H/ J: V# S
  30. #define MPU_ACCEL_CFG_REG     0X1C // 加速度计配置寄存器      **初学**# Z8 B) U6 _5 S: `1 |/ g
  31. #define MPU_MOTION_DET_REG    0X1F // 运动检测阀值设置寄存器& v: w; P4 `+ X/ H( P' K
  32. #define MPU_FIFO_EN_REG       0X23 // FIFO使能寄存器          **初学**
    1 K5 G! ^$ [4 E& b7 _
  33. #define MPU_I2CMST_CTRL_REG   0X24 // IIC主机控制寄存器
    , p# l2 U' C6 u2 Y
  34. #define MPU_I2CSLV0_ADDR_REG  0X25 // IIC从机0器件地址寄存器
      s0 A% H! A5 L  z
  35. #define MPU_I2CSLV0_REG       0X26 // IIC从机0数据地址寄存器
    $ \. U' u* p' y
  36. #define MPU_I2CSLV0_CTRL_REG  0X27 // IIC从机0控制寄存器* z/ c' g* R0 R; @) Q
  37. #define MPU_I2CSLV1_ADDR_REG  0X28 // IIC从机1器件地址寄存器; `& ^2 \) K3 h& t; K
  38. #define MPU_I2CSLV1_REG       0X29 // IIC从机1数据地址寄存器  ?8 _5 o3 ^1 l! w' b
  39. #define MPU_I2CSLV1_CTRL_REG  0X2A // IIC从机1控制寄存器. c: C$ R) t6 t$ y6 a# Z
  40. #define MPU_I2CSLV2_ADDR_REG  0X2B // IIC从机2器件地址寄存器4 R6 c/ i7 b, p. d8 E1 b
  41. #define MPU_I2CSLV2_REG       0X2C // IIC从机2数据地址寄存器
    ) O# w( x8 [5 C$ a" Y6 Y/ e
  42. #define MPU_I2CSLV2_CTRL_REG  0X2D // IIC从机2控制寄存器7 r: `/ h& x, ~- J, G: f. W: H* l8 z3 B
  43. #define MPU_I2CSLV3_ADDR_REG  0X2E // IIC从机3器件地址寄存器$ n) V- T( z9 a0 _( h" G. m& c
  44. #define MPU_I2CSLV3_REG       0X2F // IIC从机3数据地址寄存器. ^: g' m4 w  c. G/ W/ e
  45. #define MPU_I2CSLV3_CTRL_REG  0X30 // IIC从机3控制寄存器5 a/ k/ \+ F5 [5 l
  46. #define MPU_I2CSLV4_ADDR_REG  0X31 // IIC从机4器件地址寄存器
    * r$ r9 r# a+ H5 c
  47. #define MPU_I2CSLV4_REG       0X32 // IIC从机4数据地址寄存器
    9 T5 k; k8 A3 _9 N: a- {' [: B
  48. #define MPU_I2CSLV4_DO_REG    0X33 // IIC从机4写数据寄存器
    " D5 _3 S7 N9 u# H# L* u7 K% H5 q& v
  49. #define MPU_I2CSLV4_CTRL_REG  0X34 // IIC从机4控制寄存器. P! _" h6 H. t  S) ]. L
  50. #define MPU_I2CSLV4_DI_REG    0X35 // IIC从机4读数据寄存器
    " n% H; C+ l8 d4 w  f4 a
  51. #define MPU_I2CMST_STA_REG    0X36 // IIC主机状态寄存器& T3 f# T6 B) @8 h8 d
  52. #define MPU_INTBP_CFG_REG     0X37 // 中断/旁路设置寄存器
    % n4 N- w% O) A7 t7 d4 L
  53. #define MPU_INT_EN_REG        0X38 // 中断使能寄存器- O+ @) t9 e  V/ h7 a
  54. #define MPU_INT_STA_REG       0X3A // 中断状态寄存器/ ~6 H; r( @, b' A3 L
  55. #define MPU_ACCEL_XOUTH_REG   0X3B // 加速度值,X轴高8位寄存器  **初学**
    8 F# o/ Q+ j! L( e
  56. #define MPU_ACCEL_XOUTL_REG   0X3C // 加速度值,X轴低8位寄存器  **初学**$ `2 Q% g  ^! \1 b
  57. #define MPU_ACCEL_YOUTH_REG   0X3D // 加速度值,Y轴高8位寄存器  **初学**3 Z. m0 f" z5 ]" }4 W, |
  58. #define MPU_ACCEL_YOUTL_REG   0X3E // 加速度值,Y轴低8位寄存器  **初学**6 L7 b- D* g5 r' l3 m+ p9 d
  59. #define MPU_ACCEL_ZOUTH_REG   0X3F // 加速度值,Z轴高8位寄存器  **初学**
    5 s. H' @' [! w9 ^* {/ e" J1 u
  60. #define MPU_ACCEL_ZOUTL_REG   0X40 // 加速度值,Z轴低8位寄存器  **初学**
    8 D8 k, e) V8 c& }, z' P
  61. #define MPU_TEMP_OUTH_REG     0X41 // 温度值高八位寄存器    **初学**
    ' \$ f( ^! Q3 \: o" A
  62. #define MPU_TEMP_OUTL_REG     0X42 // 温度值低八位寄存器    **初学**
    0 P' [' e; u7 ^; c
  63. #define MPU_GYRO_XOUTH_REG    0X43 // 陀螺仪值,X轴高8位寄存器 **初学**
    0 i. Z: H+ F& Z5 A$ u" c
  64. #define MPU_GYRO_XOUTL_REG    0X44 // 陀螺仪值,X轴低8位寄存器 **初学**
    : m& F- S7 S0 W! S6 d$ x, Y7 \
  65. #define MPU_GYRO_YOUTH_REG    0X45 // 陀螺仪值,Y轴高8位寄存器 **初学**
      u3 f8 a- ^( U& J: D1 Z
  66. #define MPU_GYRO_YOUTL_REG    0X46 // 陀螺仪值,Y轴低8位寄存器 **初学**
    7 X( ^, J7 H/ i/ p' W4 _% |
  67. #define MPU_GYRO_ZOUTH_REG    0X47 // 陀螺仪值,Z轴高8位寄存器 **初学**
    3 F+ G& R& ^5 ?5 C
  68. #define MPU_GYRO_ZOUTL_REG    0X48 // 陀螺仪值,Z轴低8位寄存器 **初学**
    $ z9 h/ G) E$ r1 p2 J
  69. #define MPU_I2CSLV0_DO_REG    0X63 // IIC从机0数据寄存器
    * z, [1 Q! [/ v  n3 A$ V0 @
  70. #define MPU_I2CSLV1_DO_REG    0X64 // IIC从机1数据寄存器9 W1 U. @' T2 ~7 x* X
  71. #define MPU_I2CSLV2_DO_REG    0X65 // IIC从机2数据寄存器
    3 C$ s% n5 h; o; t$ H# V
  72. #define MPU_I2CSLV3_DO_REG    0X66 // IIC从机3数据寄存器4 L6 s- k" X: {* e
  73. #define MPU_I2CMST_DELAY_REG  0X67 // IIC主机延时管理寄存器- ?: _! \4 C! V7 C( r$ I) ]
  74. #define MPU_SIGPATH_RST_REG   0X68 // 信号通道复位寄存器8 Z, |2 }+ k4 Z, i/ {5 e9 ~% I
  75. #define MPU_MDETECT_CTRL_REG  0X69 // 运动检测控制寄存器, ^. |) Q! [$ }$ `, D8 Y
  76. #define MPU_USER_CTRL_REG     0X6A // 用户控制寄存器0 k) z/ f' G4 q1 ]5 k* w
  77. #define MPU_PWR_MGMT1_REG     0X6B // 电源管理寄存器1      **初学**: k# ]  L* t5 K4 Y, H  O& W+ Q& w' Y0 Y
  78. #define MPU_PWR_MGMT2_REG     0X6C // 电源管理寄存器2      **初学**- V% M. ^- m5 ?, Q% D+ W' s" Z
  79. #define MPU_FIFO_CNTH_REG     0X72 // FIFO计数寄存器高八位/ K1 @# L) j9 B/ f
  80. #define MPU_FIFO_CNTL_REG     0X73 // FIFO计数寄存器低八位
    - H  P9 ]4 Y  x. \1 m& t
  81. #define MPU_FIFO_RW_REG       0X74 // FIFO读写寄存器: C1 Y1 O7 L% A% x
  82. #define MPU_DEVICE_ID_REG     0X75 // 器件ID寄存器
    % R  y9 n8 |% H2 G! _
  83. // 备注:如果AD0脚(9脚)接地,0,IIC地址为0X68(不包含最低位);+ ^1 h+ I9 h0 v
  84. // 如果接V3.3,则IIC地址为0X69(不包含最低位),9 @# F' m% [& D; `; |$ D; ^3 f
  85. // 本开发板由PA15管脚控制,另PA15为低电平
    8 v: j3 h9 b- A& ?) ^3 |5 k+ q3 t: E
  86. #define MPU_ADDR       0X68
    3 j5 J2 G3 H: G- v; x- Z
  87. /* 函数申明 -----------------------------------------------------*/# P) l. d8 V6 y: c
  88. u8 MPU_Init(void);                                 // 初始化MPU6050
    ' z) t: M9 ^8 U" n1 z& t
  89. u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf);   // IIC连续写/ f! t/ C+ t# Q4 k( ^
  90. u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf);    // IIC连续读
    1 s% U8 k6 f( t$ H( {' |
  91. u8 MPU_Write_Byte(u8 reg,u8 data);                 // IIC写一个字节
    " W' B1 Y0 g9 x2 p4 O9 I
  92. u8 MPU_Read_Byte(u8 reg);                          // IIC读一个字节) d' m3 u5 ?9 C, r. v
  93. u8 MPU_Set_Gyro_Fsr(u8 fsr);; R% g( @" {. A* U
  94. u8 MPU_Set_Accel_Fsr(u8 fsr);% A8 ], @5 g0 U
  95. u8 MPU_Set_LPF(u16 lpf);
    : v' ~, n/ M: x& x$ {
  96. u8 MPU_Set_Rate(u16 rate);( f$ r8 k8 ?" v- e" c, G$ z
  97. u8 MPU_Set_Fifo(u8 sens);( K! S+ B( [* \& ?0 r
  98. short MPU_Get_Temperature(void);  l& X( l' s" L
  99. u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz);
    ) A" |9 s6 @+ v" F  \2 s
  100. u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az);6 {5 Z" b9 Q/ u  d. H. a
  101. #endif /* __MPU6050_H */4 v) E% o+ J! S1 z) E! R& H* g
  102. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码

1 V; d) V( s7 t* M10.4 mpu6050.c源文件函数
) B3 ]: s( R( f# X& R# @% G( s9 F. H& }  q5 {8 h
  1. /**5 b% }: a. m8 t/ Q
  2. ********************************  STM32F10x  *********************************% d2 x1 d7 W6 L+ t3 |+ M) n1 I& ^
  3. * @文件名称: mpu6050.c
    ) B0 K8 y6 I/ d' }. U& o8 J2 G
  4. * @修改作者: Aaron
    4 ]3 }2 h$ g! h5 \+ N# x
  5. * @库版本号: V3.5.0
    ' S6 r* l7 ?0 j/ v' }
  6. * @工程版本: V1.0.0( L  p/ g" F& d: i  ]- p# f
  7. * @开发日期: 2020年11月30日
    3 R8 b; O0 ^/ `/ v" D6 F
  8. * @摘要简述: mpu6050源文件
    0 d' `' r0 Z8 x/ H
  9. ******************************************************************************/* _  l# y/ c/ [, Q
  10. /*-----------------------------------------------------------------------------
    : u8 D1 N. W" s8 _% q% |( {: f
  11. * @更新日志:" N  R3 I4 F: \- b! N/ Y  x/ f
  12. * @无
    # Y  ~+ Q9 o8 W& h. K0 ?$ E% v
  13. * ---------------------------------------------------------------------------*/
    ' K4 l) \/ x& _& [' _3 n
  14. /* 包含的头文件 --------------------------------------------------------------*/; W* F( ~7 b/ R- p2 k9 o
  15. #include "mpu6050.h"
    6 R, f2 i+ |# ^" O2 B. h
  16. #include "delay.h"
    : |( l* C. K- Q. S
  17. /*********************************************************************% e/ T% r& y! ]. `$ m7 e2 }7 Q5 \
  18. 函数名称:u8 MPU_Init()
    : u: ~4 E  s: {  Y: u0 V7 }
  19. 函数功能:初始化MPU6050) x1 K# x9 H( j- J, `
  20. 入口参数:无
    1 v3 X# u) Q1 s7 m3 X3 P
  21. 返回参数:0,成功,1失败& c1 \3 p( [7 w  Y; S
  22. 修改作者:Aaron
    6 ~! S9 ^' p% o- a; k) z' Y5 y
  23. **********************************************************************/
    ! Y" B( C( o6 s6 t9 R' i- p& d6 J1 o7 o& n
  24. u8 MPU_Init(void)
    7 R* ^- k7 f' n
  25. {
    " k& j; K( f! |0 J  {
  26. u8 res;& O7 d' y- h* X  c7 J1 e5 _! ~6 l
  27. GPIO_InitTypeDef  GPIO_InitStructure;
    - m# P# H4 u% h
  28. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);      // 使能AFIO时钟
    ( N2 M, a; A- V5 ?! c. g' J) [
  29. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);     // 使能外设IO PORTA时钟  
    8 c- D" ~$ }3 Z+ x1 V' i
  30. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;               // 管脚15
    4 j" Z: _4 b; T  W3 j
  31. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         // 推挽输出
    / h4 t, o5 B7 L
  32. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        // IO口速度为50MHz) P4 Z' M9 }2 Q* O3 p: w
  33. GPIO_Init(GPIOA, &GPIO_InitStructure);                   // 根据设定参数初始化PA15,对应MPU-6050芯片的AD0地址管脚1 ~2 L/ P/ t. C5 d1 i! F
  34. GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);  // 禁止JTAG,从而PA15可以做普通IO使用,否则PA15不能做普通IO!!!+ P6 P1 a8 f% P
  35. MPU_AD0_CTRL=0;                                          // 控制MPU6050的AD0脚为低电平,则从机地址为:0X68
    " D- f* ]: b' a: r
  36. MPU_IIC_Init();                                          // 初始化IIC总线
    7 k, N7 E' s: a2 ~
  37. MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);                  // 对电源管理寄存器1输入0x80,复位MPU6050
    7 _, @2 P% L; X7 b6 y: r
  38. delay_ms(100);
    ! N0 x! o( f; M& w! W; z% T
  39. MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);                  // 对电源管理寄存器1输入0x00,主要令[6]位设0,正常工作模式,即唤醒MPU6050
    8 S+ E" i' N( q6 C
  40. MPU_Set_Gyro_Fsr(3);                                     // 设置陀螺仪传感器满量程范围,±2000dps
    . `3 l% c% _" f9 g9 H: H7 l5 d
  41. MPU_Set_Accel_Fsr(0);                                    // 设置加速度传感器满量程范围,±2g
    $ L- j" ^9 f$ W, t& m
  42. MPU_Set_Rate(50);                                        // 设置采样率50Hz) Z# a3 R# s6 w+ f9 ~* P% N6 X
  43. MPU_Write_Byte(MPU_INT_EN_REG,0X00);                     // 对中断使能寄存器输入0x00,关闭所有中断
    ! ^7 t, f4 i# y6 P( g7 @+ I
  44. MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);                  // 对用户控制寄存器输入0x00,I2C主模式关闭
    ( V! I9 u$ I- Y7 ~, T1 [( {
  45. MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);                    // 对FIFO使能寄存器输入0x00,关闭FIFO5 Q( p& o3 D1 O, Q1 R2 }5 f
  46. MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80);                  // 中断/旁路设置寄存器输入0x80,INT引脚低电平有效
    ; \3 g4 s- k$ l' G+ T/ G# W3 ]# k: H
  47. res=MPU_Read_Byte(MPU_DEVICE_ID_REG);                    // 读取器件ID寄存器值,传至res里
    # `! W8 w! U' Z2 _! i7 t
  48. if(res==MPU_ADDR)                                        // 如果res=0x68,则器件ID正确$ p5 w( w1 J, {8 I( _5 }
  49. {
    ) R: a3 E( C4 j8 ]$ z( o, C0 Z  h3 M( G
  50.   MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);                 // 对电源管理寄存器1输入0x01,设置CLKSEL,001,PLL X轴为参考9 Q9 s! G/ t6 P
  51.   MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);                 // 对电源管理寄存器2输入0x00,加速度与陀螺仪都工作(都不待机)
    $ P: X1 _0 b) A/ d4 E
  52.   MPU_Set_Rate(50);                                       // 设置采样率为50Hz
    * C8 f* D8 a9 n5 z
  53.   }$ e% [/ x" Z3 X) O0 a
  54. else
    , B& g1 q& u# N
  55.   return 1;1 c* ]; c- g/ _/ h' j
  56. return 0;
    6 a) z' w" J) p& U+ C+ ~
  57. }, r6 q+ N. S. P0 E- D
  58. /*********************************************************************
    % i3 G4 i. C6 E0 L9 k
  59. 函数名称:u8 MPU_Set_Gyro_Fsr(u8 fsr)
    $ F2 L) N  f  y8 i$ f9 [1 u* D
  60. 函数功能:设置MPU6050陀螺仪传感器满量程范围+ ]5 S0 O% ?, [! e4 x. B6 X
  61. 入口参数:u8 fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
    9 @' v* _- O" ^- P% \0 U2 x
  62. 返回参数:0,成功,1失败
    7 G# j2 t2 B6 h( S) ]
  63. 修改作者:Aaron
    + S5 P, I; J( b3 _6 T3 F/ C) ~
  64. **********************************************************************/6 k  b( ~* U, k
  65. u8 MPU_Set_Gyro_Fsr(u8 fsr)
    8 y3 f9 a4 |" X: O3 x( k( K
  66. {
    5 I& o% q# r4 H
  67. return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);  // 设置陀螺仪满量程范围为±2000dps  ) M+ A4 W- X5 g  `
  68. }
    4 ~5 N6 f" ^5 N; v
  69. /*********************************************************************
    # U1 T- O0 A# i9 @
  70. 函数名称:u8 MPU_Set_Accel_Fsr(u8 fsr)
    : m( ^" Q( i! s# |& F" L
  71. 函数功能:设置MPU6050加速度传感器满量程范围0 }- ?7 P, J! c- i: K# V" v0 i- V. q# w3 j  o
  72. 入口参数:fsr:0,±2g;1,±4g;2,±8g;3,±16g
    8 n& d9 W/ r% u
  73. 返回参数:0,成功,1失败
    & c6 c2 c5 q5 j1 ~  @( R
  74. 修改作者:Aaron+ H& B# H4 ]4 t5 N' a' X1 o! c& D5 w
  75. **********************************************************************/1 Y* X/ l' u/ P! G$ t
  76. u8 MPU_Set_Accel_Fsr(u8 fsr), d' T8 T( d" r: Y9 {1 m; c+ r! M
  77. {' S$ y5 D6 J9 M% x# `2 v+ i8 X
  78. return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3); // 设置加速度传感器满量程范围为±2g  1 a% u# A4 s. V$ D+ R
  79. }
    8 c2 {5 k* r3 t# y# Z
  80. /*********************************************************************, W' Y  B  S& ^7 r: \$ i
  81. 函数名称:u8 MPU_Set_LPF(u16 lpf)( W, K; }) J% O7 T9 e0 r  z
  82. 函数功能:设置MPU6050的数字低通滤波器
    8 Y& j( Y$ _1 A3 C1 o) R( |
  83. 入口参数:lpf:数字低通滤波频率(Hz)9 G# @8 x- a) s5 i9 T( g% ~/ s! b
  84. 返回参数:0,成功,1失败
    $ I$ M( t1 U1 ?& W
  85. 修改作者:Aaron
    * j$ O. S6 o& D1 P7 r
  86. **********************************************************************/( Y0 W3 G8 X8 l  y5 Q$ i% J
  87. u8 MPU_Set_LPF(u16 lpf)
    . r* w, Q5 ]7 K; S( N9 M4 l
  88. {
    / U" z% P! [2 W1 h
  89. u8 data=0;
    : ^, Z& w0 G5 T, R% [
  90. if(lpf>=188)                                // 如果lpf≥188Hz,则data=1. t# B2 A, X1 j, O! z
  91.   data=1;, u  [6 o- u# [8 G. W  B
  92. else if(lpf>=98)) r. L% U4 _% i6 r4 j
  93.   data=2;
    0 `4 J! {- x/ R; K8 ?0 O. e9 z
  94. else if(lpf>=42)2 @0 t% @- @7 J" y- o, Y
  95.   data=3;4 d# n5 ?- C9 ~# ^, d, z
  96. else if(lpf>=20)6 N$ L. J, h; m3 ?! R3 E
  97.   data=4;
    & m! u( R& r/ L
  98. else if(lpf>=10)
    # q  K- N" f1 I; n9 U
  99.   data=5;8 A$ S1 }1 T1 I
  100. else
    $ w) Q! X+ w) \1 O% [' C- o, r
  101.   data=6; + F( ^  @" |) W0 [& E# Q
  102. return MPU_Write_Byte(MPU_CFG_REG,data);    // 设置数字低通滤波器  , V5 k7 A4 w7 F/ A7 j: @8 z
  103. }0 V5 _, E( s8 \) u

  104. 8 O" ~$ C5 F( l9 y
  105. /*********************************************************************
    ) g1 }& P8 r; R4 e
  106. 函数名称:u8 MPU_Set_Rate(u16 rate)
    " f/ ?5 ^' Q& Y/ D6 [- i8 ^$ l
  107. 函数功能:设置MPU6050的陀螺仪采样率(只在陀螺仪输出频率Fs=1KHz时成立)+ ?7 G* ~9 `* K
  108. 入口参数:rate:4~1000(Hz),陀螺仪采样频率
    , Z$ y, P" @. F5 z; ?$ z
  109. 返回参数:0,成功,1失败5 D" ~6 T" x" |9 n4 E/ I- N
  110. 修改作者:Aaron
    2 D$ F& `% `0 E: W, a
  111. **********************************************************************/9 `1 i0 b5 a3 q6 g6 R
  112. u8 MPU_Set_Rate(u16 rate)/ `, y7 w- z) @  T# W9 c% ]( ]8 {
  113. {
    & J7 o9 A  E. B4 s. G
  114. u8 data;0 C* J  A/ a* Z" o' j
  115. if(rate>1000)
    * `  c# y$ R# ]1 L( C2 f% j8 i
  116.   rate=1000;
    2 F' L" c( X* U# {
  117. if(rate<4); E2 S7 n  T- B9 c
  118.   rate=4;
    1 W! ?3 |' k2 t8 Q0 W( A
  119. data=1000/rate-1;. ^! [7 l$ p+ ^9 B# z+ ?
  120. data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data); 9 O' \/ x8 Y& u1 S6 x* v1 x; W
  121.   return MPU_Set_LPF(rate/2);                // 自动设置LPF为采样率的一半' v7 t* A! O7 w3 l+ N. |
  122. }
    ) A+ |+ C4 z/ r8 h/ A
  123. /*********************************************************************; Y8 A" k4 X2 s2 M! d
  124. 函数名称:short MPU_Get_Temperature()
    ! ~% [6 C' O, v4 H
  125. 函数功能:得到温度值, e  y: d2 S4 l7 ]3 A+ i3 w
  126. 入口参数:rate:4~1000(Hz),陀螺仪采样频率4 g3 J! q; ]/ h* L4 ~
  127. 返回参数:温度值(扩大了100倍)# [# ^2 @. b( @/ K, e6 J6 N
  128. 修改作者:Aaron) a: }* Z  S  c. q
  129. **********************************************************************/3 c  e$ }+ ]2 R: v& v
  130. short MPU_Get_Temperature(void)" g/ J+ p  U, H( b7 k% |
  131. {
    % ?! O2 k7 d1 L: q
  132. u8 buf[2]; 3 S4 t% v! K/ n/ P9 @+ ]7 s, ]
  133. short raw;
    $ t  N% _7 N8 Z2 t* D* o
  134. float temp;
    6 ?' g& V, H9 m7 G4 Q0 O  j  F, M) R
  135. MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); // addr:器件地址;reg:寄存器地址;len:写入长度;buf:数据区
    8 w. c* g, A/ b' u. d( h
  136. raw=((u16)buf[0]<<8)|buf[1];  
    ( _9 o9 A6 E! w# I! S) G
  137. temp=36.53+((double)raw)/340;  
    * D# k* Y( V+ D
  138. return
    8 R/ m, M! d9 `6 d
  139.   temp*100;;+ b& u' w# H5 j( r, z, L8 ~
  140. }
    " w  A8 x4 Y7 D9 F1 z
  141. /*********************************************************************3 s/ r# `* x- q! h1 D6 H
  142. 函数名称:u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
    0 J# o& n# L$ u+ X  f) I* I
  143. 函数功能:得到陀螺仪值(原始值)
    , B) _; D. q  Q* X+ B; F3 o4 J2 D
  144. 入口参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
    : y0 ?0 M" F- W6 u$ ^0 e$ g
  145. 返回参数:u8 0成功,1失败2 @* [; |9 D' A& ]! M
  146. 修改作者:Aaron# J3 ]( ?+ B2 L- X7 ]7 I  q
  147. **********************************************************************/" d6 c; M* h0 G7 L0 w
  148. u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz): i) s1 K. {0 \  J+ k
  149. {
    " g% v: T$ l3 q" C* |4 C( i- p& F
  150. u8 buf[6],res;  
    - C: t2 J7 O# h: [6 T% ^
  151. res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
    6 g4 y$ ^; W; E. P
  152. if(res==0)
    6 d' ]4 b: y8 o. T
  153. {( n/ Z( |. e( P  J: r
  154.   *gx=((u16)buf[0]<<8)|buf[1];  
    7 i0 y7 R$ B* Z2 X5 T
  155.   *gy=((u16)buf[2]<<8)|buf[3];  1 C) T8 D0 v4 X7 |$ o) j6 y
  156.   *gz=((u16)buf[4]<<8)|buf[5];! R5 G1 U9 s! b8 ^( M% V4 ~4 O
  157. }  ) l/ \. E# _9 C9 I! f. n
  158. return res;;
    ( U; D. p% v, g* d( {' b, [
  159. }
    : N8 N- s1 O+ j1 W, l
  160. /********************************************************************** w* o& _9 f3 T7 ~# T7 C; [
  161. 函数名称:u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
    4 R6 ^1 r. p' |. b
  162. 函数功能:得到加速度值(原始值)8 Z7 M9 E" o: i& O  D) J1 e" o
  163. 入口参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号), a9 u9 U3 F: y' I  C" {
  164. 返回参数:u8 0成功,1失败* E- s* V# `) j) |
  165. 修改作者:Aaron
    % |$ v8 I) a1 p" E1 `3 [  t6 T
  166. **********************************************************************// `2 \3 U* q" |( _
  167. u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
    1 K+ G( l8 R+ u' C
  168. {
    2 \5 i2 a) [3 t6 a* D* w- _( [
  169. u8 buf[6],res;  
    % t1 G- e2 S6 p% y2 S# N
  170. res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);
    % O) s. z& {  D7 n: Q5 j# V  q
  171. if(res==0)
    & z9 w' M  Y- S3 E
  172. {
    + w3 W: M5 s# z) o9 W" `9 `. _% B  J
  173.   *ax=((u16)buf[0]<<8)|buf[1];  
    , [( `3 K2 M: Q5 D) n+ ~6 \6 k
  174.   *ay=((u16)buf[2]<<8)|buf[3];  / q2 w: v2 k  ]. B7 s& a4 e4 G
  175.   *az=((u16)buf[4]<<8)|buf[5];
    / L+ y3 `. [) V4 D' |4 h) [& c, P
  176. }  
    6 `3 C0 f. c$ i, _5 F
  177. return res;;
    8 D, U, m5 H( I: b
  178. }
    3 [5 X% v) X3 i/ S
  179. /*********************************************************************
    " A; [8 s4 u5 p+ e; W
  180. 函数名称:u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
    4 j$ K  G8 h' c( {4 k
  181. 函数功能:向MPU6050连续写入数据# \2 c9 o- d- g3 s4 g) ?
  182. 入口参数:addr:器件地址;reg:寄存器地址;len:写入长度;buf:数据区
    . Y. [4 {" h) Q  K! n( U* a' D
  183. 返回参数:u8 0成功,1失败
    ! A# V. _. G4 ^
  184. 修改作者:Aaron* \4 N2 d  N6 v/ p: E  ^+ X
  185. **********************************************************************/
    1 J, w7 K+ j) }# Y/ S, ~
  186. u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
    % F! L# E' @5 K& i) j. U
  187. {
    6 {3 S, }/ Y5 ?9 J: s0 S, q) Y
  188. u8 i;
    + Y2 u( g* o$ J$ V1 O, d, O% H
  189. MPU_IIC_Start(); ; E- p/ d4 J0 {4 U, D
  190. MPU_IIC_Send_Byte((addr<<1)|0);   // 发送器件地址+写命令 . j9 B/ h# ?+ U' ^0 Y8 E/ S! `2 S
  191. if(MPU_IIC_Wait_Ack())               // 等待应答
    . X* z7 }7 _% R4 }0 s, s
  192. {! ~/ k7 X4 e5 U6 O4 `1 q1 q
  193.   MPU_IIC_Stop();   9 A$ {0 k/ ~: o" I
  194.   return 1;  
      u3 n/ t* J, O+ m6 P8 t. F& [6 o
  195. }& f% h5 c) ]& f' _1 B+ Y& M
  196. MPU_IIC_Send_Byte(reg);              // 写寄存器地址9 w5 B# E! K# R; o9 Z. g  h2 o
  197. MPU_IIC_Wait_Ack();              // 等待应答
    - {( p/ q: a' M4 G
  198. for(i=0;i<len;i++)4 S$ S3 }, j" ^* S+ W  _5 _
  199. {
    , ]6 m( J* ~# l: M/ A4 f* N) I
  200.   MPU_IIC_Send_Byte(buf);      // 发送数据& s5 B; ?( E  X; [
  201.   if(MPU_IIC_Wait_Ack())          // 等待应答
    ( D1 A% r0 x4 d) A8 S% E
  202.   {
    8 L) R* F; i. @: E& \  x' |; j
  203.    MPU_IIC_Stop();  
    ' S6 {# J4 y* t$ q- W1 ^: s
  204.    return 1;   
    . [% f2 X) E+ ~+ P  W! z
  205.   }  " r' X- A/ t  V4 L6 I% W
  206. }   
    & C9 {3 q3 l7 O4 i
  207. MPU_IIC_Stop();  ) t& ^) h+ P3 d! r9 L- A; m8 _
  208. return 0; 7 ?: z, z( Y8 y$ {# K  n
  209. }
    ! o! j; b6 f: f- x7 o
  210. /*********************************************************************
    . ]/ ?; z- f* K% d
  211. 函数名称:u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
    1 H- T  q* C0 K- L$ ~3 M+ V
  212. 函数功能:从MPU6050连续读数据
    : B9 g; m. ~! H0 T
  213. 入口参数:addr:器件地址;reg:要读取的寄存器地址;len:要读取的长度;buf:读取到的数据存储区/ G2 g$ k: ~+ p3 W; \0 t) ]/ Z# J
  214. 返回参数:u8 0正常,1错误+ p- t  Q7 b0 J/ `8 r6 P5 a
  215. 修改作者:Aaron! v$ D$ h1 T$ @- y9 m9 o
  216. **********************************************************************/
    & f3 b5 M* O8 L
  217. u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)- R) X  x! P2 ~/ b
  218. { & e9 P1 K# I, b3 O# r1 }
  219. MPU_IIC_Start();
    3 b0 s2 \4 s' n* k4 @" v# N
  220. MPU_IIC_Send_Byte((addr<<1)|0);    // 发送器件地址+写命令 ! _; D( v9 Y. n4 }
  221. if(MPU_IIC_Wait_Ack())             // 等待应答# W6 c% N6 ]$ ?- p! t* r' W) T
  222. {
    8 R) G, ^* h" Y
  223.   MPU_IIC_Stop();   
    ! L1 z! R1 P+ U( ]5 y9 p6 y
  224.   return 1;  2 `' }; ^, L2 G" y+ ?+ ?
  225. }
    & L  |2 s9 T- e2 ~, T
  226. MPU_IIC_Send_Byte(reg);            // 写寄存器地址
    ) Z8 T2 o" x" R0 Y* Z
  227. MPU_IIC_Wait_Ack();                // 等待应答5 n* S* ?; E# U, E
  228. MPU_IIC_Start();
    " r, c  _; t/ ]8 F7 n) c% Q: w
  229. MPU_IIC_Send_Byte((addr<<1)|1);    // 发送器件地址+读命令 ' c# z  p& y' p5 f+ `
  230. MPU_IIC_Wait_Ack();                // 等待应答
    $ B# a  j: r3 ^( P; l, g9 ?
  231. while(len)
    1 r+ ?) z- s- r! Z9 d7 z
  232. {3 e3 Q; E* U' @5 s1 ^; a8 o) n% T
  233.   if(len==1)*buf=MPU_IIC_Read_Byte(0); // 读数据,发送nACK
    & l9 S/ z, c' ~+ R! X: I
  234.   else *buf=MPU_IIC_Read_Byte(1);      // 读数据,发送ACK  , q6 X4 Z' D* y
  235.   len--;6 g: g/ t  X. ~) y  w, p
  236.   buf++;
    * @8 _# u8 K- v! P& X! |
  237. }   
    8 E# X# q4 l+ S+ j
  238.     MPU_IIC_Stop();  // 产生一个停止条件 3 O7 V) W; ^: O/ p
  239. return 0;
    ( L2 v) W7 T: X, Y9 M- R( F- N
  240. }+ z! J: p. k; V' W1 C6 [8 Y! r
  241. /*********************************************************************
    & Q( n% v$ t6 ]
  242. 函数名称:u8 MPU_Write_Byte(u8 reg,u8 data)
    ' r6 c& d: f: b# }8 t
  243. 函数功能:向MPU6050写一个字节
      V5 ?: C+ ]) k" m
  244. 入口参数:reg:寄存器地址;data:数据- B0 _9 S$ o) t/ G$ a5 X& i
  245. 返回参数:0,正常;1,失败
    . L; |  }# f) p: G3 ^
  246. 修改作者:Aaron( C5 L$ E" ^; }- F4 P( p, B6 h5 n
  247. **********************************************************************/
    + j  [. \: h4 K" e' S" N7 n
  248. u8 MPU_Write_Byte(u8 reg,u8 data)      3 _6 ~  O' q$ ]; I6 b
  249. {
    5 `' }! B% j3 b/ J! t
  250. MPU_IIC_Start(); $ M' E% u8 U6 C. j* e% A3 o
  251. MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);  // 发送器件地址+写命令 $ V, h( ], ?: X0 p- {7 C, Q$ U1 L
  252. if(MPU_IIC_Wait_Ack())                     // 等待应答,0接收应答成功,1接收应答失败
    5 G3 n" f1 p5 H3 t% @  Q
  253. {- [4 I' P. H) S
  254.   MPU_IIC_Stop();                             // MPU_IIC停止信号, y) l% V# Q( F3 A! O
  255.   return 1;  
    5 m* `+ f7 c7 W  i' B! M9 X
  256. }5 f1 W/ M2 g3 F, B
  257. MPU_IIC_Send_Byte(reg);              // 写寄存器地址
    - N% o, K0 d6 C2 y* u/ ~. z. z) n
  258. MPU_IIC_Wait_Ack();                  // 等待应答
    4 H: x, s$ z5 V3 `4 B  V
  259. MPU_IIC_Send_Byte(data);             // 发送数据
    7 X/ L: Y! v8 [: F3 v) w  r; ?
  260. if(MPU_IIC_Wait_Ack())               // 等待应答
    4 b4 i: x0 D! V! T# d3 H4 U
  261. {  U- x# [$ Z1 G; S8 p- u
  262.   MPU_IIC_Stop();  
    ) [* b+ z' o- a3 W
  263.   return 1;   
    , m/ Q8 D( y' i% S# m
  264. }   
    / [  u' X" C" n4 X& t. t4 q
  265.     MPU_IIC_Stop();  ' l; y) B  Y* u$ e! p+ |. f
  266. return 0;
    ; q3 n; f5 w7 R
  267. }+ |6 V, p: c/ v# u6 H
  268. /*********************************************************************
    3 \4 o- ~$ E: x7 P* Z6 K" J
  269. 函数名称:u8 MPU_Read_Byte(u8 reg)
    ' F3 o8 P+ f# {" m) r
  270. 函数功能:从MPU6050读一个字节 ! ^' n  T. }0 B; m' s, ~
  271. 入口参数:reg:寄存器地址/ P1 m% M, r& n$ d# ~
  272. 返回参数:u8 读到的数据
    # @2 w* |3 c* c, M
  273. 修改作者:Aaron
      x7 x) G+ ?+ E: |/ f' a
  274. **********************************************************************/  n9 q: s: x, ^, W
  275. u8 MPU_Read_Byte(u8 reg)' S) Q* u; k) k# R$ j) L9 z, M& z0 c
  276. {4 q3 c4 @6 @. Y( @
  277. u8 res;
      G8 ]) X& ?. V3 c# K' c+ s, z
  278. MPU_IIC_Start(); 9 g. L* O7 I* R& X! m% J
  279. // 开始标志(S)发出后,主设备会传送一个 7 位的 Slave 地址,并且后面跟着一个第 8 位,称为 Read/Write 位。 0写,1读。
    * N" o% T& P, S- t( z
  280. MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);   // 发送器件地址+写命令1 G( Q" j+ M1 V  u
  281. MPU_IIC_Wait_Ack();                           // 等待应答
    4 e5 p- o; `* R" \3 p2 x
  282. MPU_IIC_Send_Byte(reg);                         // 写入要读取字节的寄存器首地址
    4 h4 A/ r* }$ X; O  B0 m
  283. MPU_IIC_Wait_Ack();                          // 等待应答; Y" i: Z. |& h9 B7 z) u6 \
  284. MPU_IIC_Start();
    3 K6 k% P* i/ t$ \% X; u
  285. MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);   // 发送器件地址+读命令 1 v7 T. `* h, W
  286. MPU_IIC_Wait_Ack();                           // 等待应答
    ' H+ r) m# Q  r
  287. res=MPU_IIC_Read_Byte(0);                        // 读取一个字节的数据,发送nACK
    . @2 Y; s4 O& h, |( a" J
  288. MPU_IIC_Stop();                                    // 产生一个停止条件
    ; T! B) I# ]5 e6 w  A
  289. return res;  ' M9 P% n: M7 o+ J) O3 V
  290. }
    0 d( |) E+ v7 \+ s
  291. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码

: g( q) k) j0 W7 L1 b5 {10.5 main.c主函数
$ l6 M; {* H# S6 t% ~+ L) v3 ~
3 T, M, Q2 w7 y1 s- n- ]; c7 a+ Z
  1. /**# q4 W, l% K, U0 T. @
  2. ********************************  STM32F10x  *********************************. [+ I* M1 l4 T' r2 S
  3. * @文件名称: main.c
    ; p5 e1 Q" n" B$ _. c9 s8 k4 j9 E
  4. * @修改作者: Aaron: g# h: O: s6 x
  5. * @库版本号: V3.5.0
    ! A3 B; A  W, i: r8 x3 y5 k
  6. * @工程版本: V1.0.0
      P$ n- H# c) b
  7. * @开发日期: 2020年11月30日5 S/ r0 ]! J7 {8 \- J- w+ `
  8. * @摘要简述: 主函数,增加了在LCD显示6轴的原始数据
    + P9 b' k! l7 j  ~- I' b% f
  9. ******************************************************************************/* Y% V! P6 e7 Z( O
  10. /*-----------------------------------------------------------------------------; h9 r! N) n  V+ K% Y$ ]* T
  11. * @更新日志:
    ( }0 D! F' I- r- T; w- Z) ]
  12. * @无+ V, U7 l/ E+ B5 n) g; L" P
  13. * ---------------------------------------------------------------------------*/+ f1 B0 R' ^5 O/ f& B6 b
  14. /* 包含的头文件 --------------------------------------------------------------*/$ Y5 I; t, T0 M5 n, i* _% c) s3 z' u7 @7 A
  15. #include "led.h"5 E- v7 L' Q% k% ~4 R/ t
  16. #include "delay.h"& B+ [% W" M( s4 `; m4 T
  17. #include "key.h", Y# T! a; R7 B4 K/ Y* U* C* H
  18. #include "sys.h"
    ; O' I9 u' Q3 o
  19. #include "lcd.h"! E. v. u2 J7 h3 ~
  20. #include "serial_communication.h"
    + |# z( e* h' ?7 Q
  21. #include "mpu6050.h"3 ?: a' R: U2 y7 K6 o
  22. #include "inv_mpu.h"
    " G8 A% T0 F/ {& {1 f& V8 X
  23. #include "inv_mpu_dmp_motion_driver.h" $ I$ l1 v/ L; Q1 D, [- ^- E
  24. /*********************************************************************0 \" j$ f- k& _9 f
  25. 函数名称:usart1_send_char(u8 c)
      s7 h( h1 |3 ~2 v
  26. 函数功能:串口1发送1个字符/ ~- j( V$ @8 E7 o! [* s
  27. 入口参数:c:要发送的字符
    ; Y9 V$ S1 O* b7 U  ?8 t4 R1 I
  28. 返回参数:0,成功,1失败
    % W, P; _, u0 i: T. W) H' d( m
  29. 修改作者:Aaron
    7 X% U' \' ^4 s! }/ {
  30. **********************************************************************/7 j! T8 a) q2 A) r8 X& Z+ \
  31. void usart1_send_char(u8 c)9 ?$ \7 q0 M" l$ W8 q
  32. {           
    7 m" ?9 O. c) Y& \; L! c7 [2 \
  33.         while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); // 循环发送,直到发送完毕   
    . v+ j( Q) s7 W  S' H
  34.         USART_SendData(USART1,c);  
      v# N/ Q, o$ F) ~( P. f
  35. } 1 w& W. |: W* L
  36. /*********************************************************************
    3 A  Z, }' J- V$ h  z5 j. q; `
  37. 函数名称:usart1_niming_report(u8 fun,u8*data,u8 len)
    2 K1 U: N9 m8 d9 P5 X7 R, O9 g8 `
  38. 函数功能:传送数据给匿名四轴上位机软件
    / w9 L0 k" q: ?5 s, L" |6 v
  39. 入口参数:fun:功能字.0XA0~0XAF;data:数据缓存区,最多28字节;len:data区有效数据个数
    ) v* L6 W( s) x! H1 C& P5 I$ t
  40. 返回参数:无
    # A# C  t7 [' ]6 Q
  41. 修改作者:Aaron
    / d4 n0 u- F. S$ }0 M
  42. **********************************************************************/
    " w7 T, Q- q9 J% ^7 s2 \$ n
  43. void usart1_niming_report(u8 fun,u8*data,u8 len)2 S5 N' G+ R$ R
  44. {
    : O  b% ]9 a! o4 d& |1 D9 D' C, R
  45.         u8 send_buf[32];
    ) B- T* ?; K6 u( ~/ _3 i: {
  46.         u8 i;6 B% A: O$ a; ^# r
  47.         if(len>28)return;                // 最多28字节数据
    8 p2 G; q; S5 r+ k
  48.         send_buf[len+3]=0;                // 校验数置零: S: V$ y* [  S
  49.         send_buf[0]=0X88;                // 帧头
    $ i" n! R9 g0 L' Q0 M' [+ h$ W
  50.         send_buf[1]=fun;                // 功能字
    " \9 y! q# `; G( \- s9 g
  51.         send_buf[2]=len;                // 数据长度
    ( s5 I2 C$ ?1 f% G& f
  52.         for(i=0;i<len;i++)send_buf[3+i]=data;                                                // 复制数据
    # [( U6 Z  s# @$ b
  53.         for(i=0;i<len+3;i++)send_buf[len+3]+=send_buf;                                // 计算校验和        
    0 v- u% N7 n* P3 i' m9 C
  54.         for(i=0;i<len+4;i++)usart1_send_char(send_buf);                                // 发送数据到串口1
    ' j4 n# D* ]! G7 T
  55. }* j5 m& C. A$ d5 ?! \
  56. /*********************************************************************
    2 D$ ^3 `, y  {: M: ]! V
  57. 函数名称:mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)) q* d1 d9 U! V% L
  58. 函数功能:发送加速度传感器数据和陀螺仪数据
    5 S: S% T& G2 G( c
  59. 入口参数:aacx,aacy,aacz:x,y,z三个方向上面的加速度值;gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值0 q( n3 i* e; M( ^; q! p
  60. 返回参数:无
    7 Y7 L( i- W/ U. w2 z% y
  61. 修改作者:Aaron
    ( [" r3 S  v! G! S- S  F4 L5 K- b8 ~
  62. **********************************************************************/
    0 _3 z/ s- ]# `- C; e3 o7 B) A+ J3 E
  63. void mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)
    ) T- T# b4 k: ~4 o
  64. {3 r! M. ^1 c/ M8 ^, B* T4 }
  65.         u8 tbuf[12];   u4 r) I* E6 }# X9 T# I/ |
  66.         tbuf[0]=(aacx>>8)&0XFF;
    % T. X  O* e* ^1 q
  67.         tbuf[1]=aacx&0XFF;
    ! Q$ B$ a' Y( V# I$ O
  68.         tbuf[2]=(aacy>>8)&0XFF;
    4 n* B' y7 w( p* z: H
  69.         tbuf[3]=aacy&0XFF;
    ' D' `7 _! s! H% u8 R" v! `8 j
  70.         tbuf[4]=(aacz>>8)&0XFF;
    9 T* u& u1 H8 V: x
  71.         tbuf[5]=aacz&0XFF; # e! Q7 D: e: i% c
  72.         tbuf[6]=(gyrox>>8)&0XFF;
    0 U5 S3 F/ b) @- ?
  73.         tbuf[7]=gyrox&0XFF;5 p3 x7 _% Q/ e# W' G) {/ r
  74.         tbuf[8]=(gyroy>>8)&0XFF;. P* [# d8 P* L, g7 k# U, c$ ?
  75.         tbuf[9]=gyroy&0XFF;7 e& s& e: N! z% V1 |8 _
  76.         tbuf[10]=(gyroz>>8)&0XFF;
    4 R* U; K0 `9 u( s
  77.         tbuf[11]=gyroz&0XFF;
    $ W# ]3 x8 g* k+ o
  78.         usart1_niming_report(0XA1,tbuf,12);                // 自定义帧,0XA1' W4 f* x) A8 g3 R0 f
  79. }        
    3 l9 L. s: M/ o' L) `( a' x; U
  80. /*********************************************************************
    - Y0 o/ I  a# |# g# v/ r$ b8 U  E. N' v
  81. 函数名称:mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)
    1 n4 O! u  T5 c2 S2 g0 m6 F2 h! z/ D$ ^
  82. 函数功能:通过串口1上报结算后的姿态数据给电脑
    8 t- r; g; _. u" B  L
  83. 入口参数:aacx,aacy,aacz:x,y,z三个方向上面的加速度值;gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值;
    - M8 S/ \5 {( }3 Y! m' |% [9 ~
  84.                                         roll:横滚角.单位0.01度。 -18000 -> 18000 对应 -180.00  ->  180.00度;- L7 L3 C! |. v" [: [2 O6 C  }$ M
  85.                                         pitch:俯仰角.单位 0.01度。-9000 - 9000 对应 -90.00 -> 90.00 度: q7 F% t$ D/ J5 k% A' \
  86.                                         yaw:航向角.单位为0.1度 0 -> 3600  对应 0 -> 360.0度! b) |- X: w# Q$ P# A9 p
  87. 返回参数:无2 S) w, ~& V% [: A) T( R7 T( o
  88. 修改作者:Aaron2 b/ u& Z, W; y, B7 w& y
  89. **********************************************************************/  X9 p8 a% u. H$ G
  90. void usart1_report_imu(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz,short roll,short pitch,short yaw)2 B- w& r5 l0 ?/ K8 k  ]
  91. {1 s, n6 I% y$ m. U1 `, C, u
  92.         u8 tbuf[28]; , E7 J: q0 E1 B, n' m! f
  93.         u8 i;$ g' `" P" j' _, b
  94.         for(i=0;i<28;i++)tbuf=0;                                        // 清0- B6 n: N0 o5 k5 `# L/ w
  95.         tbuf[0]=(aacx>>8)&0XFF;
    8 Z) V- }8 y- P6 |
  96.         tbuf[1]=aacx&0XFF;1 q. `9 t4 Y3 X
  97.         tbuf[2]=(aacy>>8)&0XFF;/ l: @; w: X/ }1 o
  98.         tbuf[3]=aacy&0XFF;
    # m7 u" n( [$ c; ~2 Y% P
  99.         tbuf[4]=(aacz>>8)&0XFF;" B! J* X% g; `) y: V
  100.         tbuf[5]=aacz&0XFF;
    0 g5 o3 L# v2 p% j' N/ c  @4 V' m
  101.         tbuf[6]=(gyrox>>8)&0XFF;
    - A  B3 |( b2 H* |
  102.         tbuf[7]=gyrox&0XFF;
    ' v9 m! h( a- x8 D) q% k; _* S
  103.         tbuf[8]=(gyroy>>8)&0XFF;
    ! O% V7 \) ~( [: \8 @6 ?
  104.         tbuf[9]=gyroy&0XFF;* _. ?) o4 r1 K1 V! ^
  105.         tbuf[10]=(gyroz>>8)&0XFF;/ z5 T8 y7 T& P% p. w
  106.         tbuf[11]=gyroz&0XFF;        
    6 e3 X8 O7 d& e7 a$ P( `7 G  n
  107.         tbuf[18]=(roll>>8)&0XFF;
    * Q9 q7 |6 Q2 V6 V. e3 o. i
  108.         tbuf[19]=roll&0XFF;
    : ^. I& l9 p  g7 `6 Y# V9 z
  109.         tbuf[20]=(pitch>>8)&0XFF;4 T/ Q1 J6 I. ^. }& r
  110.         tbuf[21]=pitch&0XFF;
    % ]/ d3 u3 B% g, k4 M
  111.         tbuf[22]=(yaw>>8)&0XFF;( F7 J6 ]6 @) r: B. G  n
  112.         tbuf[23]=yaw&0XFF;6 Z: t2 S; p' a' H, `7 i% |- S7 R
  113.         usart1_niming_report(0XAF,tbuf,28); // 飞控显示帧,0XAF
    0 l" w3 s2 e0 G' s2 O$ U, O
  114. }  # M% {( ^- \' O$ V
  115. /*********************************************************************" \5 i5 B- _6 D
  116. 函数名称:int main(): W7 L1 Q! e, w( [$ _
  117. 函数功能:主函数,增加了在LCD屏上显示6轴原始数据的功能
    ' ]* r+ P6 {2 C% z
  118. 入口参数:无/ I) s  N$ ?1 _% A% Q! _5 v
  119. 返回参数:无  T2 R& X+ T/ I! }
  120. 修改作者:Aaron9 Q* f* _5 Z2 r1 l/ R
  121. **********************************************************************/! A* e% l  L. n3 n9 A
  122. int main(void)" X1 X- H- h/ |; B5 H
  123. {         * f) @# P% h# d& {, D- Y, N
  124.         u8 t=0,report=1;                                                // 默认开启上报,发给匿名四轴上位机软件
    3 i+ i3 U# m9 D
  125.         u8 key;
    8 |4 b# N0 J4 W2 q, |: ?' B
  126.         float pitch,roll,yaw;                                         // 欧拉角8 G  l- ?% m2 P8 d. N5 c
  127.         short aacx,aacy,aacz;                                        // 加速度传感器原始数据
    , {  q0 j0 n; ?% A2 u' A0 f9 m
  128.         short gyrox,gyroy,gyroz;                                // 陀螺仪原始数据
    & N4 z7 l/ X4 w7 i
  129.         short temp;                                                                // 温度         
    4 s: H: H" Q* e1 h$ R2 C
  130.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                         // 设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    6 u. O; K% k0 n% W+ C0 m! b* _
  131.         My_USART1_Init();                                                                                  // 串口初始化为500000
    & J8 q8 z' f6 ?5 p1 i, H
  132.         delay_init();                                                                                         // 延时初始化
    ' Q2 ~- \7 p1 E' E7 F, F4 @8 T. h
  133.         LED_Init();                                                                                                   // 初始化与LED连接的硬件接口' s* e- p' s7 Q" v9 {- n
  134.         KEY_Init();                                                                                                 // 初始化按键) x9 D1 j# i  R# G" O4 b5 k
  135.         LCD_Init();                                                                                                    // 初始化LCD  
    1 V: D! T! E- Y; r! v# k2 m) F
  136.         MPU_Init();                                                                                                 // 初始化MPU6050
    - A  m6 Q9 w/ c
  137.          POINT_COLOR=RED;                                                                                 // 设置字体为红色         8 N" ?$ P) z, x1 H( x
  138.         LCD_ShowString(30,70,200,16,16,"MPU6050 TEST");        
    ' s- c4 m9 h9 C, k5 s
  139.         LCD_ShowString(30,90,200,16,16,"2020/11/30"); 8 F9 Q: q7 R+ H) a$ U, a: r! F$ B) m
  140.         while(mpu_dmp_init())1 L# k- e: Z) i9 f* d3 ^
  141.          {6 a3 Q# v/ F' U* W/ j
  142.                 LCD_ShowString(30,110,200,16,16,"MPU6050 Error");" `" ?3 s$ L' ^: ]7 A# b
  143.                 delay_ms(200);
    2 o4 O9 M( q4 y* [4 {
  144.                 LCD_Fill(30,110,239,130+16,WHITE);( C0 |% P/ j- W9 e" ?6 t& V, n' }
  145.                  delay_ms(200);1 E, c& e  q/ X
  146.         }  
    % v) W" u1 n. }5 }: u$ |
  147.         LCD_ShowString(30,110,200,16,16,"MPU6050 OK");
    ' u6 n- c/ C/ H# F- ?  O
  148.         LCD_ShowString(30,130,200,16,16,"KEY0:UPLOAD ON/OFF");
    # b( i3 K. ?* |( I/ N
  149.         POINT_COLOR=BLUE;                                                                                                                                 // 设置字体为蓝色 3 M  K' |, o& i" ~
  150.          LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");         4 Z9 d5 {+ w+ z
  151.          LCD_ShowString(30,200,200,16,16," Temp:    . C");        % {0 u5 o' q% K9 o4 K, h
  152.          LCD_ShowString(30,220,200,16,16,"Pitch:    . C");        3 q/ W3 Y# Q9 `1 L
  153.          LCD_ShowString(30,240,200,16,16," Roll:    . C");         
    + w, z5 d1 ], ?- T3 X0 E6 q7 l
  154.          LCD_ShowString(30,260,200,16,16," Yaw :    . C");         
    8 x+ a: E  s) c- H5 i, j7 L
  155.          while(1)7 v- X) g- r$ R* ^' U$ V& v4 R
  156.         {5 a1 r+ h- _  U' i9 w/ c$ }  Y; V7 {
  157.                 key=KEY_Scan(0);
    1 U. D1 \% n) H4 f, @
  158.                 if(key==KEY0_PRES)6 z$ c+ d. i! v. I
  159.                 {& C) T& y6 C& v4 C9 \; `7 T! @$ ]
  160.                         report=!report;
    * r: Z) a" u* O, o
  161.                         if(report)
    7 K+ |6 q( U' D4 R) x: ^
  162.                                 LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");
    * S" k3 f! w# ~# J2 P* h
  163.                         else 5 Z( E- B; W5 o  p
  164.                                 LCD_ShowString(30,170,200,16,16,"UPLOAD OFF");
    ( g' \, V2 d6 t" W" ?' d8 A9 [
  165.                 }1 U. x  t* i( b9 ~& l9 P: ?
  166.                 if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)" X4 i5 J: |- J) ^
  167.                 { , b# z' C+ N' B, e
  168.                         temp=MPU_Get_Temperature();                                                                        // 得到温度值                 ( h# A7 `" }. t9 S" J; u8 S9 W3 U) d
  169.                         MPU_Get_Accelerometer(&aacx,&aacy,&aacz);                                        // 得到加速度传感器数据/ V' C) I' L' q9 I$ J% D
  170.                         MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);                                        // 得到陀螺仪数据6 {( s' y( ]7 \/ j9 w+ h! N( X
  171.                         if(report)
    - ?4 x9 o# a: r' s6 m
  172.                                 mpu6050_send_data(aacx,aacy,aacz,gyrox,gyroy,gyroz);        // 用自定义帧发送加速度和陀螺仪原始数据
    % E9 D8 r- }6 @4 g5 D- U
  173.                         if(report)8 R4 o5 B! Q* `1 x7 J
  174.                                 usart1_report_imu(aacx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),(int)(pitch*100),(int)(yaw*10));
    5 X5 P, T  d- R( A" [( O
  175.                         LCD_ShowString(30,300,200,16,16," aacx:    ");                                                                  
    * L+ Z) n: C% i* }% h( M& b: k
  176.                         if(aacx<0)
    . [& [- C& q6 s$ K3 o8 r( g5 |
  177.                         {
    ! o; t  i% \) }1 P* H
  178.                                 LCD_ShowChar(30+48,300,'-',16,0);                         // 显示负号& `+ \: P$ q+ T' }4 d; _
  179.                                 aacx=-aacx;                                                                        // 转为正数3 Y6 Y4 h% h0 n& H* a5 `: q$ y: l
  180.                         }
    9 v$ S2 H/ D- w/ l. K7 u
  181.                         else : `. i/ Z" G6 [$ G4 t1 [
  182.                                 LCD_ShowChar(30+48,300,' ',16,0);                        // 去掉负号 9 D' w' o# T$ [
  183.                         LCD_ShowNum(30+48+8,300,aacx,10,16);                        // 显示aacx                           
    2 j% P. F7 a6 _& A4 u. q
  184.                         LCD_ShowString(30,320,200,16,16," aacy:    ");        
    ; o$ q& ]; }. ~0 g4 U5 X
  185.                         if(aacy<0)
    . C2 o& i. A, @
  186.                         {# w- {4 F- [- b' g+ \
  187.                                 LCD_ShowChar(30+48,320,'-',16,0);                          // 显示负号
    & l" d* a8 P" H
  188.                                 aacy=-aacy;                                                                        // 转为正数; r" o5 u/ l/ F' D
  189.                         }
    " \4 s% t9 b3 U) `' ]" v
  190.                         else ! j& W# T! p- u$ m* r) P$ Z
  191.                                 LCD_ShowChar(30+48,320,' ',16,0);                        // 去掉负号 4 v# N4 j. Z9 U' G# B8 t/ }0 L' g& P" u
  192.                         LCD_ShowNum(30+48+8,320,aacy,10,16);                        // 显示aacy            
    ' O; M  i$ [/ _) Q& o' K
  193.                         LCD_ShowString(30,340,200,16,16," aacz:    ");         $ z' T  N' B( N
  194.                         if(aacz<0)* I+ W- B" V" N  I$ G
  195.                         {
    / }; a, [+ A+ @/ ~5 b
  196.                                 LCD_ShowChar(30+48,340,'-',16,0);                          // 显示负号& D# B( T* h) N- m
  197.                                 aacz=-aacz;                                                                        // 转为正数
    5 D* ]- `- K, N" V6 ?1 n3 R5 l
  198.                         }! X! o( D6 n$ \9 k$ p7 g
  199.                         else
    ( ~; v: c1 Q/ p) ]. [
  200.                                 LCD_ShowChar(30+48,340,' ',16,0);                        // 去掉负号 $ _) J5 @9 b3 h+ A
  201.                         LCD_ShowNum(30+48+8,340,aacz,10,16);                        // 显示aacz           & I( K1 Z/ v9 J' \5 Q1 b
  202.                         LCD_ShowString(30,360,200,16,16,"gyrox:    ");        
    8 v( z9 b  ]$ ~6 H  A+ L+ a
  203.                         if(gyrox<0)4 P3 O6 w5 d8 l0 F
  204.                         {
    - v, ^1 W# n, l4 R- `: @
  205.                                 LCD_ShowChar(30+48,360,'-',16,0);                          // 显示负号
    ! A) V; z$ S! w. v$ R! g
  206.                                 gyrox=-gyrox;                                                                // 转为正数
    8 z; o- l# F* z3 o7 F9 g3 T6 M/ l
  207.                         }  D7 g. @/ T1 H& X/ W
  208.                         else , m. ~0 a6 P5 D
  209.                                 LCD_ShowChar(30+48,360,' ',16,0);                        // 去掉负号 1 W! J9 G( N6 r
  210.                         LCD_ShowNum(30+48+8,360,gyrox,10,16);                        // 显示gyrox    ) c) U* n& q) \9 R4 D- U' @1 I7 K
  211.                         LCD_ShowString(30,380,200,16,16,"gyroy:    ");        
    . p" X# E: c4 r2 D# J1 k7 X7 b
  212.                         if(gyroy<0)% ^/ I6 b  M% C; b% v* i$ G
  213.                         {- j/ U! N9 S2 X: w+ W! j! C- |- a+ j
  214.                                 LCD_ShowChar(30+48,380,'-',16,0);                          // 显示负号
    . I9 ]: v8 `0 L8 @$ E  K
  215.                                 gyroy=-gyroy;                                                                // 转为正数, h" e3 J9 A& c; @6 |
  216.                         }
    ; t, s! y( ^2 w+ v& x+ X0 D- E8 B5 C
  217.                         else
    " X& c5 x; n6 t  P8 P1 Q$ p% A2 d
  218.                                 LCD_ShowChar(30+48,380,' ',16,0);                        // 去掉负号 % U, Q& v8 l6 C/ N5 R: Z  c( G
  219.                         LCD_ShowNum(30+48+8,380,gyroy,10,16);                        // 显示gyroy                  
    1 F' l. b! j; L4 _0 u
  220.                         LCD_ShowString(30,400,200,16,16,"gyroz:    ");5 q8 a6 |, ?3 d. y
  221.                         if(gyroz<0)0 l+ X: E! R: Q% p
  222.                         {
    - m1 u% q: `, T! M2 z# q
  223.                                 LCD_ShowChar(30+48,400,'-',16,0);                          // 显示负号
    / s" [# A% Q( D7 R% |
  224.                                 gyroz=-gyroz;                                                                // 转为正数
    $ H2 |# d6 p% M# u
  225.                         }# Z/ j, e2 |! ?% Q# L  v8 I( {
  226.                         else 7 J* J+ o1 k# H  C1 Y
  227.                                 LCD_ShowChar(30+48,400,' ',16,0);                        // 去掉负号
    % `5 I: \# E5 _$ V0 n/ W) @
  228.                         LCD_ShowNum(30+48+8,400,gyroz,10,16);                        // 显示gyroz                           
    , x: X. F+ m! s7 ~6 j
  229.                         if((t%10)==0)3 q. P1 `) d: k
  230.                         {   Q6 d. t/ ~; d) R; a: N
  231.                                 if(temp<0)
    6 l+ U: `! Y' q4 @" X4 Y
  232.                                 {
    & G- d0 @+ L0 y
  233.                                         LCD_ShowChar(30+48,200,'-',16,0);                // 显示负号% D0 h$ T8 a' ^0 X+ g5 X+ ^
  234.                                         temp=-temp;                                                                // 转为正数
    * t: _0 Z, N8 x) v; D; T
  235.                                 }
    * j9 |: y  x: A; _$ N5 H
  236.                                 else 0 [, ^7 u) V  Y! ~& w6 n/ W5 k
  237.                                         LCD_ShowChar(30+48,200,' ',16,0);                // 去掉负号
    * |: d1 m/ {) i3 J# p$ H
  238.                                 LCD_ShowNum(30+48+8,200,temp/100,3,16);                // 显示整数部分            $ I' a" c1 Y% u7 a  g& X/ \- E
  239.                                 LCD_ShowNum(30+48+40,200,temp%10,1,16);                // 显示小数部分
    ( e  N5 ]4 a' m9 p  p
  240.                                 temp=pitch*10;& F5 r. a9 a3 f! G7 q
  241.                                 if(temp<0)
    ) l2 b3 O1 D- J* ?/ m8 U/ r# H5 ]
  242.                                 {, ~% \6 z( Y/ x( \
  243.                                         LCD_ShowChar(30+48,220,'-',16,0);                // 显示负号
    ; @) e& ^- m% D( D# p
  244.                                         temp=-temp;                                                                // 转为正数
    & m6 b. {+ A7 N2 l# p3 t% y* _
  245.                                 }2 e' z- v( R1 i* p9 W& t5 h
  246.                                 else ; P! U! d8 d8 i, `4 z+ I/ P, T& |
  247.                                         LCD_ShowChar(30+48,220,' ',16,0);                // 去掉负号
    ; k/ X) @& S" K- O5 D( }9 G+ v
  248.                                 LCD_ShowNum(30+48+8,220,temp/10,3,16);                // 显示整数部分            
    % n$ `3 l2 S( M  w  f; O/ n
  249.                                 LCD_ShowNum(30+48+40,220,temp%10,1,16);                // 显示小数部分
    & |7 _+ j6 `7 U4 U
  250.                                 temp=roll*10;5 F( J5 w( x; W4 R# r( V& U
  251.                                 if(temp<0)
    # @4 v! v. x; O! i, t
  252.                                 {2 @" e& _' u5 L+ g
  253.                                         LCD_ShowChar(30+48,240,'-',16,0);                // 显示负号2 P* l6 {* a/ m
  254.                                         temp=-temp;                                                                // 转为正数( C3 G/ q3 a+ W  U, v" N. g" m, l
  255.                                 }5 X9 L" K( w3 S2 ?3 J  T
  256.                                 else
    " d' v: G) Q! J9 W! i
  257.                                         LCD_ShowChar(30+48,240,' ',16,0);                // 去掉负号
    , D# i2 B" D3 m, W3 g7 K
  258.                                 LCD_ShowNum(30+48+8,240,temp/10,3,16);                // 显示整数部分            0 r# W% \$ m2 i$ D
  259.                                 LCD_ShowNum(30+48+40,240,temp%10,1,16);                // 显示小数部分 " I$ N6 H3 v6 M7 @& B
  260.                                 temp=yaw*10;. ~6 i3 \, q3 b
  261.                                 printf("temp=%d\r\n",temp);
    ! Y4 _4 |/ E+ q% `" ?+ L  A
  262.                                 if(temp<0)+ W0 W) h* g6 l- E. L2 z
  263.                                 {) ?. k7 R& X, o: f7 ^6 h4 |( M, p
  264.                                         LCD_ShowChar(30+48,260,'-',16,0);                // 显示负号7 n& L+ H7 W7 J2 p; O
  265.                                         temp=-temp;                                                                // 转为正数
    0 [5 r. l: X5 K) s& {! w6 S
  266.                                 }
    ! h3 C: ?- I. n: [8 L
  267.                                 else 7 E* N, z( c* Q# }
  268.                                         LCD_ShowChar(30+48,260,' ',16,0);                // 去掉负号 2 l* u8 `: L8 j
  269.                                 LCD_ShowNum(30+48+8,260,temp/10,3,16);                // 显示整数部分            ! \9 A% x7 N7 y5 J  r, D9 d# A. m$ i
  270.                                 LCD_ShowNum(30+48+40,260,temp%10,1,16);                // 显示小数部分    B1 O- j3 B' M8 G2 j
  271.                                 t=0;& k# A& h- ~9 N" U- L
  272.                                 DS0=!DS0;                                                                        // LED闪烁) p9 `! ^, V7 f' u/ S  x+ M4 s
  273.                         }
    + c: N2 s+ x' d/ l6 G4 e
  274.                 }5 U1 l, ^& p4 j! x+ p! o6 h4 ]
  275.                 t++;
    " f, w2 E" o0 L! v- K% K
  276.         }         
    . u) L8 M/ m: r) u- @$ B2 Z' J1 S3 I
  277. }! P  c; L% R1 G0 L8 ~: Q' {! n
  278. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码
* ~- y; Y3 n; o: C8 A
10.6 移植文件/ k& f0 @: F8 r+ @  C# ]
文件中代码太多,这里主要关注:
% x/ p7 ^/ ~. B: @) s: e) Z1)inv_mpu.c源文件中定义了四个函数:2 [( I- H6 B+ _: \; r/ R! m
0 J6 _! v( V$ a; I. |# t
  1. #define i2c_write   MPU_Write_Len  // 对应mpu6050.c源文件里的MPU_Write_Len
    8 Z) C1 v* y2 y
  2. #define i2c_read    MPU_Read_Len   // 对应mpu6050.c源文件里的MPU_Read_Len( X# _6 T: _7 w# p0 j+ ?
  3. #define delay_ms    delay_ms       // 对应delay.c源文件里的delay_ms0 C3 s5 {' m& l( S$ Z: @
  4. #define get_ms      mget_ms        // 这是一个空函数
复制代码

/ C8 Q# s6 h+ M5 U$ E8 d2)inv_mpu.c源文件中u8 mpu_dmp_init()初始化函数:5 y/ m0 V: F: Y/ L

, j4 }, w) R+ V. _; |. o" _- ^
  1. u8 mpu_dmp_init(void)
    $ q9 A7 P5 [* V3 h. w8 i
  2. {% D3 K9 x$ m1 h$ ], e, N
  3. u8 res=0;$ @" B& }% |+ |' J- T9 p' G
  4. MPU_IIC_Init();   // 初始化IIC总线
    3 g' y+ a; ^8 b* d
  5. if(mpu_init()==0) // 初始化MPU6050
      g; n4 M, w# D: f. M7 j
  6. {  8 w1 P. h1 b5 U- ?0 q+ @2 b
  7.   res=mpu_set_sensors(INV_XYZ_GYRO|INV_XYZ_ACCEL);     // 设置所需要的传感器
    ; y1 `; l$ i9 y* _
  8.   if(res)return 1;
    ! b4 m0 U( T; r3 ^3 i$ i
  9.   res=mpu_configure_fifo(INV_XYZ_GYRO|INV_XYZ_ACCEL);  // 设置FIFO
    ! _7 `$ P) }* n# {% Z% E7 _* _& J7 O
  10.   if(res)return 2;
      L: q$ B4 k  n$ m
  11.   res=mpu_set_sample_rate(DEFAULT_MPU_HZ);             // 设置采样率
    0 w3 t, c) ?7 I* ]# C1 G8 L
  12.   if(res)return 3;
    , m- x$ j2 C- y
  13.   res=dmp_load_motion_driver_firmware();               // 加载dmp固件6 G9 [+ j6 {; W+ D
  14.   if(res)return 4; * I7 E) [  x+ d% S8 h6 B6 t
  15.   res=dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation)); // 设置陀螺仪方向% u+ b( y7 v7 H  i' ~( @
  16.   if(res)return 5;
    3 p$ y. I1 k5 l
  17.   res=dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT|DMP_FEATURE_TAP|               // 设置dmp功能
    , U1 h6 `4 c, o& e
  18.       DMP_FEATURE_ANDROID_ORIENT|DMP_FEATURE_SEND_RAW_ACCEL|DMP_FEATURE_SEND_CAL_GYRO|9 q( z( j! z) t( M+ n) b: Y
  19.       DMP_FEATURE_GYRO_CAL);
    4 p& M0 S$ ~6 [. H* l1 m, z5 J9 \
  20.   if(res)return 6; 2 C8 v6 T, e0 l4 i4 F% Y) q$ B
  21.   res=dmp_set_fifo_rate(DEFAULT_MPU_HZ);  // 设置DMP输出速率(最大不超过200Hz)8 Z. ^  o- E! X6 M
  22.   if(res)return 7;   
    3 z0 ?5 ?& T, X8 u+ O6 v
  23.   res=run_self_test();                    // 自检. N4 E# _) m; K6 T$ ~: l
  24.   if(res)return 8;    1 k& v$ {, R* V2 O0 H( u- q. ~
  25.   res=mpu_set_dmp_state(1);               // 使能DMP) y" k& J5 S  F6 c) j/ z* Y8 o1 h
  26.   if(res)return 9;     
    : X2 K9 ?) Z7 [* {* o- M' B) D
  27. }else return 10;
    ! f1 N. C# S6 t! A: U9 y  t
  28. return 0;
    8 Y- e+ a, d$ z8 h! {* ^
  29. }
复制代码
5 i( q5 q7 w, w% w
3)inv_mpu.c源文件中u8 mpu_dmp_get_data(float *pitch,float *roll,float *yaw)获取欧拉角的函数:
3 P- Y& L  Z! l9 I
* V3 E# m8 z, u) H
  1. u8 mpu_dmp_get_data(float *pitch,float *roll,float *yaw)1 z  }$ {; _+ Y/ o; g# N; m: o
  2. {
    + Z9 _4 q: D9 Z/ k8 g5 \
  3. float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;0 d' i, ?& o9 m: h
  4. unsigned long sensor_timestamp;- r! n1 j. e- b# n& n5 b' S
  5. short gyro[3], accel[3], sensors;% t" B2 @( A' A( J( m
  6. unsigned char more;
    : h( Q1 Z( O( E; M
  7. long quat[4]; ' G# K' t9 G: }' G" T% y+ S, t
  8. if(dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more))
    3 O" `9 ^' k7 ]7 j) T
  9.    return 1;  
    - U! g4 t. R" l! H' b9 x
  10. ors&INV_WXYZ_QUAT)
    + c. Y8 `' {1 d, y
  11. {% B5 B. n/ L, i, K  V
  12.   q0 = quat[0] / q30;    // q30格式转换为浮点数  G: b) X, U7 i; V: M4 ~
  13.   q1 = quat[1] / q30;
    3 I. k$ W9 |% W; k8 C4 L  K
  14.   q2 = quat[2] / q30;
    1 e: n' }* Z, ]2 y& {9 C5 p
  15.   q3 = quat[3] / q30; " O5 D* s  Z" z
  16.   // 计算得到俯仰角/横滚角/航向角( x1 X9 r( W5 S: I/ q
  17.   *pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch4 e$ r1 ^; Q1 g2 e$ q+ o
  18.   *roll  = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
    3 J- g- p8 v( [. w6 k- ?
  19.   *yaw   = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3; //yaw" @6 x& z& I( z" U  G6 N. {2 l* V
  20. }" V" X& e8 P' ^3 X9 K
  21. else
    - X/ f+ X" k9 t; G3 S1 x
  22.    return 2;1 K8 y6 @, a3 ]1 x: _: B2 u
  23. return 0;
    7 N, p7 L. }% B5 `
  24. }
复制代码

" K- p6 [0 p& N1 i& p, r! r6 i" s% q3 h十一、实验结果
6 m( y4 v9 x2 x
该程序可用匿名四轴上位机软件实时查看6轴的原始数据和姿态数据,即欧拉角:航向角(yaw)、横滚角(roll)和俯仰角(pitch)。(这里就不放截图了)。
) ]' U; L& l+ I, R另外在LCD屏上,也可实时查看6轴的原始数据和姿态数据,如下图:5 u# V; u) h9 Q" u' |, J
20201204235655599.png $ w2 w4 M* N4 c7 r6 c

! l$ N4 J6 H+ m2 v, z& s$ R$ B————————————————$ \+ Y: H6 x. c
版权声明:天亮继续睡0 m  t( f- h; [- {; J- W
" z0 F; @  U" N3 B
1 X+ @! n# q5 x" I" s/ T; _1 h0 q3 U
% |' [" U+ N4 p
收藏 评论0 发布时间:2022-11-18 19:00

举报

0个回答

所属标签

相似分享

官网相关资源

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