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

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

[复制链接]
STMCU小助手 发布时间:2022-11-18 19:00
主要内容:
& A3 S9 o% p7 q9 q1 t1)MPU6050简介;
# `* I, v9 Q5 ^. D! z* J" j2)MPU6050相关寄存器介绍;$ h6 t" n! }4 T# _, j
3)相关实验代码解读(除了案例可实现的功能外,主函数增加了在LCD屏上显示6轴的原始数据(含正负号)的功能)。& D( ?% C! v% e5 B

, ]# Y4 e5 \! m* c一、什么是MPU6050?
: l" G' C/ U8 g' D' Z# S0 V2 d) C; ?MPU6050是InvenSense公司推出的全球首款整合性6轴运动处理组件,内带3轴陀螺仪和3轴加速度传感器,并且含有一个第二IIC接口,可用于连接外部磁力传感器,利用自带数字运动处理器(DMP: Digital Motion Processor)硬件加速引擎,通过主IIC接口,可以向应用端输出完整的9轴姿态融合演算数据。* m( a- ~: l+ c- x. j

$ J% r! B4 B3 e8 [! ^/ X; f6 o二、MPU6050特点* E( K$ v6 W0 T6 r9 C; \8 Q7 Y
1)自带数字运动处理(DMP: Digital Motion Processing),输出6轴或9轴(需外接磁传感器)姿态解算数据;$ |3 q. E9 j. L0 O4 C* J" C
2)集成可程序控制,测量范围为±250、±500、±1000与±2000°/sec 的3轴角速度感测器(陀螺仪);
2 z1 z; `% \6 ~3 K; L9 @3)集成可程序控制,范围为±2g、±4g、±8g和±16g的3轴加速度传感器;% u- M* p3 q% H/ P  O
4)自带数字温度传感器;+ q1 j$ G6 _7 D/ T5 n
5)可输出中断(interrupt),支持姿势识别、摇摄、画面放大缩小、滚动、快速下降中断、high-G中断、零动作感应、触击感应、摇动感应功能;/ E% n; d) H. z" c1 ]
6)自带1024字节FIFO,有助于降低系统功耗;
3 w) v; f+ e. `( L7)高达400Khz的IIC通信接口;
# w) W" I5 j- V) P1 h8)超小封装尺寸:4x4x0.9mm(QFN)。
5 X3 Z+ `  ^3 T2 b0 `) I" `1 K$ i7 Y, z
三、MPU6050框图
* o6 [7 h9 U9 G+ W+ [, \ 20201202115316729.png
3 a7 m  W+ ]: T; CAD0=0对应器件物理地址=0X68
5 n! I0 `# b- x& P2 x2 O: f( b* T; bAD0=1对应器件物理地址=0X69
, t4 R+ n+ p# j7 x) i- y6 |
0 H/ C# M3 |2 o* m四、MPU6050初始化
1 H# K0 F6 ^$ L( z3 u9 L8 w( q1)初始化IIC接口;' i3 G! T* M' x" M
2)复位MPU6050,由电源管理寄存器1(0X6B)控制;1 W( |4 j% D# }$ y0 f$ j* Z
3)设置角速度和加速度传感器的满量程范围,由陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置 ;
$ W/ B) |, H( Z5 x" h4)设置其他参数:
6 w+ }7 H3 P* r5 i设置中断,由中断使能寄存器(0X38)控制;( D$ a1 H; U9 w2 r+ h; [. F  w
设置AUX IIC接口,由户控制寄存器(0X6A)控制;' z: Q  T" y* ~# D+ S; @
设置FIFO,由FIFO使能寄存器(0X23)控制;6 Z5 t' q0 I* i! _
设置陀螺仪采样率 ,由采样率分频寄存器(0X19)控制;
0 p& ?. X, }; K设置数字低通滤波器,由配置寄存器(0X1A)控制;
& i6 B8 ?5 Q- a3 n7 S0 v6 X- h5)设置系统时钟。由电源管理寄存器1(0X6B)控制。一般选择x轴陀螺PLL作为时钟源,以获得更高精度的时钟;
+ I8 i, Y) @' P6 J6 w$ K6)使能角速度传感器(陀螺仪)和加速度传感器。由电源管理寄存器2(0X6C)控制。  X8 g! D. k* ~) S% h
初始化完成后,即可读取陀螺仪、加速度传感器和温度传感器的数据了!!5 I% o2 c9 c* i. {6 Q

. y9 b, l# G" n五、主要的寄存器介绍
! E4 y6 D( `  h5.1)电源管理寄存器1(0X6B)/ d/ q) _9 z. J  z  p

/ F) Q7 O) ]! d! x5 V- E 20201202124650455.png & R( [  K: C; \2 j
- p( W6 q8 q2 c: B$ C7 {2 c  \% Y
DEVICE_RESE=1,复位MPU6050,复位完成后,自动清零;
7 _( J( A9 l+ v% f6 ySLEEP=1,进入睡眠模式;SLEEP=0,正常工作模式;
: O$ I9 K( U, v* {; e/ c$ pTEMP_DIS,用于设置是否使能温度传感器,设置为0,则使能;& U( _/ {4 v8 ~/ {5 h6 G; k+ D
CLKSEL[2:0],用于选择系统时钟源,如下表所示:
6 I5 J3 P+ g2 B6 K4 v: v
5 M, s% T$ h+ I8 t 20201202124734929.png
6 V1 j$ U, Q0 |' y: F7 d
- K4 K( ]: l* G0 R5.2)陀螺仪配置寄存器(0X1B). P+ v1 w3 s% b3 F( ^5 l9 G$ a2 ^

5 A$ K6 O; K3 X8 b* w0 ]6 q' q8 ` 20201202124826207.png
! d) t3 ?, K+ }; Z4 Z9 P% L7 P
8 e6 h& h' C5 R1 w主要关注FS_SEL[1:0]这两个位,用于设置陀螺仪的满量程范围:+ d. {" Z6 J0 n8 U2 f
0,±250°/S;1,±500°/S;2,±1000°/S;3,±2000°/S;
! w) I' J2 w0 ]一般设置为3,即±2000°/S,因为陀螺仪的ADC为16位分辨率,所以灵敏度为:65536/4000=16.4LSB/(°/S)。' s- s' E! j2 t
- w8 a( E/ \* {. P
5.3)加速度传感器配置寄存器(0X1C)5 m* S  L* v$ ^8 q, {( `

. `  t6 [  ?' G# e$ ~# f 20201202124906190.png
9 c( S4 g3 m" b. q; Q) {
) N6 Z& |4 a7 v主要关注AFS_SEL[1:0]这两个位,用于设置加速度传感器的满量程范围:
+ Y: U- H1 F0 Q) [9 g0,±2g;1,±4g;2,±8g;3,±16g;- p8 c- @8 |4 g7 I0 m" v
一般设置为0,即±2g,因为加速度传感器的ADC是16位,所以灵敏度为:65536/4=16384LSB/g。
" D. j. f+ A/ ]0 J9 ~, _3 g4 U) I  _3 M# m! N5 D: L2 o' R
5.4)FIFO使能寄存器(0X23). D' ^' j9 ^; S3 p  O6 q

# u, c/ W7 Y1 g; [$ C 20201202124951209.png
. j7 ]$ l1 R# O/ U( E: Y. n; y! H0 \
该寄存器用于控制FIFO使能,在简单读取传感器数据的时候,可以不用FIFO,设置对应位为:0,即可禁止FIFO,设置为1,则使能FIFO。6 b: t* Y7 M' Y( c
注意:加速度传感器的3个轴,全由1个位(ACCEL_FIFO_EN)控制,只要该位置1,则加速度传感器的三个通道都开启FIFO了。& a# W8 j# K; k0 I# g* K/ O
- M- h, f" U7 P2 Z
5.5)陀螺仪采样率分频寄存器(0X19)
$ [  i0 \! `3 @4 k7 S
- k6 L+ S+ W/ \" t 2020120212502194.png 4 Q) ~. h9 i9 c' O4 P

  r6 r2 ~+ h$ n该寄存器用于设置MPU6050的陀螺仪采样频率,计算公式为:
$ T9 X- D: ~* J采样频率 = 陀螺仪输出频率 / (1+SMPLRT_DIV)2 U- J0 h+ V1 b) N( o% K
这里陀螺仪的输出频率,是1Khz或者8Khz,与数字低通滤波器(DLPF)的设置有关,当DLPF_CFG=0或7的时候,频率为8Khz,其他情况是1Khz。而且DLPF滤波频率一般设置为采样率的一半。采样率,我们假定设置为50Hz,那么:SMPLRT_DIV=1000/50-1=19。/ [) J9 A) f5 x

0 A$ _7 J, p, d; c9 T" |/ n5.6)配置寄存器(0X1A)
) M( o1 q6 Q; S8 {: F
2 Q0 Q' q" B: R# \# V; e6 B7 t 20201202125111514.png
" m( {1 h' Y& \6 H
8 S. Q; O" g! ?$ W: d) b! N/ {1 ?4 ?重点看数字低通滤波器(DLPF)的设置位:DLPF_CFG[2:0],加速度计和陀螺仪,都是根据这三个位的配置进行过滤的,如下表所示:
6 r: A5 ?6 R! ]/ Z. g! |# A+ ^
20201202125128497.png
6 U0 ], _! ~; }8 p: w7 e3 N- a. d( d! D& N+ Y. p
备注:带宽=1/2采样率6 }9 O/ Q8 L0 r8 u, A: O* y
3 Q( W$ J6 z' i+ G
5.7)电源管理寄存器2(0X6C)
( C1 v9 _) I; B0 m0 H4 x
7 Y7 G1 N( K8 K0 Z# q 20201202125210534.png
4 q/ D  [0 i$ P+ ^2 ]7 M4 Q
& d! M) r/ {4 C2 w/ q! _" o, K该寄存器的LP_WAKE_CTRL用于控制低功耗时的唤醒频率;
% W  S" p- Y1 V/ r4 b, F% V剩下的6位,分别控制加速度和陀螺仪的x/y/z轴是否进入待机模式;2 q' |8 Y: v; u3 b7 |) C$ b$ u
本例程全部设置为:0 ,即可。
/ \. O  V" R: d% e! M2 S6 H8 I
5.8)加速度传感器数据输出寄存器(0X3B~0X40)
1 F% i/ \* H. G' \
* w) V% k6 ]' `6 Y1 A 20201202125232456.png
/ P3 Q$ ^9 Q1 V1 n
  q3 h. X# A2 D# G' Y总共由6个寄存器组成,输出X/Y/Z三个轴的加速度传感器值,高字节在前,低字节在后。+ V9 j6 |5 H1 x, J" H

$ y4 b; j  ~: `. X  B/ O5.9)陀螺仪数据输出寄存器(0X43~0X48), M7 @+ R: f8 {- K' n# T+ w' G; o
; V& b& N0 H% Z  |
20201202125315716.png " ~/ G5 \2 k& v+ K  F

2 Z+ K; I% q6 g总共由6个寄存器组成,输出X/Y/Z三个轴的陀螺仪传感器数据,高字节在前,低字节在后。, _( H9 m8 h3 ^% \- _+ o

1 t0 i% h" ], ?) u  D# s5.10)温度传感器数据输出寄存器(0X41~0X42)
) K3 k" V- J0 O$ z1 ?& ~3 c1 e0 x' W; `& o+ y6 o; w" A  |. X
20201202125336901.png
# |& @& \, q* G/ d( [6 x5 I+ }! D' k9 |! |
通过读取0X41(高8位)和0X42(低8位)寄存器得到,温度换算公式为:
* @8 R* d$ `+ N% E! z2 i. Q$ WTemperature = 36.53 +regval/340$ ?6 T! s$ w0 I  R. g, t
其中,Temperature为计算得到的温度值,单位为℃,regval为从0X41和0X42读到的温度传感器值。
; R5 K. h2 I. c
1 ]' L+ I: V1 E# i六、DMP使用介绍
  a/ v# g( J4 O实际使用时(比如做四轴),我们更希望得到姿态数据,即欧拉角:航向角(yaw)、横滚角(roll)和俯仰角(pitch)。/ j3 o* h2 C3 Z* m: l+ ^
要利用原始数据,需要进行姿态融合解算。MPU6050自带数字运动处理器,即DMP,并且InvenSense提供了一个MPU6050的嵌入式运动驱动库,结合MPU6050的DMP,可以基于原始数据直接转换成四元数输出,而得到四元数之后,便可很方便的计算出欧拉角,从而得到yaw、roll和pitch。
( f& K$ h0 X4 T& g3 G- z5 w备注:InvenSense提供的MPU6050运动驱动库是基于MSP430的,需要将其移植后才可以用到STM32上面。6 Q, W) j) C) O3 {/ D7 ~3 S  a

: v9 s3 s- B+ I) L# ]移植细节:3 j- n$ J, v5 N: ]+ E1 F  R
官方DMP驱动库移植,主要是实现这4个函数:i2c_write、i2c_read、delay_ms和get_ms。
/ _. ~) p5 ^8 R- ^3 m& |' ?移植后的驱动代码如下图:
9 _; Q: y$ P7 ?! Q6 Y# I" b( t! g' I$ R* Q1 t
20201202125526501.png
0 `6 M# i7 r# T) w) o+ \# F7 R9 l7 \& ]
MPU6050 DMP输出的是姿态解算后的四元数,采用q30格式,即2的30次方,要得到欧拉角,需要做一个转换,代码如下:. C2 H. T, T6 k( X9 V& ~4 p; a4 J

% `( x) h% E7 ?- t
  1. q0=quat[0] / q30;   // q30格式转换为浮点数
    , Z- R2 F* O; G% }. r0 ^" _& F$ |
  2. q1=quat[1] / q30;   // q30格式转换为浮点数/ n, M. n8 C; p3 K; X* L% y) B! |
  3. q2=quat[2] / q30;   // q30格式转换为浮点数
    " v4 w4 G% }/ Y6 [3 l6 z
  4. q3=quat[3] / q30;   // q30格式转换为浮点数
      P: Z& k+ P  m3 m
  5. // 计算得到俯仰角/横滚角/航向角# x. p. ?- x  I5 n* R6 s
  6. pitch=asin(-2 * q1 * q3 +2 * q0* q2)* 57.3;      // 俯仰角
    - v' R! r9 M$ [4 L( H
  7. roll=atan2(2 * q2 * q3 +2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // 横滚角yaw=atan2(2*(q1*q2 +
    3 ]6 ?  a5 d" X# l9 u( R
  8. q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3;          // 航向角
复制代码

2 c7 p5 Y% Z2 K5 s2 h上述代码中:quat[0]~quat[3]:是MPU6050的DMP解算后的四元数,q30格式; q30:是一个常量:1073741824,即2的30次方; 57.3:是弧度转换为角度,即180/π,这样结果就是以度(°)为单位的。* x' r% I& d% t& r% x5 @, o: f

  y- B& [! J4 E2 g/ W: m七、ATK-MPU6050模块0 T0 {- l% {# u/ g
ATK-MPU6050模块主要由MPU-6050芯片和RT9193-33芯片组成,原理图如下图所示:
8 ?/ w7 S& J8 I' w/ A
( G- S  |1 y; M3 D+ [ 20201202125803667.jpg 8 q+ S3 @2 H# b( V
, \$ u; c2 d: s0 M' ^  s$ f
开发板通过ATK-MODULE接口外接MPU6050模块,硬件连接原理图如下:& s  b0 \2 c5 C) D) a) b
8 w4 m4 ~6 ^1 D+ F9 ~! Q- S
20201202125834118.jpg ( X' a. ^- r; Z& A4 Y# Y# I# n

5 L! V; X1 B* c' n4 \) ~6 C1 F- {八、重点关注的相关代码# E% p( h$ g6 A5 U/ ]: x  ?
8.1)MPU-6050驱动代码% B. v. w3 x; m) j2 n- {
1,MPU6050 IIC接口驱动代码
$ V' B, s2 m9 J5 F0 H, h2,MPU_Init函数/ S2 d: U9 z- `% S9 N
3,MPU_Get_Gyroscope函数; S1 O( u+ Y6 o% L3 J/ ^
4,MPU_Get_Accelerometer函数
$ `$ e  V5 c" A7 |% A3 t$ O5,MPU_Get_Temperature函数2 ]% S6 C; c1 b' g+ H6 `
8.2)DMP驱动代码& C8 L2 O" g! S5 L" C
1,DMP移植相关代码
3 E4 s- y3 ?- D( xi2c_write、i2c_read、delay_ms和get_ms." ]! i6 g) @+ s8 ]
2, mpu_dmp_init函数
# o+ K- F3 W* R$ l+ p3, mpu_dmp_get_data函数
; |; E0 O) I8 D( j, W
/ F8 y5 t& o  Y- t九、MPU6050读写时序
1 \8 _) `  x4 @0 C: w- b- B; T9.1)单字节写入时序6 ?8 y) x+ R# X, n
' l; |4 Y7 g7 j' Z
20201202130030646.png ) ?7 q! U" S0 Z1 }! R# J
% k, \, \8 h. ]: ?% l: [
9.2)连续写入时序5 y' Z, G9 a) q- i$ L0 n
. u+ W% }0 p) M4 p1 @
2020120213005560.png
$ |9 N; ]1 R9 j. ~( z
3 d, y3 l( m: A  s9.3)单字节读出时序
' C/ U7 H6 i0 F6 r3 g& t' C  z" O3 `% q. W
20201202130110852.png - P0 E+ O: y1 F

" B  _+ }. |, c9.4)连续读出时序
, }. H' h: v6 ]( k1 \% t0 t- K% T" L" s! H6 }, F
20201202130123583.png 9 A' K0 e) M8 @- f. F3 }
# B7 |% q) U5 E: I3 }5 k: h
十、部分实验代码解读
5 A) L7 C6 W$ ?- K( a1 w10.1 mpuiic.h头文件函数6 ?/ n4 _$ p( E" v9 B) d

, X; t. H2 ]4 ^. o8 I
  1. /**% p8 P* r. T( d5 T; T
  2. ********************************  STM32F10x  *********************************
    5 l2 A2 m" ]1 o6 `
  3. * @文件名称: mpuiic.h
    2 R7 w. p$ p/ I; r, d
  4. * @修改作者: Aaron
    - ]; Y+ ?1 i/ p5 T% d. K0 F
  5. * @库版本号: V3.5.0$ m+ b! }) w" m7 {7 [
  6. * @工程版本: V1.0.0* C# ^) `8 W7 w  C  R/ Y) g/ g! i
  7. * @开发日期: 2020年11月30日
    - H, Q7 Z6 S  f2 a. n4 @1 y
  8. * @摘要简述: mpuiic头文件,主要跟MPU-6050模块进行IIC通讯时用
    1 W* o' t) m5 x. X" v  b
  9. ******************************************************************************/. b: ^9 i/ h) P6 H1 q9 }
  10. /*-----------------------------------------------------------------------------
    5 Q  X  _. `1 i% k  R2 N( o$ v8 ?
  11. * @更新日志:6 g$ e- C$ y4 d6 D
  12. * @无5 H% x% {. f9 T: ^$ ]
  13. * ---------------------------------------------------------------------------*/- H/ h& l) Q3 S( R5 j4 l
  14. #ifndef __MPUIIC_H
    , ?+ i! L/ z$ C/ y" a
  15. #define __MPUIIC_H& c* E  T7 W! ?' w% c
  16. /* 包含的头文件 --------------------------------------------------------------*/; c8 t6 h, ^6 Y6 Y- ]9 t
  17. #include "sys.h"
    7 N$ P0 L% }. M, c* \' _
  18. #include "stm32f10x.h"
    7 Z* ]. N$ b+ D, h1 e; D% @. n2 W4 s: A
  19. /* 寄存器方法控制GPIO管脚输入输出模式 ----------------------------------------*/
    & D4 R' f% ?, ], \/ E' X3 y7 W5 A8 l. q
  20. #define MPU_SDA_IN()  {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=8<<12;}   // PB11 上拉输入模式
    4 V: |, Y  |5 V! X5 B8 m
  21. #define MPU_SDA_OUT() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=3<<12;}   // PB11 通用推挽输出模式,50MHz
    3 b5 E+ o6 {  v5 @1 y# m* D
  22. /* 位操作方法定义 ------------------------------------------------------------*/
    + X* w1 S/ g1 Q, q$ @
  23. #define MPU_IIC_SCL    PBout(10)   // PB10对应SCL
    % v& E" H1 D: j/ i' O8 w; n& r
  24. #define MPU_IIC_SDA    PBout(11)   // PB11对应SDA,输出SDA  
    ) v+ C" k+ k& e
  25. #define MPU_READ_SDA   PBin(11)    // PB11对应SDA,输入SDA" w( s2 T) n5 H5 j" r/ e
  26. /* 定义IIC底层驱动程序 -------------------------------------------------------*/
    1 m# @2 n! s6 w7 e
  27. void MPU_IIC_Delay(void);                         // MPU IIC延时函数,延时 2 us
    8 @3 j7 {$ m( L' y5 h. D
  28. void MPU_IIC_Init(void);                   // 初始化IIC的IO口- P) Q# P8 o4 `7 [0 j
  29. void MPU_IIC_Start(void);                  // 发送IIC开始信号  ~+ m: Y+ V' A6 A: D: e4 X
  30. void MPU_IIC_Stop(void);                              // 发送IIC停止信号
    & h6 i: w6 w- V6 O* u% \' u  A
  31. u8 MPU_IIC_Wait_Ack(void);                 // IIC等待ACK信号' u* B3 f) k) s6 w; e1 Q& q
  32. void MPU_IIC_Ack(void);                    // IIC发送ACK信号   
    * x+ e  w5 _# \7 k$ H5 ~  R& a
  33. void MPU_IIC_NAck(void);                   // IIC不发送ACK信号
    . C- \9 c% w& B# p+ H
  34. void MPU_IIC_Send_Byte(u8 txd);            // IIC发送一个字节% G) I; [) X! c" G6 j. G
  35. u8 MPU_IIC_Read_Byte(unsigned char ack);   // IIC读取一个字节
    7 Y  j; x: n. t+ i6 k: G  j! q
  36. #endif /* __MPUIIC_H */
    3 B& m9 t0 p# ^
  37. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码

" u+ Z/ `0 V( W, H& F0 c10.2 mpuiic.c源文件函数5 c# o. A" h: C: |4 a  Z

! l" v5 Y/ N" M3 {4 _- r+ w
  1. /**4 J. U- g( y7 Q% j/ N& w, f5 `4 a- F% w- U
  2. ********************************  STM32F10x  *********************************0 u; m0 h3 n$ Q; j
  3. * @文件名称: mpuiic.c, w( Y8 E3 p  Y, l4 {
  4. * @修改作者: Aaron
    ! \' i/ U  ^: b, d% `
  5. * @库版本号: V3.5.0
    ) S$ i) f* l9 Z/ K4 I  M- C
  6. * @工程版本: V1.0.0
    3 }; o; K7 E5 s: C2 t5 [
  7. * @开发日期: 2020年11月30日$ M6 s$ D; U9 r' ~8 @: z8 `
  8. * @摘要简述: mpuiic源文件,主要包含与MPU-6050进行IIC通讯的IIC底层驱动程序' \' r+ n+ |1 \3 x7 Q+ d& m; O/ R
  9. ******************************************************************************/; e0 S! P7 C+ h! ?6 d8 ^
  10. /*-----------------------------------------------------------------------------( O" h+ O" Y) l3 L* r
  11. * @更新日志:
    0 |% g; [/ z! x) v4 g% E& g
  12. * @无6 ]5 C+ o1 z" C4 f# t. O: a
  13. * ---------------------------------------------------------------------------*/8 g; r5 E' d% R0 d8 Y9 j9 M
  14. /* 包含的头文件 --------------------------------------------------------------*/
    # p3 `' l  I8 }% s' J0 k
  15. #include "mpuiic.h"( a% b7 [8 |# N/ G
  16. #include "delay.h"  r, g3 Z8 M3 f0 y! Y% A$ R* `
  17. /*********************************************************************
    ! s+ ?+ B$ K; b0 T7 u0 t. X
  18. 函数名称:MPU_IIC_Delay()( D  h8 b9 z0 ], w+ o! V
  19. 函数功能:延时函数,延时2微秒(us)6 E3 ^0 o( i4 ~0 X. W2 e7 ?
  20. 入口参数:无
    . n$ M; v1 S# K8 m: H1 e3 R
  21. 返回参数:无; Z6 t, f8 o+ `, r* V
  22. 修改开发:Aaron0 O6 P: j& Y7 ^# f7 v0 l
  23. **********************************************************************/
    $ D: K" i9 h$ K" o, \
  24. void MPU_IIC_Delay(void)( C3 N; B- L* v/ U: ~
  25. {
    4 E& a( W7 Z: @# d/ k
  26. delay_us(2);
    4 c- {/ b/ A6 M% L# w- M+ o4 G$ Y
  27. }
    3 V. z' P2 d, ]7 x  B8 `  b, L- K
  28. /*********************************************************************
    0 b3 F4 }7 P! s$ T3 L' ~- m1 E
  29. 函数名称:MPU_IIC_Init()* [+ ]! q; n+ b. G# }  O4 l
  30. 函数功能:MPU_IIC管脚初始化配置5 j& Z7 N4 V8 U. |+ y
  31. 入口参数:无. l* |) m% i- \9 B1 b# D
  32. 返回参数:无
    9 u( f: ~) E0 Y( i" Z  w
  33. 修改作者:Aaron. H# j  v2 z. B- p, B
  34. **********************************************************************/
    ) F2 H1 }; ~2 d$ I) ]' P2 q
  35. void MPU_IIC_Init(void)# i/ m% Z0 `& y/ B- W
  36. {         
    - W  g( k$ U9 F
  37.   GPIO_InitTypeDef  GPIO_InitStructure;
    1 B' P1 L2 e9 b) u( ^8 ^
  38.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);     // 使能外设IO PORTB时钟   
    2 \6 F: m! K1 B& o
  39.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;   // 端口配置,管脚10和管脚11
    " t0 r% X2 [( @1 W, {% U& f# {
  40.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         // 推挽输出& j9 I1 \* e0 v* x& O
  41.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        // IO口速度为50MHz
    0 `! H6 Z( n+ b+ b/ n5 T
  42.   GPIO_Init(GPIOB, &GPIO_InitStructure);            ) W' h6 m$ l* F/ L9 x$ G5 P4 D- o
  43.   GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);             // PB10(SCL),PB11(SDA) 输出高
    4 P/ V9 z( b" h
  44. }. {. h4 N0 ^( y5 r; I0 d/ O0 U
  45. /*********************************************************************7 c* Y' S" w9 G, w; B; U+ p& p0 g
  46. 函数名称:MPU_IIC_Start()
    , K$ h& l2 J6 ~3 H) u( s
  47. 函数功能:MPU_IIC起始信号
    + J# {! T) t3 l& \
  48. 入口参数:无+ e% t; }8 U5 T3 [2 y
  49. 返回参数:无
    : b5 E$ F# n6 t/ e
  50. 修改作者:Aaron
    ' W; O- _' r2 r  e
  51. **********************************************************************/
    9 B2 D/ H* \5 s6 J
  52. void MPU_IIC_Start(void)) F8 ]8 Y6 \; ~! l/ b" U
  53. {" C# o2 M/ s: `* {  W# p: r
  54. MPU_SDA_OUT();      // SDA线输出模式3 c( c/ H1 V* f4 N# i0 M
  55. MPU_IIC_SDA=1;      // SDA输出高
    . o$ ?. f$ j4 Y3 ]- t+ H) |: z
  56. MPU_IIC_SCL=1;      // SCL输出高,此时为空闲状态/ ~, K3 b3 J  B9 y
  57. MPU_IIC_Delay();    // 延迟 2 us5 b3 A' j+ B. ]
  58. MPU_IIC_SDA=0;      // 在SCL输出高的状态下,SDA由高至低跳变,IIC开始
    : E; A+ ]0 ?9 M7 U
  59. MPU_IIC_Delay();    // 延迟 2 us
    * @3 u1 A9 T: E5 I3 z& h5 X
  60. MPU_IIC_SCL=0;      // 钳住I2C总线,准备发送或接收数据
    ) Y- k: c" ?0 a. {! A1 N
  61. }  
    9 e. \/ n/ n' {  e/ \0 B
  62. /*********************************************************************
    * O4 W  Z5 G) H9 x  E3 ], t
  63. 函数名称:MPU_IIC_Stop()
    0 ^  R. B1 K" }
  64. 函数功能:MPU_IIC停止信号
    + h) C( t6 c' W3 U9 h6 e; L( |
  65. 入口参数:无
    , U; @8 S+ j/ q  o
  66. 返回参数:无
    ; s3 o5 ?+ o3 d1 c4 Q
  67. 修改作者:Aaron
    5 i% \" K4 d$ ]) ]
  68. **********************************************************************// W8 W8 a) [" N( Y" w; N
  69. void MPU_IIC_Stop(void)
    ) V, ~' t) E/ S3 y- P" K" q
  70. {
    3 d9 R4 @$ e" e" p8 P
  71. MPU_SDA_OUT();      // SDA线输出模式9 u' a; t# r7 Z0 V
  72. MPU_IIC_SCL=0;      // SCL输出低" X( a1 Z8 \) o" P, v4 ], P& k5 F
  73. MPU_IIC_SDA=0;      // SDA输出低  c1 c8 k# d6 L3 c! a% l8 V) R
  74. MPU_IIC_Delay();    // 延迟 2 us# o  J2 _* ^0 F
  75. MPU_IIC_SCL=1;      // 先SCL输出高,在SCL输出高的状态下,SDA一直是低电平# s/ U4 _& _/ _" c5 d
  76. MPU_IIC_SDA=1;      // SDA输出高,发送I2C总线结束信号
    1 d# g! y; Y0 S+ a; @
  77. MPU_IIC_Delay();    // 延迟 2 us        1 h2 k! b) ], J  f7 @1 w: g3 Z
  78. }
    1 k$ W( m1 D9 |6 ^
  79. /*********************************************************************3 m" J) B0 w( @4 ~( a+ a: e
  80. 函数名称:u8 MPU_IIC_Wait_Ack()3 a+ W' p8 G7 S# y/ f$ n+ U
  81. 函数功能:等待应答信号到来# M! n9 i0 y" B: W, B
  82. 入口参数:无; Z9 W: Y  f- Z, h9 B6 |6 x4 k
  83. 返回参数:u8,1,接收应答失败,0,接收应答成功( [9 [# [7 g1 L8 t6 J3 S+ a
  84. 修改作者:Aaron
    3 n  |0 P% t( @( H
  85. **********************************************************************/
    $ V6 r1 N+ P  w- @! C# J
  86. u8 MPU_IIC_Wait_Ack(void)% i" O2 ^0 `3 N( a/ w( K  ]$ \
  87. {, @, P2 y1 k( S2 `. v9 o, b# G
  88. u8 ucErrTime=0;# Y) v0 p+ j; g' |) b
  89. MPU_SDA_IN();         // SDA设置为输入  , c+ c7 o; A; s
  90. MPU_IIC_SDA=1;        // SDA设高电平
    2 G: O3 S# V* o3 E
  91. MPU_IIC_Delay();      // 延迟 2 us
    ) v" Z  g0 Z" c" Y7 Z4 w
  92. MPU_IIC_SCL=1;        // SCL设高电平
    9 L7 _; \2 y9 X6 y& ^8 u
  93. MPU_IIC_Delay();      // 延迟 2 us + k8 _; L! M9 E1 I5 |# p' h
  94. while(MPU_READ_SDA)   // 读取PB11的值,一直读PB11=1,高电平,则不断循环,直到溢出; l) K! M/ t) b3 r
  95. {, f2 e) f% D1 n% S; @7 y
  96.   ucErrTime++;
    , _5 X, Z' H$ y8 @/ v
  97.   if(ucErrTime>250)- @- ^9 E# E5 D7 j
  98.   {
    3 t% B0 I% \5 }$ U! [* [! X6 T
  99.    MPU_IIC_Stop();
    , w3 e7 `( z4 ?6 o9 S
  100.    return 1;
    , y1 r6 n  W( T* ]
  101.   }
    1 S! x; }. [4 b+ D/ Y
  102. }4 ?4 [9 `+ ]) E" H: l
  103. MPU_IIC_SCL=0;        // SCL设低电平     5 {# R, x% @/ D" W( x
  104. return 0;  + A+ {# z: ~8 r
  105. }
    + t2 w5 A' `2 l0 ]
  106. /*********************************************************************
    7 R4 k( o, o/ x1 j+ b* s9 D/ s
  107. 函数名称:MPU_IIC_Ack()* d3 n- K4 a6 x% P! f# P2 @( {" L
  108. 函数功能:产生ACK应答
    + h# m' {) S! L2 G
  109. 入口参数:无* u7 R# Q) f% e3 E5 _
  110. 返回参数:无0 ?; A$ N, E% n, {4 q7 \* H& u4 T4 q
  111. 修改作者:Aaron
    & X! ]: K: a. o: a0 G* k& o
  112. **********************************************************************/
    1 M: }4 ~5 |; V+ `' |
  113. void MPU_IIC_Ack(void)# S! R0 m; y% P5 |
  114. {( l) v" s! ^2 X2 `4 {5 S4 k  w
  115. MPU_IIC_SCL=0;       // SCL设低电平
    0 M9 {6 y# e9 E5 b/ y% s* y
  116. MPU_SDA_OUT();       // SDA输出模式
    / `6 t( e5 W  A' ~  ?
  117. MPU_IIC_SDA=0;       // SDA设低电平
    % K6 i9 c5 Q9 T- _) g
  118. MPU_IIC_Delay();     // 延时 2 us5 O4 A1 e; A# d- u8 O. _
  119. MPU_IIC_SCL=1;       // SCL设高电平
    4 B  ?: Z& O1 K, [# P* }1 u
  120. MPU_IIC_Delay();     // 延时 2 us
    / a: `2 `0 N) g
  121. MPU_IIC_SCL=0;       // SCL设第电平,在SCL高电平期间,SDA为低电平,则说明有效应答) o# K8 R9 L5 z/ k( c" C
  122. }
    6 V1 O; a) v) V( D& {1 O
  123. /*********************************************************************; o6 j( o4 e; c& E
  124. 函数名称:MPU_IIC_NAck()
    & O  X, m% h- n% u% G9 g  M
  125. 函数功能:不产生ACK应答
    6 `. P# e8 v- r5 Y* Y6 @/ _
  126. 入口参数:无
    & h8 t$ {4 g% g, E' S
  127. 返回参数:无
    / x; n& t$ ]/ K9 C0 }' @0 `. q
  128. 修改作者:Aaron' S" b2 n0 K3 o  D3 P
  129. **********************************************************************/
    ) j$ [, Q0 S! N7 F: h! R& p
  130. void MPU_IIC_NAck(void)
    0 |4 x0 ?. o! a( R1 j
  131. {
    7 v( [) @6 w/ c, B5 j  u
  132. MPU_IIC_SCL=0;       // SCL设低电平- F; Z  f; d$ j9 x- u; V7 x9 F  W
  133. MPU_SDA_OUT();       // SDA输出模式
    . X" U8 I0 z; K1 d
  134. MPU_IIC_SDA=1;       // SDA设高电平6 R8 x+ x+ |- Y6 M3 r
  135. MPU_IIC_Delay();     // 延时 2 us
    3 y7 ]- C6 Y0 @* H( @  P
  136. MPU_IIC_SCL=1;       // SCL设高电平
    % D  w$ J$ G9 r. v' @7 K1 p9 z
  137. MPU_IIC_Delay();     // 延时 2 us
    ) Z8 ~: G3 Z2 b+ }' N9 p
  138. MPU_IIC_SCL=0;       // SCL设低电平,在SCL高电平期间,SDA为高电平,则说明无效应答
    6 h% h5 W- f& d; y, J" F. r
  139. }
    / b& x' E8 Y% i
  140. /*********************************************************************
    3 w7 M8 Z8 t4 m7 V
  141. 函数名称:MPU_IIC_Send_Byte(u8 txd)' ]' R% p/ p9 z9 h$ P
  142. 函数功能:IIC发送一个字节
    . x) i8 y9 p- p/ g( x
  143. 入口参数:u8 txd* R* n' V' f  H) |. J
  144. 返回参数:无7 ~% b! e0 W+ c' \3 D" M. P$ K' ^
  145. 修改作者:Aaron* t1 h1 H7 ]( o0 ~6 e
  146. **********************************************************************/
    9 U' D7 j( a9 Y3 ^& u) [1 A
  147. void MPU_IIC_Send_Byte(u8 txd)
    & [6 J% T% ]' G" z- ]
  148. {                        
    . W" Z( s% K2 e; g
  149. u8 t;   % }/ P+ Z6 C2 q0 k% ]
  150. MPU_SDA_OUT();       // SDA输出模式 ! ~7 R' |. s) w3 X
  151. MPU_IIC_SCL=0;       // SCL设低电平,此时可改变SDA,以实现数据的有效传输
    , j- j( x. ?, u& J
  152. for(t=0;t<8;t++)     // 发送一个字节,即8个bit
    1 A/ T& Z1 D( V2 N& q
  153. {              
    1 Y* w  G! A4 e/ w
  154.   MPU_IIC_SDA=(txd&0x80)>>7;  // 获取u8 txd的最高位(0或1),并右移7位,将最高位值给MPU_IIC_SDA+ b, k8 ^; ^# ]* l+ ~
  155.   txd<<=1;    ' O1 K- C  X& `; V2 S- q: I- F
  156.   MPU_IIC_SCL=1;              // SCL设高电平
    6 c' U: d8 s- z1 l! V
  157.   MPU_IIC_Delay();            // 延时 2 us
    0 O( H2 o2 o0 ^; U4 u6 d
  158.   MPU_IIC_SCL=0;              // SCL设低电平,传输SDA完成9 D5 j& I  ^$ [3 Q
  159.   MPU_IIC_Delay();            // 延时 2us
    2 e) s4 {9 l; n' i; |8 c7 G' s
  160. }  ! k1 O/ j; Z, b! T  J
  161. }   i: `! Q6 U# S/ X; U3 S' z( A
  162. /*********************************************************************
    * W1 I5 F3 U1 e# x; u
  163. 函数名称:u8 MPU_IIC_Read_Byte(unsigned char ack)3 U6 x3 k. l( l
  164. 函数功能:IIC读取一个字节,ack=1时,发送ACK,ack=0,发送nACK ( A# [1 v& n9 e6 o* ~( W" `% s
  165. 入口参数:ack5 {5 u3 L0 y/ ^5 [2 h- C
  166. 返回参数:u8,
    2 B" D! }5 @7 I' j+ m) Z
  167. 修改作者:Aaron# E; U8 w& R- a0 R% v2 F
  168. **********************************************************************/
    . g! B0 v6 G$ B1 p. k
  169. u8 MPU_IIC_Read_Byte(unsigned char ack)
    3 K- D2 y' V9 Y' R) b+ v( s* I, u
  170. {
    * ~( @$ K* o# K7 h
  171. unsigned char i,receive=0;1 {. {6 d  j8 g$ u4 R( p
  172. MPU_SDA_IN();                 // SDA设置为输入模式
    6 `$ {% C7 E- i  ]) E' O/ h5 m: D
  173. for(i=0;i<8;i++ )             // 读取一个字节,即8个bit4 b. I; |  U* o* d
  174. {
    0 o* x+ |5 Q' @; g. E! _( c! E
  175.   MPU_IIC_SCL=0;               // SCL设为低电平
    0 R2 ?- G6 R& f- e2 @5 T
  176.   MPU_IIC_Delay();             // 延时 2us
    , R. s% A1 z3 I
  177.   MPU_IIC_SCL=1;               // SCL设为高电平
    # r6 |  P* M7 H9 G& l+ v
  178.   receive<<=1;
    - s& N" D* a" y6 |
  179.   if(MPU_READ_SDA)             // 如果读取的SDA为1,则receive最低值+1,若读取的SDA为0,则receive最低值不变,即0
      Y8 t: }' \( I$ I# K0 {
  180.    receive++;   ' X8 Q# u4 X% p& l/ P
  181.   MPU_IIC_Delay();             // 延时 2us. R7 g8 S8 F! e* z! _+ R0 c
  182. }      , z* M6 _% `" ]* X" G4 X& i( O2 l
  183. if (!ack)
    2 ?' k+ N+ C( h* V
  184.   MPU_IIC_NAck();              // 发送nACK
    / E' m! E; j6 ~4 V
  185. else
    & I2 _; ]9 ^8 S/ f1 J
  186.   MPU_IIC_Ack();               // 发送ACK   
    4 L, H9 Z7 [6 o6 N2 \" O' \6 o  W) p
  187. return receive;* _* h/ }$ }! n/ U" u! N
  188. }, n1 F' i+ Y& Y9 y: M8 p
  189. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码

; z  g! J7 G" _10.3 mp6050.h头文件函数4 T8 l2 _. b# r, G! J( }: T4 D
代码中标记“初学”的说明是前面寄存器介绍时讲到的。4 ?& i0 n6 R/ j/ y* k5 ^5 f/ A
5 v) v& E5 a- U' Q
  1. /**( ^; F' M6 a4 L) H2 L9 b3 g1 v
  2. ********************************  STM32F10x  *********************************2 F0 O! w) v; {1 C9 L2 S8 m  G
  3. * @文件名称: mpu6050.h
    4 ]1 ]+ P! @  s
  4. * @修改作者: Aaron7 y- l" E: _, n$ g
  5. * @库版本号: V3.5.0
    : c- L/ M  c0 S  C' l
  6. * @工程版本: V1.0.0
    2 f/ K# J2 o6 b* Q2 Q! k' k0 q
  7. * @开发日期: 2020年11月30日9 q! Z+ _1 e1 n0 S( v
  8. * @摘要简述: mpu6050头文件& x; K- m0 k3 l: m# D
  9. ******************************************************************************/% i. h# D/ b, n- A  ^
  10. /*-----------------------------------------------------------------------------
    ! l: i1 z" W# O, `# r
  11. * @更新日志:
    - v# i3 y5 a5 k3 ]
  12. * @无, A2 g3 _8 R+ U# [
  13. * ---------------------------------------------------------------------------*/- I2 Y! x! d" `6 o
  14. #ifndef __MPU6050_H
    6 b- |4 T- ^  S
  15. #define __MPU6050_H6 n' |. L+ i1 {  {8 B" e7 [
  16. /* 包含的头文件 --------------------------------------------------------------*/
    2 ^: K: l" [  u- T/ r" q
  17. #include "mpuiic.h"   
    , z- D* H3 P! `5 u; |3 N  P4 v$ G+ E0 m
  18. /* 位操作控制PA15,对应MPU6050 AD0的高低电平 ----------------------------------*/
    ( [& e' U2 P/ e  T4 T  y" f
  19. #define MPU_AD0_CTRL   PAout(15) // 控制AD0电平,从而控制MPU-6050地址
    4 x2 |3 A# w8 K# q1 l# T7 L
  20. /* MPU6050 寄存器ID定义 ------------------------------------------------------*/3 t, E+ h3 ~3 j
  21. // #define MPU_ACCEL_OFFS_REG 0X06 // accel_offs寄存器,可读取版本号,寄存器手册未提到
    1 n9 c. V# A, L! K
  22. // #define MPU_PROD_ID_REG    0X0C // prod id寄存器,在寄存器手册未提到0 q( [4 f6 l( z# R/ D
  23. #define MPU_SELF_TESTX_REG    0X0D // 自检寄存器X ACC和G
    " ~7 b7 Y, g, ?, X
  24. #define MPU_SELF_TESTY_REG    0X0E // 自检寄存器Y ACC和G
    3 a% c9 q6 }0 H, X% b# N7 g, `/ [
  25. #define MPU_SELF_TESTZ_REG    0X0F // 自检寄存器Z ACC和G
    $ M1 l% }# _: P; v: O( ~6 n0 X- g  j
  26. #define MPU_SELF_TESTA_REG    0X10 // 自检寄存器X,Y,Z only ACC1 a, I' ?: {$ n: g' `6 g5 }
  27. #define MPU_SAMPLE_RATE_REG   0X19 // 陀螺仪采样频率分频器    **初学**
    1 v* v9 p( L2 J6 _' }- B
  28. #define MPU_CFG_REG           0X1A // 配置寄存器              **初学**$ S8 w+ c/ r: k% p# Y; L
  29. #define MPU_GYRO_CFG_REG      0X1B // 陀螺仪配置寄存器        **初学**
    3 O# F2 C" N- S  p. V6 }
  30. #define MPU_ACCEL_CFG_REG     0X1C // 加速度计配置寄存器      **初学**0 N2 g1 t- g5 p3 R
  31. #define MPU_MOTION_DET_REG    0X1F // 运动检测阀值设置寄存器
    6 l- [/ L) H5 j% z+ `" o- q* ~
  32. #define MPU_FIFO_EN_REG       0X23 // FIFO使能寄存器          **初学**7 R1 `; R- d& W4 C8 ~( U
  33. #define MPU_I2CMST_CTRL_REG   0X24 // IIC主机控制寄存器
    * n7 b! L& ]. o  z: z! @- w
  34. #define MPU_I2CSLV0_ADDR_REG  0X25 // IIC从机0器件地址寄存器' P. z7 {# F8 ?1 T3 J
  35. #define MPU_I2CSLV0_REG       0X26 // IIC从机0数据地址寄存器
    0 Y3 l2 b6 A0 k8 v7 n
  36. #define MPU_I2CSLV0_CTRL_REG  0X27 // IIC从机0控制寄存器
    $ i2 b& @2 u, Z, w* U
  37. #define MPU_I2CSLV1_ADDR_REG  0X28 // IIC从机1器件地址寄存器) V. k5 ?1 t8 ~" f6 f
  38. #define MPU_I2CSLV1_REG       0X29 // IIC从机1数据地址寄存器
    * M, m3 d% ^+ D
  39. #define MPU_I2CSLV1_CTRL_REG  0X2A // IIC从机1控制寄存器
    / E. ^& s# l% f: Z  b
  40. #define MPU_I2CSLV2_ADDR_REG  0X2B // IIC从机2器件地址寄存器
    / O& D3 Z9 s* W* U- T8 T1 g
  41. #define MPU_I2CSLV2_REG       0X2C // IIC从机2数据地址寄存器
    ) M( ?7 y2 }) Y
  42. #define MPU_I2CSLV2_CTRL_REG  0X2D // IIC从机2控制寄存器
    , z, `/ M# d+ B6 F9 N: \7 L  H
  43. #define MPU_I2CSLV3_ADDR_REG  0X2E // IIC从机3器件地址寄存器' j( ?# U4 E& V7 ]2 C! v  b
  44. #define MPU_I2CSLV3_REG       0X2F // IIC从机3数据地址寄存器& c5 g* {8 F. v4 e
  45. #define MPU_I2CSLV3_CTRL_REG  0X30 // IIC从机3控制寄存器
    % K3 |0 L* O5 s* s! R8 q& `
  46. #define MPU_I2CSLV4_ADDR_REG  0X31 // IIC从机4器件地址寄存器
    $ `# Z2 k4 I5 Q! ~! U% _
  47. #define MPU_I2CSLV4_REG       0X32 // IIC从机4数据地址寄存器' I3 {1 ?" D& {2 f
  48. #define MPU_I2CSLV4_DO_REG    0X33 // IIC从机4写数据寄存器- a$ }- n4 A: |0 H% V
  49. #define MPU_I2CSLV4_CTRL_REG  0X34 // IIC从机4控制寄存器
    - o: M; I1 p% K% [
  50. #define MPU_I2CSLV4_DI_REG    0X35 // IIC从机4读数据寄存器0 p& O; V1 v$ Y; |
  51. #define MPU_I2CMST_STA_REG    0X36 // IIC主机状态寄存器* A4 {( ?. \7 [/ A. n
  52. #define MPU_INTBP_CFG_REG     0X37 // 中断/旁路设置寄存器  ?: t0 @3 b1 h. z! ~' Z7 j; ]/ J
  53. #define MPU_INT_EN_REG        0X38 // 中断使能寄存器
    + t+ y( |! r$ J% x6 r
  54. #define MPU_INT_STA_REG       0X3A // 中断状态寄存器
    + }6 i4 `" R2 r$ f" V" \
  55. #define MPU_ACCEL_XOUTH_REG   0X3B // 加速度值,X轴高8位寄存器  **初学**! ^4 G/ \2 k; _
  56. #define MPU_ACCEL_XOUTL_REG   0X3C // 加速度值,X轴低8位寄存器  **初学**/ I; K( C) {& z
  57. #define MPU_ACCEL_YOUTH_REG   0X3D // 加速度值,Y轴高8位寄存器  **初学**' ]+ H) u, |: ]& w/ e2 \
  58. #define MPU_ACCEL_YOUTL_REG   0X3E // 加速度值,Y轴低8位寄存器  **初学**
    8 [" ]; w7 e! P3 ~8 S& |7 x1 J
  59. #define MPU_ACCEL_ZOUTH_REG   0X3F // 加速度值,Z轴高8位寄存器  **初学**0 a- b: Q5 B' P3 p
  60. #define MPU_ACCEL_ZOUTL_REG   0X40 // 加速度值,Z轴低8位寄存器  **初学**/ L- s# i8 H3 {- a8 K) E  I" P
  61. #define MPU_TEMP_OUTH_REG     0X41 // 温度值高八位寄存器    **初学**
    / I0 V- Z! R' e0 T
  62. #define MPU_TEMP_OUTL_REG     0X42 // 温度值低八位寄存器    **初学**8 C3 I6 X( v$ ~3 z# k: w
  63. #define MPU_GYRO_XOUTH_REG    0X43 // 陀螺仪值,X轴高8位寄存器 **初学**
    3 v% |2 L. u( d9 G+ n, h( J
  64. #define MPU_GYRO_XOUTL_REG    0X44 // 陀螺仪值,X轴低8位寄存器 **初学**8 a6 ]% _' L0 H
  65. #define MPU_GYRO_YOUTH_REG    0X45 // 陀螺仪值,Y轴高8位寄存器 **初学**! z7 l+ i) ^5 R' ]( ~
  66. #define MPU_GYRO_YOUTL_REG    0X46 // 陀螺仪值,Y轴低8位寄存器 **初学**
    + e( ?1 U# M$ j" u( z
  67. #define MPU_GYRO_ZOUTH_REG    0X47 // 陀螺仪值,Z轴高8位寄存器 **初学**
    6 c+ w5 R5 V8 Z
  68. #define MPU_GYRO_ZOUTL_REG    0X48 // 陀螺仪值,Z轴低8位寄存器 **初学**
    ! [7 Z' M% [' H+ V% h! I! w
  69. #define MPU_I2CSLV0_DO_REG    0X63 // IIC从机0数据寄存器
    9 u% u9 a: f; r+ H; l" U
  70. #define MPU_I2CSLV1_DO_REG    0X64 // IIC从机1数据寄存器. }- H* v4 j3 ?# x
  71. #define MPU_I2CSLV2_DO_REG    0X65 // IIC从机2数据寄存器
    - w& m$ m8 j8 }
  72. #define MPU_I2CSLV3_DO_REG    0X66 // IIC从机3数据寄存器
    4 z% O4 D: P9 O$ F: R, E
  73. #define MPU_I2CMST_DELAY_REG  0X67 // IIC主机延时管理寄存器5 X2 B- w2 O/ ?: U! Y# m6 B
  74. #define MPU_SIGPATH_RST_REG   0X68 // 信号通道复位寄存器
    ) f' @2 }& L& y# B# Q. S# H
  75. #define MPU_MDETECT_CTRL_REG  0X69 // 运动检测控制寄存器- @3 g0 X2 j0 Z' g* _+ `* S$ X  y
  76. #define MPU_USER_CTRL_REG     0X6A // 用户控制寄存器
    & `0 p% a' Z# @1 C
  77. #define MPU_PWR_MGMT1_REG     0X6B // 电源管理寄存器1      **初学**0 j+ _2 D/ o1 W! y& |
  78. #define MPU_PWR_MGMT2_REG     0X6C // 电源管理寄存器2      **初学**
    0 C; |8 c1 s: p4 R8 W+ Z
  79. #define MPU_FIFO_CNTH_REG     0X72 // FIFO计数寄存器高八位2 r$ t# G' _, u/ ]7 ^  t
  80. #define MPU_FIFO_CNTL_REG     0X73 // FIFO计数寄存器低八位
    : j% A" m9 n9 @
  81. #define MPU_FIFO_RW_REG       0X74 // FIFO读写寄存器1 x. ?7 ~- O# g2 u
  82. #define MPU_DEVICE_ID_REG     0X75 // 器件ID寄存器$ \/ s  F6 r8 g+ Y- C
  83. // 备注:如果AD0脚(9脚)接地,0,IIC地址为0X68(不包含最低位);1 o  I- H% B1 W" p
  84. // 如果接V3.3,则IIC地址为0X69(不包含最低位),
    ) }: F: @* \6 G) N) |
  85. // 本开发板由PA15管脚控制,另PA15为低电平 $ ^) \$ `; X4 t9 M2 ?+ `
  86. #define MPU_ADDR       0X68" O9 f0 m5 \5 p& \7 b
  87. /* 函数申明 -----------------------------------------------------*/; O: t0 g# r! c. w: A3 y+ m$ g
  88. u8 MPU_Init(void);                                 // 初始化MPU6050
    7 \, M/ b- X3 Y. f( S
  89. u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf);   // IIC连续写
    0 \  o2 r& i% G* K/ q/ Q
  90. u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf);    // IIC连续读 ( [5 ?, R( |0 a
  91. u8 MPU_Write_Byte(u8 reg,u8 data);                 // IIC写一个字节
    : T0 S! F2 a) [. N( q& C
  92. u8 MPU_Read_Byte(u8 reg);                          // IIC读一个字节8 e, o- q  }& [/ |" t, J
  93. u8 MPU_Set_Gyro_Fsr(u8 fsr);5 }; }; F1 E* F: J+ D/ {
  94. u8 MPU_Set_Accel_Fsr(u8 fsr);& V9 i( ^! K6 o! P# N' ]
  95. u8 MPU_Set_LPF(u16 lpf);; V8 G5 H! y, u& m4 x$ {
  96. u8 MPU_Set_Rate(u16 rate);3 H; L4 E4 o: T% f! [" ?  s
  97. u8 MPU_Set_Fifo(u8 sens);
    ) G; A* c% N9 j" ^9 o5 m/ t9 @
  98. short MPU_Get_Temperature(void);
    # }  R3 d7 G" O+ X
  99. u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz);4 O8 z2 I# t0 v& V
  100. u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az);0 f2 n3 `# R& D# D9 S
  101. #endif /* __MPU6050_H */
    + b% b1 }! T  x3 _2 n& a
  102. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码

( b" [* g7 s  Z$ b10.4 mpu6050.c源文件函数" Y7 `$ }9 T% x4 I. u2 K4 f

  r7 d+ `% x4 |/ u1 Y
  1. /*** x( {3 P8 t5 c/ D
  2. ********************************  STM32F10x  *********************************
    3 R5 @/ n6 C) m
  3. * @文件名称: mpu6050.c
    2 N$ R- v9 n2 b' j
  4. * @修改作者: Aaron
    2 c5 ^  j4 J' b* E! L
  5. * @库版本号: V3.5.0
    % j) D3 _9 w2 w6 S# i' J3 e
  6. * @工程版本: V1.0.0
    " y+ X) R# s! F+ I8 v, j# L
  7. * @开发日期: 2020年11月30日
    0 }3 ]5 g* J3 L
  8. * @摘要简述: mpu6050源文件8 a6 b8 j9 B0 A& L) L
  9. ******************************************************************************/
    / k& V: _. g6 X% F
  10. /*-----------------------------------------------------------------------------
    " }' ^" R, ?4 d5 c+ I5 s: X8 U8 B5 G
  11. * @更新日志:
    % P7 Z9 C/ U% W
  12. * @无
    ( [- T8 \  X* B( ?9 {
  13. * ---------------------------------------------------------------------------*/
    + O/ J  ^/ r1 U% D8 L" p$ _
  14. /* 包含的头文件 --------------------------------------------------------------*/0 @) c: O" `. j, |0 g
  15. #include "mpu6050.h"  ^3 a5 d% V! M- a9 `
  16. #include "delay.h"# V  O8 E4 P4 H& c1 E% l$ |
  17. /*********************************************************************% \  x, ^5 N4 X$ [
  18. 函数名称:u8 MPU_Init()4 ]1 d) W3 {% @* e- B' G
  19. 函数功能:初始化MPU60506 B- r3 R; {/ W
  20. 入口参数:无
    # W3 A; B: o% H' d0 o, G2 Z0 b, c
  21. 返回参数:0,成功,1失败
    3 z$ X) V" B1 [1 t
  22. 修改作者:Aaron( h- ^1 L. B0 Q
  23. **********************************************************************/
    * q: E( Z# H9 k7 e
  24. u8 MPU_Init(void)
    , O4 h! @( I( ^" Y. a, C$ ^& G
  25. { $ X/ ?+ @8 Y  b9 }
  26. u8 res;( j! w6 D0 {1 u( `7 O! }
  27. GPIO_InitTypeDef  GPIO_InitStructure;
    : K: x& d$ @+ Q, H% @" s8 r; ?1 u
  28. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);      // 使能AFIO时钟
    % k: G* \& p) j9 H" W/ y
  29. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);     // 使能外设IO PORTA时钟  & Q8 P) i+ ^% \" J
  30. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;               // 管脚15! u% v' a6 |& H' s7 u* ~
  31. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         // 推挽输出5 t: h8 s" Q- j! _/ _# V3 r
  32. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        // IO口速度为50MHz
    8 B. `; `: U1 w) ]1 N7 s  ?7 }
  33. GPIO_Init(GPIOA, &GPIO_InitStructure);                   // 根据设定参数初始化PA15,对应MPU-6050芯片的AD0地址管脚% K& D$ w1 S* A& L: z
  34. GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);  // 禁止JTAG,从而PA15可以做普通IO使用,否则PA15不能做普通IO!!!1 X4 n/ M( u0 m; \( p
  35. MPU_AD0_CTRL=0;                                          // 控制MPU6050的AD0脚为低电平,则从机地址为:0X685 ]7 T( m1 ~$ Z  c
  36. MPU_IIC_Init();                                          // 初始化IIC总线
    , q$ q, I8 V% {1 x: u2 h; D
  37. MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);                  // 对电源管理寄存器1输入0x80,复位MPU6050( T7 s; c$ P' {
  38. delay_ms(100);, B4 v( b( C& ?+ J. [: I" h6 I$ l
  39. MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);                  // 对电源管理寄存器1输入0x00,主要令[6]位设0,正常工作模式,即唤醒MPU6050 ! F' n* r! I2 _( ?& x- Q* f
  40. MPU_Set_Gyro_Fsr(3);                                     // 设置陀螺仪传感器满量程范围,±2000dps
    8 T8 Q2 \/ d  `8 s1 [
  41. MPU_Set_Accel_Fsr(0);                                    // 设置加速度传感器满量程范围,±2g* i9 b  w+ F6 o5 n: _
  42. MPU_Set_Rate(50);                                        // 设置采样率50Hz! X# l* F. ^) N% B2 H! {7 a
  43. MPU_Write_Byte(MPU_INT_EN_REG,0X00);                     // 对中断使能寄存器输入0x00,关闭所有中断/ i* j: Y4 b! Q4 f; S' n
  44. MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);                  // 对用户控制寄存器输入0x00,I2C主模式关闭2 W: ?0 Y. ^$ p, T! h! b* N
  45. MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);                    // 对FIFO使能寄存器输入0x00,关闭FIFO3 v# q  H% f. y2 `- N
  46. MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80);                  // 中断/旁路设置寄存器输入0x80,INT引脚低电平有效# \& g$ N( v" J1 W+ F* {0 d( ?6 {, O
  47. res=MPU_Read_Byte(MPU_DEVICE_ID_REG);                    // 读取器件ID寄存器值,传至res里) U% r* c, Q9 g+ u9 r$ Z
  48. if(res==MPU_ADDR)                                        // 如果res=0x68,则器件ID正确
    ' }" F3 i4 p! Q6 _. E, v& n
  49. {' r$ Q& l3 P3 G- x2 M  G  p# a5 X
  50.   MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);                 // 对电源管理寄存器1输入0x01,设置CLKSEL,001,PLL X轴为参考. ?& e3 j0 o! A* ~1 c0 b! v
  51.   MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);                 // 对电源管理寄存器2输入0x00,加速度与陀螺仪都工作(都不待机)
    1 H" h6 z, z' s
  52.   MPU_Set_Rate(50);                                       // 设置采样率为50Hz
    0 y8 x1 ~! N- t- _
  53.   }
    2 Q9 r$ W; m7 U* M
  54. else $ W3 P' ~- m2 N* T
  55.   return 1;
    ) U0 |4 Y2 |+ S
  56. return 0;
    & [8 W6 g1 a5 i. x( @
  57. }
    ! t8 S$ S' z! D( V
  58. /*********************************************************************
    ' a( L2 I0 y3 `! |* Z
  59. 函数名称:u8 MPU_Set_Gyro_Fsr(u8 fsr)
    + R' u( r) r) Y7 {& p
  60. 函数功能:设置MPU6050陀螺仪传感器满量程范围' P- p, K& w4 m& D: Z  a* E
  61. 入口参数:u8 fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
    3 m/ ]& x( h: l  f( Z% @
  62. 返回参数:0,成功,1失败; @$ Q( P& X% I: k$ r' b4 a
  63. 修改作者:Aaron  g: T! R) r+ E! d# g* e
  64. **********************************************************************/
    6 _, z3 j3 S7 m( E
  65. u8 MPU_Set_Gyro_Fsr(u8 fsr)2 A& ^! N7 k- g" `( k) D
  66. {
    4 e! a6 }3 c: f2 I: T
  67. return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);  // 设置陀螺仪满量程范围为±2000dps  : ]9 y! }# i) Q0 Z& G
  68. }
    2 A8 y4 n. K! {
  69. /*********************************************************************; j* k% j4 G. q2 j/ o, y/ z4 t9 _
  70. 函数名称:u8 MPU_Set_Accel_Fsr(u8 fsr)
    " P9 S' i2 E* ?' ~% `- u4 d$ t
  71. 函数功能:设置MPU6050加速度传感器满量程范围7 O% ?, }' P  h" T
  72. 入口参数:fsr:0,±2g;1,±4g;2,±8g;3,±16g3 k/ e1 t. k9 z0 a$ m
  73. 返回参数:0,成功,1失败
    + O4 A8 h4 q* w% ~0 c
  74. 修改作者:Aaron
    ) g" L! Q7 p0 ^. v% d+ ~
  75. **********************************************************************/2 E" U5 D& x4 _9 R* \
  76. u8 MPU_Set_Accel_Fsr(u8 fsr)
    & z7 L& T, T% R3 X/ _+ ?
  77. {
    5 G3 k; D$ R" F
  78. return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3); // 设置加速度传感器满量程范围为±2g  1 k/ |8 T. K; ]/ u
  79. }
    $ D+ A) r' [3 q" S' t8 h
  80. /*********************************************************************+ E/ Z! B1 b# G5 F
  81. 函数名称:u8 MPU_Set_LPF(u16 lpf)
    9 ]) R4 [: Q( v/ q5 c% y
  82. 函数功能:设置MPU6050的数字低通滤波器7 w2 r& q% o' s# U+ x/ t
  83. 入口参数:lpf:数字低通滤波频率(Hz)
    " k- G, K2 G3 A0 X$ H% b) _: X0 {
  84. 返回参数:0,成功,1失败
    & d8 G7 m9 l' v
  85. 修改作者:Aaron
    0 i6 @, X3 A. ?# O
  86. **********************************************************************/
    % e. ?% }0 j9 @& E2 J; d8 @/ V" e+ }
  87. u8 MPU_Set_LPF(u16 lpf)) _$ E( }5 P* e2 {/ H' j: W, N& h
  88. {$ z. |- M. K" M8 Z3 r
  89. u8 data=0;6 M; A) r* D7 A" L% h. b0 T0 u2 X
  90. if(lpf>=188)                                // 如果lpf≥188Hz,则data=1
    5 b2 r, u! \: |" X" B+ S
  91.   data=1;4 T+ f/ I* Y  O; c4 s
  92. else if(lpf>=98)* v- C+ c! R! u4 F. y+ [
  93.   data=2;
    2 p! h" K, }/ _! b# {! n
  94. else if(lpf>=42)8 B4 V! C# B% o$ G1 ]. p
  95.   data=3;
    # W4 g# b2 Q2 h  }3 y6 k$ n% F
  96. else if(lpf>=20)
    3 \0 Y6 }, [; ]
  97.   data=4;/ v0 o7 |0 S6 {# z- \8 [* t9 e1 n
  98. else if(lpf>=10)+ i8 I( a* Q( b. y* d" R: L7 w+ y
  99.   data=5;1 P& u) ?, s+ y
  100. else
    - B& L0 `" t3 r1 m! t8 m' h' b
  101.   data=6;
    + C0 T- w" x! F+ K! \
  102. return MPU_Write_Byte(MPU_CFG_REG,data);    // 设置数字低通滤波器  - m& x( X# s% r' Q3 S, I* p
  103. }
    2 P, |3 t6 @+ b+ v' P3 R) @
  104. 8 W- `* _  m) X& M, a9 K& b4 O
  105. /*********************************************************************  U% l( B3 {3 O$ M
  106. 函数名称:u8 MPU_Set_Rate(u16 rate)& I; a2 K& K2 R: @* F6 r2 m
  107. 函数功能:设置MPU6050的陀螺仪采样率(只在陀螺仪输出频率Fs=1KHz时成立). h$ V3 O8 Z/ |! x1 ^
  108. 入口参数:rate:4~1000(Hz),陀螺仪采样频率7 s. w; i) i# i+ F' X, W; ~# B
  109. 返回参数:0,成功,1失败
    " _2 a$ R1 L4 `' |5 I
  110. 修改作者:Aaron
    : S( Y' C& L6 c8 w
  111. **********************************************************************/
    5 Q# g" j; k! F$ Q4 v( I
  112. u8 MPU_Set_Rate(u16 rate)
      e+ Z: V- {* v1 n
  113. {
    & Z. Q' o5 O' D+ Y' P) C
  114. u8 data;
    ; ?0 Z" I0 s1 [% h
  115. if(rate>1000)
    7 D% Y: |, o/ x- V' r
  116.   rate=1000;) ~9 a7 U8 d* C* C3 s
  117. if(rate<4)9 J- `0 N+ B/ w2 J1 `/ k
  118.   rate=4;
    / f# q: C! D; F% t+ z
  119. data=1000/rate-1;) Y  `/ t# ]  M- o4 y7 h) ]
  120. data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data);
    : M: q. h' Q" Y0 v
  121.   return MPU_Set_LPF(rate/2);                // 自动设置LPF为采样率的一半, X! R$ j6 W1 D, [# R% v' n0 f
  122. }9 F7 R" k& q8 q4 ]$ T5 T* P8 A* b
  123. /*********************************************************************8 h/ g/ y" M7 g- A
  124. 函数名称:short MPU_Get_Temperature()
    # i- R! u* Q" R+ |2 g0 h; o
  125. 函数功能:得到温度值2 `; u- S1 Q3 g" b7 V
  126. 入口参数:rate:4~1000(Hz),陀螺仪采样频率
    ; D# g" N1 ~( u
  127. 返回参数:温度值(扩大了100倍)
    ) f* E$ E5 n+ p- z
  128. 修改作者:Aaron
      o9 u6 m5 F7 }( g7 w# `
  129. **********************************************************************/! ]0 s$ `0 @% s$ [% y: H! C
  130. short MPU_Get_Temperature(void)9 a" g* g1 Y& @4 z  v& t5 \
  131. {6 n" ^) c9 E. Y4 Y- j
  132. u8 buf[2];
    . Z8 }$ J$ j" ]9 p6 b8 ]
  133. short raw;
    7 S/ _, S; ^- a
  134. float temp;# o7 q# R7 Q& }$ Y# j
  135. MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); // addr:器件地址;reg:寄存器地址;len:写入长度;buf:数据区
    $ c% x. b# G$ @4 s( \8 f
  136. raw=((u16)buf[0]<<8)|buf[1];  7 |1 Q$ g- n$ E- {' P3 ^$ K
  137. temp=36.53+((double)raw)/340;  
    ' }! t2 @" T2 L0 K1 u! t, M6 k
  138. return $ ?( g& t+ M  |4 C
  139.   temp*100;;( a/ G$ r( |* t3 y
  140. }
    ' L, k; r/ {6 w& Z  `
  141. /*********************************************************************
    1 w  n5 Y% `( m
  142. 函数名称:u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
    , J" |- h7 p' B* }$ u0 v6 u
  143. 函数功能:得到陀螺仪值(原始值)
    # c7 n. M6 t* L0 e- x5 S1 @' i
  144. 入口参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
    $ d& h, H$ O5 j# k0 z$ W- y- h
  145. 返回参数:u8 0成功,1失败
    ! j( R  ?" D5 @4 k1 i/ O
  146. 修改作者:Aaron
    & ?+ t+ n, `( ?4 X! c5 ]& J
  147. **********************************************************************/
    7 N; H! W! b3 A: I$ A
  148. u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz): h6 V9 ]! s# Z
  149. {
    2 q  H! h3 m3 g# O2 q* Q
  150. u8 buf[6],res;  
    & `8 X  Z2 l: U4 z
  151. res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
    0 |7 m$ A/ ?* u) Q
  152. if(res==0)  A% b% X! C  z& ]. S9 f
  153. {
    1 x8 D) J- p  R( r& }! M- X, @9 b. ~
  154.   *gx=((u16)buf[0]<<8)|buf[1];  ! I) t5 i) }' Z  s8 u
  155.   *gy=((u16)buf[2]<<8)|buf[3];  2 q' l, p2 m4 _+ c
  156.   *gz=((u16)buf[4]<<8)|buf[5];
    1 w2 O6 E. z( n: k' G: m
  157. }  
    + t+ e9 ~& S+ t3 N& G# a
  158. return res;;
    % ?; e) O4 v2 M5 E) k5 g7 ]8 |
  159. }
    0 l5 m  i9 M* {- \3 s7 f
  160. /*********************************************************************' h6 J# s2 P" g! Q) ~  ~6 c
  161. 函数名称:u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
    5 i" i2 M1 }. M$ @% j5 X# D
  162. 函数功能:得到加速度值(原始值)
    ) t8 L8 n; \" ]; N& V
  163. 入口参数:gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
    / A: K8 D8 b6 p/ V( G
  164. 返回参数:u8 0成功,1失败7 C1 \# l6 W2 C/ t
  165. 修改作者:Aaron
      ^9 Y: x, w, w& F6 P
  166. **********************************************************************/% x' [7 ^3 y# K4 J
  167. u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
    2 G5 o; v3 h6 n% w/ G% P5 T
  168. {* d6 V# m- }: q% ]& K0 Y9 h0 J* |
  169. u8 buf[6],res;  
    8 Y( P  A  h" M9 {$ ?5 |" g6 ^+ b
  170. res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);% u, n2 }0 x3 g* x! p( j
  171. if(res==0)
    5 i/ ]8 `* o. g3 M  X
  172. {
    2 {7 D- ]2 ?4 Q3 Q2 H9 e# T3 Q
  173.   *ax=((u16)buf[0]<<8)|buf[1];  
    / O3 k( U: j" N; J! U6 u
  174.   *ay=((u16)buf[2]<<8)|buf[3];  
    + Y/ U' ?% N0 ^
  175.   *az=((u16)buf[4]<<8)|buf[5];$ B3 w: b8 e9 B$ k  Y6 T9 ~
  176. }  
    , N$ @8 }. X% a
  177. return res;;1 w; V( G5 t3 m" P
  178. }8 p9 u0 W6 f7 X! Y
  179. /*********************************************************************
    , J# |' B. q& Q& j+ z
  180. 函数名称:u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
    4 \. R4 z( _' \3 ~
  181. 函数功能:向MPU6050连续写入数据
    5 ~! ?; t+ X3 T+ U# {" h
  182. 入口参数:addr:器件地址;reg:寄存器地址;len:写入长度;buf:数据区
    ) Z3 G& @9 b  l" K  ^, A8 g
  183. 返回参数:u8 0成功,1失败
    : r( i: X* h! H8 e% p6 W$ ^; g+ [
  184. 修改作者:Aaron
    6 o. `0 [  u3 @6 ^' P) s' z0 g1 O
  185. **********************************************************************/! n% J$ i+ U( ]& L# _- f; G4 b$ U
  186. u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
    ; Q% L1 e+ E: }  n/ s2 Q5 M
  187. {
    9 Y" {) q2 n" s$ H+ |' B
  188. u8 i;
    & `3 D: ]/ f  y( {
  189. MPU_IIC_Start();
    3 u9 S; w5 ]* g
  190. MPU_IIC_Send_Byte((addr<<1)|0);   // 发送器件地址+写命令
    & c3 D6 L3 y! N, w  s
  191. if(MPU_IIC_Wait_Ack())               // 等待应答
    : V8 u& m5 ]4 ^8 d* Y" o/ i
  192. {! _% G7 o6 D" \) Q/ }
  193.   MPU_IIC_Stop();   
    % m9 y6 X  x, \8 C+ \
  194.   return 1;  
    - D  z/ Q7 a4 ^7 h7 X, \$ C
  195. }, L) J3 }# B0 y5 x6 N* V  L
  196. MPU_IIC_Send_Byte(reg);              // 写寄存器地址
    , e4 g; S0 O3 n5 x% C2 ^* P
  197. MPU_IIC_Wait_Ack();              // 等待应答
    " }' J/ ?2 [+ S% T0 }/ i# f
  198. for(i=0;i<len;i++)% I) I# [7 l  x# @* `
  199. {/ z4 D3 J: N( _$ a4 C7 h) r) e
  200.   MPU_IIC_Send_Byte(buf);      // 发送数据
    # T) a5 m' t6 \% I# B
  201.   if(MPU_IIC_Wait_Ack())          // 等待应答" J% x! N( ~. B) h$ Z$ n
  202.   {
    5 D2 S3 w- f  Z5 x9 E1 z7 R
  203.    MPU_IIC_Stop();  7 Q4 i' {( C& m! x
  204.    return 1;   
      K  i4 [9 h2 t/ N' j0 {0 P9 s! W, ^
  205.   }  
    1 i3 a+ N  |, Q+ j/ @) a
  206. }    7 {/ @* D* a. E. s7 c& S' K
  207. MPU_IIC_Stop();  
    : B. \: }& H1 n" A( i
  208. return 0;
    + f. q& R. K; a  A# V! T
  209. }
    9 E+ v1 ~4 Y  W7 y0 s, ]
  210. /*********************************************************************1 ~- }" D/ ]+ S
  211. 函数名称:u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)8 F+ P  [0 w/ I9 M
  212. 函数功能:从MPU6050连续读数据! [3 n1 X, r) X  |  c" {% ?
  213. 入口参数:addr:器件地址;reg:要读取的寄存器地址;len:要读取的长度;buf:读取到的数据存储区
    . {) A/ y% U( X) j5 o
  214. 返回参数:u8 0正常,1错误% M1 {- Q" }" ^& m4 [3 o
  215. 修改作者:Aaron; ]/ K9 V3 A7 |) V# T. B
  216. **********************************************************************/
    + `% q7 B, F: T0 @# V8 C
  217. u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
      p! G$ s! X, X. H: X8 T
  218. { / \  O/ s: L. {4 X- x5 p
  219. MPU_IIC_Start(); 2 l2 O- d7 P& z9 J! c7 J3 T: C
  220. MPU_IIC_Send_Byte((addr<<1)|0);    // 发送器件地址+写命令 : m4 T- @2 @4 b! y+ J
  221. if(MPU_IIC_Wait_Ack())             // 等待应答
    - G$ A; l, p9 S$ ^1 p
  222. {
    , \. r) a  o7 `* q4 V6 j
  223.   MPU_IIC_Stop();   
    1 b1 C; e/ m/ T1 s
  224.   return 1;  
    / A  L3 I: a( e3 Q! ?6 b+ V) a
  225. }2 |8 F& C- ?! P: M; o1 N) W
  226. MPU_IIC_Send_Byte(reg);            // 写寄存器地址6 O( l- G7 A. w4 M1 W$ J2 Y' d' o
  227. MPU_IIC_Wait_Ack();                // 等待应答4 ^% z$ C2 d- P( x" T" m6 d5 j  J( [; g
  228. MPU_IIC_Start();
    % \9 ~' D' A) J: Q: h
  229. MPU_IIC_Send_Byte((addr<<1)|1);    // 发送器件地址+读命令
    2 V* I4 R) [! d; f* ?
  230. MPU_IIC_Wait_Ack();                // 等待应答
    1 N, T: P7 m+ N
  231. while(len). V4 ~& m$ X' J) p" G
  232. {7 p  e9 a6 z. J3 i, \
  233.   if(len==1)*buf=MPU_IIC_Read_Byte(0); // 读数据,发送nACK
    ' ]! V! w$ ]+ W4 c6 [4 r
  234.   else *buf=MPU_IIC_Read_Byte(1);      // 读数据,发送ACK  
    / w$ Z" G5 s$ C5 ^3 ~
  235.   len--;
    . |; b0 W  j1 |6 ?9 B& a' j; O
  236.   buf++;
    ! r' P2 T& `* B! r5 b! z
  237. }    + ~" _' h" k% K, @. m
  238.     MPU_IIC_Stop();  // 产生一个停止条件 " \% C7 L: }; k  e
  239. return 0; 1 M3 m- n" \3 Q# |0 |& y
  240. }, W4 `, _3 j) V$ }; E+ B& G% l
  241. /*********************************************************************0 q% o4 K  r7 C6 R& ?/ i
  242. 函数名称:u8 MPU_Write_Byte(u8 reg,u8 data)
    9 z/ ]4 `( ]. t; g* i% n9 B+ x
  243. 函数功能:向MPU6050写一个字节 2 C7 N  R9 s! h1 s+ K1 u
  244. 入口参数:reg:寄存器地址;data:数据5 t& T7 m( E3 r. w! ~  N9 b
  245. 返回参数:0,正常;1,失败7 W( ]; I1 f. k! B: z4 x( I
  246. 修改作者:Aaron- q6 E4 Y# C# v9 T" P
  247. **********************************************************************/* T! I, p  C  r. o0 z! R/ P- j
  248. u8 MPU_Write_Byte(u8 reg,u8 data)      7 I3 Q* S5 }0 ], {
  249. { 3 L5 r1 B. N$ E0 N6 c
  250. MPU_IIC_Start(); ( {9 _1 X8 p7 R
  251. MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);  // 发送器件地址+写命令
    ' R- r7 i6 N( g( c8 J8 W/ W6 V
  252. if(MPU_IIC_Wait_Ack())                     // 等待应答,0接收应答成功,1接收应答失败
    $ W, l) E, D, s7 R5 B4 [% s0 z5 R
  253. {8 \+ ]  o* Q$ }6 `
  254.   MPU_IIC_Stop();                             // MPU_IIC停止信号% K! I7 Z& `% b3 s& y6 O  V7 q
  255.   return 1;  
    + h+ _  _3 L" H& ?2 ~
  256. }
    2 R2 I$ p! J/ e! ]+ p
  257. MPU_IIC_Send_Byte(reg);              // 写寄存器地址0 K; T/ {( ?8 B
  258. MPU_IIC_Wait_Ack();                  // 等待应答 $ `+ z7 `9 ~* T( [) i; @
  259. MPU_IIC_Send_Byte(data);             // 发送数据! G4 C. y! b! i/ x. e
  260. if(MPU_IIC_Wait_Ack())               // 等待应答- A$ a, G, j, m) l% Y( ^
  261. {1 v$ n$ H2 s( o& x' R* u8 P( b
  262.   MPU_IIC_Stop();  
    $ d$ {, z# H) q4 b) z9 X# h
  263.   return 1;     @/ q) N1 @1 {/ T
  264. }   
    5 E6 A7 E5 b' c! x0 J& w  O
  265.     MPU_IIC_Stop();  
    0 d$ z5 ]1 K) q( L5 }
  266. return 0;
    9 ^5 Q/ |& L# z+ d4 Y% I0 }
  267. }
    8 N2 ]( Q% J* x9 m; Q% E
  268. /*********************************************************************
    * K1 e( U7 h, N8 A
  269. 函数名称:u8 MPU_Read_Byte(u8 reg)2 U" q" A* {+ F$ v7 F4 C. X
  270. 函数功能:从MPU6050读一个字节
    $ _) a; Q7 u6 e  t& J7 |
  271. 入口参数:reg:寄存器地址
    * g8 ?, e/ g6 C* H& W. s$ g; K
  272. 返回参数:u8 读到的数据
    / t$ h# Z6 C. {. G' H4 P7 ^
  273. 修改作者:Aaron
    * Q4 f5 x( h" Y' _% P$ d, ]# m
  274. **********************************************************************/& O+ e( N0 _: \+ t; z2 x
  275. u8 MPU_Read_Byte(u8 reg)2 G6 d8 h# E$ v  z8 O( I
  276. {
    ' ?' `& E5 x4 o2 D$ B3 L
  277. u8 res;6 A- b7 U( g2 }. Y: _0 H: D6 f
  278. MPU_IIC_Start(); & D+ M- h$ F1 c7 l) \
  279. // 开始标志(S)发出后,主设备会传送一个 7 位的 Slave 地址,并且后面跟着一个第 8 位,称为 Read/Write 位。 0写,1读。# s, `1 a2 w4 P
  280. MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);   // 发送器件地址+写命令
    - c' ?! v1 a; E- x6 z
  281. MPU_IIC_Wait_Ack();                           // 等待应答
    1 S+ s% g. O- l1 {2 T+ W# x6 }
  282. MPU_IIC_Send_Byte(reg);                         // 写入要读取字节的寄存器首地址
    7 _0 w. F5 i- O, y4 k) Q" P2 S
  283. MPU_IIC_Wait_Ack();                          // 等待应答
    5 N  ~  e/ ~* X% y7 w
  284. MPU_IIC_Start();, R  l8 L0 K* ?" _) h3 @
  285. MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);   // 发送器件地址+读命令 2 ?  z' \. Z/ _
  286. MPU_IIC_Wait_Ack();                           // 等待应答
    ; H9 P: [8 @2 n0 ]# B  l
  287. res=MPU_IIC_Read_Byte(0);                        // 读取一个字节的数据,发送nACK
    , n8 _. C# G3 m. u3 H4 g* u
  288. MPU_IIC_Stop();                                    // 产生一个停止条件 5 k) O. |- |% f) M+ [5 L7 G: o' n
  289. return res;  
    6 A9 N/ B8 d" U. b6 n
  290. }
    " O. z" T/ p" M
  291. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码

# t" B; N8 ?: n' t2 d" b10.5 main.c主函数5 `3 x9 w; ]6 P' Z

5 P0 R! U/ p6 }- d$ a3 G- U6 S
  1. /**
    1 X1 m& _3 u3 u+ ?+ h- I
  2. ********************************  STM32F10x  *********************************
    8 B  q* F- l8 H7 _$ J
  3. * @文件名称: main.c
    ; K2 p6 J2 n* p" C. g0 O
  4. * @修改作者: Aaron
    1 w; J9 Y6 O4 G% b* S9 p8 J' ?5 E
  5. * @库版本号: V3.5.03 W. b0 p. d4 v# W& ~& {
  6. * @工程版本: V1.0.0
    % u8 T" J0 w% C6 p1 z
  7. * @开发日期: 2020年11月30日
    2 E7 i: |7 O1 p% Z9 E8 ~
  8. * @摘要简述: 主函数,增加了在LCD显示6轴的原始数据' G1 L6 z5 G. A/ `% o6 I1 S: m
  9. ******************************************************************************/
    . f) L7 y, W/ L8 t) S9 H) W& ]
  10. /*-----------------------------------------------------------------------------/ x- Y) U$ G% J! q
  11. * @更新日志:! H2 f6 n/ w7 }7 h0 f8 r9 Z
  12. * @无
    ! z' P& m6 g: }  \
  13. * ---------------------------------------------------------------------------*/7 Z1 u: y( v) J- x# U1 }; Y& q
  14. /* 包含的头文件 --------------------------------------------------------------*// `! P" W3 ^1 M4 r. [) w: X2 i
  15. #include "led.h"
    . F$ Q2 B! a( b2 d' o
  16. #include "delay.h"2 Z$ }1 g$ i/ K+ i8 B& C% O9 f' F
  17. #include "key.h"; w" ^) |9 h  }0 v
  18. #include "sys.h"$ }5 a" n+ l( x
  19. #include "lcd.h"; j. y/ p# v# g# r
  20. #include "serial_communication.h"
    2 ^5 L6 N9 w3 Y, V
  21. #include "mpu6050.h". O2 i4 [3 j2 P5 E2 B2 |# x( U
  22. #include "inv_mpu.h"
    2 c; l5 B' X) q+ P* @7 o& L$ z; u
  23. #include "inv_mpu_dmp_motion_driver.h"
    - \( G) E6 g5 L/ X2 p1 H
  24. /*********************************************************************
    ( c5 `, @5 f0 X, u1 U
  25. 函数名称:usart1_send_char(u8 c)
    4 J# R* o! H, r0 g' @
  26. 函数功能:串口1发送1个字符$ Z7 O/ g$ q$ y9 j0 e! K
  27. 入口参数:c:要发送的字符
    ) ~  c) E( }! x
  28. 返回参数:0,成功,1失败
    2 {' g3 t9 v! \9 D' S: ~% ]
  29. 修改作者:Aaron
    - k0 q1 s; K! Q6 ?3 Q! W
  30. **********************************************************************/
    ! V5 `8 A5 Q+ g/ z9 l
  31. void usart1_send_char(u8 c)5 e3 W( d6 F, r
  32. {           ! _  S1 T" P3 ?' c, c
  33.         while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); // 循环发送,直到发送完毕   6 w8 ^7 e! g0 w
  34.         USART_SendData(USART1,c);  3 ?4 H3 G. j7 x& {0 |7 g
  35. }
    - w7 E6 L: N+ U0 K! V" ?( z) B( Z
  36. /*********************************************************************
    : b# ?+ G( l5 l5 k) |
  37. 函数名称:usart1_niming_report(u8 fun,u8*data,u8 len)
    ( n9 V/ W8 G: x3 f2 [; x2 ^
  38. 函数功能:传送数据给匿名四轴上位机软件
    0 q+ c2 k$ T; q4 M9 U7 j9 s5 s
  39. 入口参数:fun:功能字.0XA0~0XAF;data:数据缓存区,最多28字节;len:data区有效数据个数
    . ^( j, S( F* m6 r3 _, j1 |0 H
  40. 返回参数:无6 c1 |' K& x& h: `9 t- v5 }
  41. 修改作者:Aaron. Z' @; r: ]7 Y# X1 v8 V: _  ]! i$ o
  42. **********************************************************************/2 O7 y& x& I. x( T1 U5 c
  43. void usart1_niming_report(u8 fun,u8*data,u8 len)& V7 R' m$ X" m- K; l
  44. {
    " ~: g" a% R. e4 `
  45.         u8 send_buf[32];" Y. M3 V8 k1 v$ n
  46.         u8 i;
    * h! [  @+ s% w" L
  47.         if(len>28)return;                // 最多28字节数据
    ) |% T# w' O* x  t, K( U- J, ]
  48.         send_buf[len+3]=0;                // 校验数置零
    / k7 j) }# K7 f0 x
  49.         send_buf[0]=0X88;                // 帧头# V4 X% F) ?3 l7 d+ t
  50.         send_buf[1]=fun;                // 功能字' t# U9 l2 M0 }& f- O; b: O. U) P
  51.         send_buf[2]=len;                // 数据长度: x3 S5 }% D$ G" m1 q, G
  52.         for(i=0;i<len;i++)send_buf[3+i]=data;                                                // 复制数据$ ~' C/ u( o$ q& ]! L
  53.         for(i=0;i<len+3;i++)send_buf[len+3]+=send_buf;                                // 计算校验和        
    : J; u9 K  y, U
  54.         for(i=0;i<len+4;i++)usart1_send_char(send_buf);                                // 发送数据到串口1
    : P8 E2 n/ P6 A# I' h
  55. }
    7 Z2 Y4 p$ ]3 D& b
  56. /*********************************************************************
    3 u% S4 c7 W9 o$ \4 A) w- q
  57. 函数名称:mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)6 y( ]- W+ L+ C, Z: _. h# k6 z
  58. 函数功能:发送加速度传感器数据和陀螺仪数据
    / S! }/ R- r* k
  59. 入口参数:aacx,aacy,aacz:x,y,z三个方向上面的加速度值;gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值
    0 ]6 t( }+ q: y# _
  60. 返回参数:无
    1 a4 X. |' ]2 a( X4 a
  61. 修改作者:Aaron& v" Q- i+ l4 \7 h9 l$ E+ W
  62. **********************************************************************/- D0 P( w" A( y5 d
  63. void mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)
    2 H, r& l2 @, K4 |
  64. {
    * h  z8 f" ]6 U& ?" ]* D" E
  65.         u8 tbuf[12]; 5 t4 F. P. p! }# ~; P: ^/ T
  66.         tbuf[0]=(aacx>>8)&0XFF;
    - f8 X3 b, @" \2 Z) V" L
  67.         tbuf[1]=aacx&0XFF;
    1 U# n# E  s* @
  68.         tbuf[2]=(aacy>>8)&0XFF;
    6 J" }$ x9 D; O2 b* h
  69.         tbuf[3]=aacy&0XFF;$ Z8 z; ~3 ]5 L; K  [  a. I4 }
  70.         tbuf[4]=(aacz>>8)&0XFF;% @5 I# u8 p+ i) r- f7 \  ~" x7 v
  71.         tbuf[5]=aacz&0XFF; : {- U) \* z9 I1 B( g
  72.         tbuf[6]=(gyrox>>8)&0XFF;0 H- z5 Y+ e4 Z" d. a7 q6 D
  73.         tbuf[7]=gyrox&0XFF;, V0 W" |6 u4 R  G# V! u
  74.         tbuf[8]=(gyroy>>8)&0XFF;* @% ?8 M0 l; g3 ?
  75.         tbuf[9]=gyroy&0XFF;6 z; ]& V; n7 p$ Z  {/ x
  76.         tbuf[10]=(gyroz>>8)&0XFF;
      P7 T/ ^: m8 B! m
  77.         tbuf[11]=gyroz&0XFF;" w5 U0 d  J, {* e
  78.         usart1_niming_report(0XA1,tbuf,12);                // 自定义帧,0XA1
    2 I& Q+ N. u% Y$ y
  79. }        4 g3 Q' {! e. i- E
  80. /*********************************************************************( p7 d3 V1 Y% G- S
  81. 函数名称:mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)0 C& ], q, i; F
  82. 函数功能:通过串口1上报结算后的姿态数据给电脑4 r* _0 j) _) ~4 q( z9 H
  83. 入口参数:aacx,aacy,aacz:x,y,z三个方向上面的加速度值;gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值;
    # a% a% M, T# m+ q
  84.                                         roll:横滚角.单位0.01度。 -18000 -> 18000 对应 -180.00  ->  180.00度;) F- x: W3 F' E7 k' |
  85.                                         pitch:俯仰角.单位 0.01度。-9000 - 9000 对应 -90.00 -> 90.00 度
    , G0 ^" a  w. `- J6 O; N# G
  86.                                         yaw:航向角.单位为0.1度 0 -> 3600  对应 0 -> 360.0度3 J( W9 C8 l1 r- @" ?8 T& c4 n
  87. 返回参数:无- ~9 ?) F* E; E5 Q
  88. 修改作者:Aaron
    6 K0 T& ]+ M' y/ T8 G$ d! g! a
  89. **********************************************************************/
    * T6 _2 e* k- O
  90. void usart1_report_imu(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz,short roll,short pitch,short yaw)2 L4 \1 I* g" c  d* T* Y
  91. {" N, [( u% N, T& E# W
  92.         u8 tbuf[28]; # g% ^2 q1 w# J/ }9 L
  93.         u8 i;8 L+ l/ {1 F4 w  _& k
  94.         for(i=0;i<28;i++)tbuf=0;                                        // 清00 e2 z( x. r# E; h
  95.         tbuf[0]=(aacx>>8)&0XFF;9 @: i6 V# Z$ v0 t9 o; L" U* @  x( O$ ]
  96.         tbuf[1]=aacx&0XFF;) e% J; o; T$ ?7 b, N
  97.         tbuf[2]=(aacy>>8)&0XFF;
    % `/ C  x! a# o& ^* N
  98.         tbuf[3]=aacy&0XFF;( O- m5 A$ k4 h4 |( h  ]2 D& B
  99.         tbuf[4]=(aacz>>8)&0XFF;* K9 g  \3 ?$ o/ u8 k4 L: q
  100.         tbuf[5]=aacz&0XFF; # g/ G. p9 o. y% n% e' {. E& ^
  101.         tbuf[6]=(gyrox>>8)&0XFF;
    ; G2 G( g( i) z" P, U9 ]* n. ^  T
  102.         tbuf[7]=gyrox&0XFF;6 B% \' B/ R2 B4 a# W+ W% q8 ~
  103.         tbuf[8]=(gyroy>>8)&0XFF;
    , g- F$ T% n8 |. {4 t- }0 J
  104.         tbuf[9]=gyroy&0XFF;
    & C1 F  j& A# X! p* h% F2 B! _( u
  105.         tbuf[10]=(gyroz>>8)&0XFF;
    ; S1 G, @/ ^( z* Z
  106.         tbuf[11]=gyroz&0XFF;        
    0 F% H; L! ]' P. L! Y
  107.         tbuf[18]=(roll>>8)&0XFF;( G  z% `5 J0 p+ b
  108.         tbuf[19]=roll&0XFF;
    8 ?# \" v; `7 d, z6 c7 H8 }
  109.         tbuf[20]=(pitch>>8)&0XFF;- M& K( _8 B% I) l! [$ X: ~: L0 S) u
  110.         tbuf[21]=pitch&0XFF;5 L. I- G; o- g2 j
  111.         tbuf[22]=(yaw>>8)&0XFF;- M( B9 l* O, f- n7 H
  112.         tbuf[23]=yaw&0XFF;
    * w* I4 Y7 J2 ^7 \" u; P8 S  T
  113.         usart1_niming_report(0XAF,tbuf,28); // 飞控显示帧,0XAF
    % v, g7 J+ T7 C" ^! p9 n
  114. }  
    ' {/ Y0 A: B% U! Z
  115. /*********************************************************************
    / g" D) ]+ K' w- K& z
  116. 函数名称:int main()
    2 Y8 J, e: [( m. _$ B! |# Q1 w
  117. 函数功能:主函数,增加了在LCD屏上显示6轴原始数据的功能8 ]( l- _. c, @7 a8 O4 a
  118. 入口参数:无  W# c4 d$ u& `" x
  119. 返回参数:无
    0 n" c0 z8 z& c9 }: h
  120. 修改作者:Aaron; d4 y% ]& {2 k+ q7 k, T
  121. **********************************************************************/# h$ j' F* ^9 b5 F$ L. z; w1 o8 w- _
  122. int main(void)& I" r4 Z8 N$ Z1 R0 [$ }" |4 |
  123. {         : r$ F7 }" o' W* }
  124.         u8 t=0,report=1;                                                // 默认开启上报,发给匿名四轴上位机软件6 X/ H- r9 A) P
  125.         u8 key;" y; s" }( f  b% @, {
  126.         float pitch,roll,yaw;                                         // 欧拉角
    6 b4 t8 ~: [* W; C
  127.         short aacx,aacy,aacz;                                        // 加速度传感器原始数据
    + N9 A$ m) [+ W- b* S( [! w5 g
  128.         short gyrox,gyroy,gyroz;                                // 陀螺仪原始数据5 K9 n- _- I9 m3 j2 i! ^# G, g) s
  129.         short temp;                                                                // 温度         ' P. x0 k7 u' B
  130.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                         // 设置NVIC中断分组2:2位抢占优先级,2位响应优先级1 A1 _1 j) ^3 J' h
  131.         My_USART1_Init();                                                                                  // 串口初始化为500000
    ' ]' W. w; c$ B1 ?4 v6 J# c
  132.         delay_init();                                                                                         // 延时初始化 9 L" ~) _- ~& q! H: o
  133.         LED_Init();                                                                                                   // 初始化与LED连接的硬件接口
    3 R! [6 z0 s0 G: t& x
  134.         KEY_Init();                                                                                                 // 初始化按键( Q7 C$ G8 H$ a' Z/ c/ z: Q
  135.         LCD_Init();                                                                                                    // 初始化LCD  1 f/ }+ `$ R! L! x+ S
  136.         MPU_Init();                                                                                                 // 初始化MPU6050
    9 e9 V4 T5 j5 y/ [
  137.          POINT_COLOR=RED;                                                                                 // 设置字体为红色         
    / Y6 a& u8 f7 V* e2 j( A
  138.         LCD_ShowString(30,70,200,16,16,"MPU6050 TEST");        
    % V  \5 |  ?/ _6 }( X% p5 w8 K
  139.         LCD_ShowString(30,90,200,16,16,"2020/11/30");
    " w, s- U5 a0 e* }, k
  140.         while(mpu_dmp_init())" D% B6 O! X( Y  t/ B4 K! F
  141.          {
    % G# |( P- y' ?( r! X' R
  142.                 LCD_ShowString(30,110,200,16,16,"MPU6050 Error");. W: W$ Y2 P! n2 G3 a- v
  143.                 delay_ms(200);* ~0 X* N2 j" W% Z" F% N
  144.                 LCD_Fill(30,110,239,130+16,WHITE);. k" }( K& I; {, c2 W+ d$ h
  145.                  delay_ms(200);
    ( ^3 f& c3 E, f6 C% K4 b( p9 \
  146.         }  
    * K$ p, j+ O5 W6 {' S2 Q
  147.         LCD_ShowString(30,110,200,16,16,"MPU6050 OK");& P$ V& H4 @& ~) Z  J' o9 A, M
  148.         LCD_ShowString(30,130,200,16,16,"KEY0:UPLOAD ON/OFF");5 C8 ]8 k, B4 |8 N/ ~, f6 e" k
  149.         POINT_COLOR=BLUE;                                                                                                                                 // 设置字体为蓝色
    4 M! m/ I0 B! ~( l, g- z
  150.          LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");         
    ! [' s4 U& U0 O. r4 d; t
  151.          LCD_ShowString(30,200,200,16,16," Temp:    . C");        1 Z/ o- l8 L1 S3 }
  152.          LCD_ShowString(30,220,200,16,16,"Pitch:    . C");        
    8 v6 {, g; R* _* z, \- A3 G
  153.          LCD_ShowString(30,240,200,16,16," Roll:    . C");         
    * \- P! E  q  K' f  t9 i+ H
  154.          LCD_ShowString(30,260,200,16,16," Yaw :    . C");         
    % S6 X% U4 E5 x2 ^- P! E
  155.          while(1)) \' s& w" u1 E& v/ E+ }
  156.         {2 X* v: z5 x; B
  157.                 key=KEY_Scan(0);- q1 {( h) v: L( _$ a) S. T3 F5 k
  158.                 if(key==KEY0_PRES)- X# S0 u3 S) B$ ?/ q$ @
  159.                 {
    / U6 _8 W1 \! \7 E( a& R* E4 c; _2 G" u
  160.                         report=!report;
    " t' m7 g* n6 y7 ^! t
  161.                         if(report)
    7 @$ N" O3 d, P3 N6 \
  162.                                 LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");
    . I; g" X9 `# E! C) @+ J
  163.                         else
    * W+ \8 H7 i2 c
  164.                                 LCD_ShowString(30,170,200,16,16,"UPLOAD OFF");' `/ t8 A- j3 g0 `, E' G8 L
  165.                 }
    2 P' Z' Q5 r5 l/ s. q
  166.                 if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
    5 N1 D" k# z1 d0 G' V& {5 N
  167.                 {
    2 ~& U7 e  x& y: l
  168.                         temp=MPU_Get_Temperature();                                                                        // 得到温度值                 & V6 Z* f6 Q: J& F
  169.                         MPU_Get_Accelerometer(&aacx,&aacy,&aacz);                                        // 得到加速度传感器数据6 C0 |5 Y9 O, c! g
  170.                         MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);                                        // 得到陀螺仪数据) j& Z) O* g* ^4 l4 f
  171.                         if(report)0 U/ A  k0 Z1 s6 b% {2 L2 K" ^3 L5 [, L
  172.                                 mpu6050_send_data(aacx,aacy,aacz,gyrox,gyroy,gyroz);        // 用自定义帧发送加速度和陀螺仪原始数据# k5 ]0 A! N" d/ h
  173.                         if(report)
    # w" n- Z5 \4 s4 |& d' i
  174.                                 usart1_report_imu(aacx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),(int)(pitch*100),(int)(yaw*10));
    2 T( z* X3 ]4 z$ A
  175.                         LCD_ShowString(30,300,200,16,16," aacx:    ");                                                                  ! X5 M( z: S9 m& s9 K# J5 v" M
  176.                         if(aacx<0)
    ; Q2 M, n& w; |& m2 q
  177.                         {) V0 J8 \# y2 v8 H
  178.                                 LCD_ShowChar(30+48,300,'-',16,0);                         // 显示负号6 G3 r1 B' |- ^, i+ S2 D
  179.                                 aacx=-aacx;                                                                        // 转为正数6 W& ^9 E% |# `0 a+ f% l
  180.                         }
    # \; w+ t' m6 ~- |
  181.                         else 1 S6 Y2 i7 t) o1 l
  182.                                 LCD_ShowChar(30+48,300,' ',16,0);                        // 去掉负号 6 W8 `9 N. k- E6 K6 M1 q+ F
  183.                         LCD_ShowNum(30+48+8,300,aacx,10,16);                        // 显示aacx                            & y. [! H3 {+ m' N" K; Y. @
  184.                         LCD_ShowString(30,320,200,16,16," aacy:    ");        ' L! n& q" @6 d! s# y
  185.                         if(aacy<0)
    8 N" E7 {: X! v( O
  186.                         {# C% o/ ~; o2 i; X# p/ H
  187.                                 LCD_ShowChar(30+48,320,'-',16,0);                          // 显示负号3 z2 Q2 c" A9 o7 K/ b- f* V# A0 P
  188.                                 aacy=-aacy;                                                                        // 转为正数
    8 Z( r( _- O* ~. C
  189.                         }
    ) U8 x, s* F) m9 g
  190.                         else 7 D4 b/ h$ g6 F
  191.                                 LCD_ShowChar(30+48,320,' ',16,0);                        // 去掉负号 2 M$ x& r$ C+ X+ h" @
  192.                         LCD_ShowNum(30+48+8,320,aacy,10,16);                        // 显示aacy            
    4 n; ~! f3 ^% d, b" Q5 Q
  193.                         LCD_ShowString(30,340,200,16,16," aacz:    ");         
    ' y9 ~% b0 N% v; @0 L( M4 ~
  194.                         if(aacz<0)
    ) Z. f6 B6 x$ V; Z. P: `
  195.                         {
    6 i, c* ~. f1 k$ p) @
  196.                                 LCD_ShowChar(30+48,340,'-',16,0);                          // 显示负号
    0 I! ?  q) r( ~7 ]0 K$ r* v
  197.                                 aacz=-aacz;                                                                        // 转为正数0 j4 L) K3 c% Q+ A
  198.                         }6 O2 d) }& V# w0 p
  199.                         else
    : V( D$ f2 o) Z. w; Y8 e
  200.                                 LCD_ShowChar(30+48,340,' ',16,0);                        // 去掉负号
    ; t/ s3 ?" X* G% R
  201.                         LCD_ShowNum(30+48+8,340,aacz,10,16);                        // 显示aacz           ) M! ~' J9 n; r
  202.                         LCD_ShowString(30,360,200,16,16,"gyrox:    ");        
    / w9 V6 q' o3 t; {/ F9 t+ p7 I& P
  203.                         if(gyrox<0). l1 S+ K* o. |: v
  204.                         {
    9 C  o5 X$ E1 o" E2 r+ g9 K
  205.                                 LCD_ShowChar(30+48,360,'-',16,0);                          // 显示负号+ @2 B& y; N  H
  206.                                 gyrox=-gyrox;                                                                // 转为正数3 |8 h) d* ^% r, \
  207.                         }
    . M3 U" c) l& m, E5 S. r# n
  208.                         else
    ( N) y- W  V% n0 d
  209.                                 LCD_ShowChar(30+48,360,' ',16,0);                        // 去掉负号
    : l4 I) o/ a# w3 Y) D' C
  210.                         LCD_ShowNum(30+48+8,360,gyrox,10,16);                        // 显示gyrox   
    / j6 u- t% G5 ^5 d
  211.                         LCD_ShowString(30,380,200,16,16,"gyroy:    ");        3 v* N8 H3 U6 @# o9 X. T
  212.                         if(gyroy<0)
    7 D  E) T1 f% x2 T
  213.                         {3 n3 ^% f; C& x& B) D  H7 M8 Z- r
  214.                                 LCD_ShowChar(30+48,380,'-',16,0);                          // 显示负号- t% v. N# Y- J. d
  215.                                 gyroy=-gyroy;                                                                // 转为正数2 P( q5 H* n. E6 V; h
  216.                         }& P7 A+ n. Y" p4 y6 ~
  217.                         else
    : G+ e/ r8 `2 p1 }! c
  218.                                 LCD_ShowChar(30+48,380,' ',16,0);                        // 去掉负号
    * Y8 }+ t7 ~- \+ z3 d9 k" \$ m
  219.                         LCD_ShowNum(30+48+8,380,gyroy,10,16);                        // 显示gyroy                   , A0 J3 p+ D+ v  d) I
  220.                         LCD_ShowString(30,400,200,16,16,"gyroz:    ");
    0 A; Y$ i" Y+ t, _1 z0 C
  221.                         if(gyroz<0)  N! U9 |# }+ N, A( H
  222.                         {
    , Y4 E' B2 Z0 Y: Q2 v% j9 s$ j
  223.                                 LCD_ShowChar(30+48,400,'-',16,0);                          // 显示负号( g$ Q6 b5 Q" f
  224.                                 gyroz=-gyroz;                                                                // 转为正数- W4 @4 W$ G' Z; [
  225.                         }
    / ~- \- B" t" u. s7 s
  226.                         else ! I6 v1 C9 W/ S! B9 v2 G9 ^
  227.                                 LCD_ShowChar(30+48,400,' ',16,0);                        // 去掉负号
    4 i3 i, w) u1 M% @: R+ d) N
  228.                         LCD_ShowNum(30+48+8,400,gyroz,10,16);                        // 显示gyroz                           * C% n/ S* j' Z2 f
  229.                         if((t%10)==0)
    3 @, ]8 C8 k; \+ \, Z$ J
  230.                         { % v4 p; O3 E) C3 ?+ `% B$ V
  231.                                 if(temp<0), b+ l( {) K; Q2 {
  232.                                 {8 Y( U+ X9 i! R+ H
  233.                                         LCD_ShowChar(30+48,200,'-',16,0);                // 显示负号/ ?7 r+ B" R$ W6 B
  234.                                         temp=-temp;                                                                // 转为正数2 x! W4 ?2 t7 g# \
  235.                                 }
    & T& H% @' I7 K* [% R
  236.                                 else
    ; `! V3 r( e0 f
  237.                                         LCD_ShowChar(30+48,200,' ',16,0);                // 去掉负号
    ; J" P1 y- i+ C1 N3 ^$ f& L+ L
  238.                                 LCD_ShowNum(30+48+8,200,temp/100,3,16);                // 显示整数部分            
    0 Q; z% b) K3 x$ ?) _4 }& j
  239.                                 LCD_ShowNum(30+48+40,200,temp%10,1,16);                // 显示小数部分
    . G5 M) {" s, o
  240.                                 temp=pitch*10;
    8 h! [9 D4 q! U9 D) |
  241.                                 if(temp<0)9 m1 Z* X- n" G' r" d
  242.                                 {; T' i5 k$ z9 U9 |+ q- l
  243.                                         LCD_ShowChar(30+48,220,'-',16,0);                // 显示负号) J# T* b/ i3 [
  244.                                         temp=-temp;                                                                // 转为正数
      }/ j2 [: z* J8 ~, s
  245.                                 }3 f' g+ C7 ?( j( F/ Q
  246.                                 else
    . K7 p5 M; F! w: o: r6 D, m
  247.                                         LCD_ShowChar(30+48,220,' ',16,0);                // 去掉负号
    . n( Y  |7 Q3 d5 }* F: K
  248.                                 LCD_ShowNum(30+48+8,220,temp/10,3,16);                // 显示整数部分            
    1 N5 ?$ U: a5 B7 E9 f- b2 U2 Y
  249.                                 LCD_ShowNum(30+48+40,220,temp%10,1,16);                // 显示小数部分
    2 E  ~0 n& ?% k( _$ p# Y
  250.                                 temp=roll*10;
    : x% N) c  {6 ^7 b* N
  251.                                 if(temp<0)/ y1 h2 q: a8 l  J8 B) ~" n. r! l
  252.                                 {" N: Z2 r, S% [# W  y& Y- W
  253.                                         LCD_ShowChar(30+48,240,'-',16,0);                // 显示负号! x+ g5 O; ^5 A# x. L
  254.                                         temp=-temp;                                                                // 转为正数6 T, w9 H- a* U( }% F. P
  255.                                 }
    5 R" _" |9 L4 \: ^# x
  256.                                 else
    8 I) j+ l, V* d+ r
  257.                                         LCD_ShowChar(30+48,240,' ',16,0);                // 去掉负号 8 x* ^! x0 Z! V# \3 q( j4 v
  258.                                 LCD_ShowNum(30+48+8,240,temp/10,3,16);                // 显示整数部分            
    9 i' w9 s. O4 P& U" j
  259.                                 LCD_ShowNum(30+48+40,240,temp%10,1,16);                // 显示小数部分
    $ ?; V. l4 W  x$ m$ Q2 U
  260.                                 temp=yaw*10;
    / @7 L6 I* i$ ?' s: K) j& L
  261.                                 printf("temp=%d\r\n",temp);& m# z3 h# Q; ?7 @, M8 r: B6 E
  262.                                 if(temp<0)
    - f; W% X2 Q; v9 R" v
  263.                                 {" j; v" s- N% g. a/ F
  264.                                         LCD_ShowChar(30+48,260,'-',16,0);                // 显示负号) r$ C" Z. x' e" }
  265.                                         temp=-temp;                                                                // 转为正数
    # V% F& m4 P, f9 R! P" [' v$ y
  266.                                 }
    ! }9 [/ I2 R# u/ M/ Y8 I, _: W
  267.                                 else
    6 `8 X* T' a1 K+ f7 D# O! _
  268.                                         LCD_ShowChar(30+48,260,' ',16,0);                // 去掉负号 * e8 R9 z" N  a, |% B
  269.                                 LCD_ShowNum(30+48+8,260,temp/10,3,16);                // 显示整数部分            3 {; ?2 t/ x; u" h" ^( i
  270.                                 LCD_ShowNum(30+48+40,260,temp%10,1,16);                // 显示小数部分  8 c( @# X- \* k2 z; }6 O8 D
  271.                                 t=0;
    4 K( n( n! `! N. |  [$ u& Q, s( Z. E
  272.                                 DS0=!DS0;                                                                        // LED闪烁
    ; C, o7 y; E- r/ Y3 h
  273.                         }# k  U7 f% G; d+ p% D1 w$ U# N
  274.                 }: c" u6 e( J, j; ]: u/ M4 w6 }
  275.                 t++;
    7 [- v* Q8 m, c7 r4 a. l: W
  276.         }         
    + b; u' h" T% N8 @/ u# {9 f
  277. }
    2 q$ e6 S( a& P7 }% s7 a
  278. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码

6 B( y5 S1 Z7 j$ y10.6 移植文件. ^+ H$ h/ ~# E* `+ [0 [
文件中代码太多,这里主要关注:
4 }6 c( ^% q" v# z- O1)inv_mpu.c源文件中定义了四个函数:8 K) Z3 M% v* I9 c8 S0 I  h
# r+ @: P# T1 B/ H
  1. #define i2c_write   MPU_Write_Len  // 对应mpu6050.c源文件里的MPU_Write_Len4 W( c) f" ^- H+ Q: \
  2. #define i2c_read    MPU_Read_Len   // 对应mpu6050.c源文件里的MPU_Read_Len: r2 {0 o8 K; Y0 ?3 ~
  3. #define delay_ms    delay_ms       // 对应delay.c源文件里的delay_ms4 ~# T, K1 a- B. |9 E5 V% `
  4. #define get_ms      mget_ms        // 这是一个空函数
复制代码
* f3 H9 d4 l) C) @" P) I! ]
2)inv_mpu.c源文件中u8 mpu_dmp_init()初始化函数:& P- l  b3 V- r6 a
8 P# G1 b- B, ]2 z
  1. u8 mpu_dmp_init(void)
    . s, K1 @- t  x! [
  2. {* J4 B7 I8 [. \1 D) a2 M
  3. u8 res=0;) K4 }3 D; v* |2 n
  4. MPU_IIC_Init();   // 初始化IIC总线
    ( W# b6 O7 I6 L+ m' f7 i
  5. if(mpu_init()==0) // 初始化MPU60509 ]- ~" }) b' w' ^' C: Y3 p
  6. {  ; E& z! l6 B" t5 r) k9 [
  7.   res=mpu_set_sensors(INV_XYZ_GYRO|INV_XYZ_ACCEL);     // 设置所需要的传感器# m1 X. G2 @, q5 i
  8.   if(res)return 1; " h0 ~0 ?4 ]! w& S0 T' `
  9.   res=mpu_configure_fifo(INV_XYZ_GYRO|INV_XYZ_ACCEL);  // 设置FIFO4 f1 h! J" U% K: V. `2 |9 V
  10.   if(res)return 2;
    ! I6 F4 U0 _$ F0 D9 n
  11.   res=mpu_set_sample_rate(DEFAULT_MPU_HZ);             // 设置采样率2 q' D8 s  o; k. T: T' R  c& r6 j( x
  12.   if(res)return 3;   J8 T- h9 c0 M
  13.   res=dmp_load_motion_driver_firmware();               // 加载dmp固件/ M4 O+ j& [& Y
  14.   if(res)return 4; 2 \4 @5 ]* m4 W0 |) }
  15.   res=dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation)); // 设置陀螺仪方向' h4 _1 N# W8 M8 V5 Z5 Z
  16.   if(res)return 5; * ?! g* S* p1 R5 C6 X5 d: {; C
  17.   res=dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT|DMP_FEATURE_TAP|               // 设置dmp功能
    ! |5 \+ H' c% [: X- k0 e2 x# r
  18.       DMP_FEATURE_ANDROID_ORIENT|DMP_FEATURE_SEND_RAW_ACCEL|DMP_FEATURE_SEND_CAL_GYRO|
    5 J, W* p# w: }/ d. Q
  19.       DMP_FEATURE_GYRO_CAL);
    + v$ l3 D  f: l9 ~- _/ a7 {& g3 H
  20.   if(res)return 6;
    $ }4 V7 m: P3 {* {" Z  G# `
  21.   res=dmp_set_fifo_rate(DEFAULT_MPU_HZ);  // 设置DMP输出速率(最大不超过200Hz)
    / L5 A6 S+ [( c
  22.   if(res)return 7;   . N% f/ o5 Y- ^% y6 p- \  x) ~8 E
  23.   res=run_self_test();                    // 自检( b6 i. J3 s0 d1 o
  24.   if(res)return 8;    . D: X7 Z' m4 O6 L: Q6 }& a7 E/ W! p
  25.   res=mpu_set_dmp_state(1);               // 使能DMP  y- y+ t6 w7 f, G+ N" Z9 o  q, r
  26.   if(res)return 9;     
    # X4 Q. M1 R6 Z: H
  27. }else return 10;
    0 m! @6 F4 p3 L+ @
  28. return 0;
    - W; z$ p# r, O6 ]& m
  29. }
复制代码

! ~4 @* n. A+ J/ o+ o/ ~3)inv_mpu.c源文件中u8 mpu_dmp_get_data(float *pitch,float *roll,float *yaw)获取欧拉角的函数:. L# d% r  x; A& q; `5 }
, D0 L  W& N  w; l5 H# u0 S( `
  1. u8 mpu_dmp_get_data(float *pitch,float *roll,float *yaw), s+ Q: f2 T& b  h* [% N, m
  2. {: q2 m% _8 j" b  Y' u
  3. float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;5 W8 e) J6 ~  B7 _4 z/ i% b( @, P
  4. unsigned long sensor_timestamp;
    * v1 z3 z: R) {. n+ o4 H6 h; \; t% S- _
  5. short gyro[3], accel[3], sensors;
    4 k0 h5 r- {0 i$ n- J
  6. unsigned char more;
    8 U* z- c3 j, K5 j) T0 M0 I$ a
  7. long quat[4]; & e4 T4 G- p# A4 A1 ]
  8. if(dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more))
      g7 V3 j1 l) \0 D9 H8 i* I
  9.    return 1;  : S& g8 F0 F7 E+ X% ?; d4 _. q
  10. ors&INV_WXYZ_QUAT)
    ; z5 s, h6 ^( [5 I8 ]+ A8 h$ U# W& [
  11. {& D6 G/ F6 w  Y/ ~3 d1 j9 i6 }
  12.   q0 = quat[0] / q30;    // q30格式转换为浮点数
    . t" n. [3 c% F+ M6 S
  13.   q1 = quat[1] / q30;
    ( H! I, Y: L3 R2 U: f' g9 Z
  14.   q2 = quat[2] / q30;& ?& G( k% s! c8 i) d, G" @
  15.   q3 = quat[3] / q30; ) _- P' p5 ^0 \- H/ G
  16.   // 计算得到俯仰角/横滚角/航向角
    ) t7 ^) |- X' T& x/ N0 A  Q1 q
  17.   *pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch
    : ~7 c8 c1 i  ~2 G( N
  18.   *roll  = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
    & W, o1 ^& R- ^* Y  B
  19.   *yaw   = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3; //yaw
    5 G! `+ N( G2 D% r+ o% ]
  20. }* A: n  ~# C, n# M/ g  ~1 s: L
  21. else ; _+ k3 y7 r, |6 j
  22.    return 2;
    7 _+ D* ^0 L$ s3 W9 L% P
  23. return 0;: `* k2 l) |8 X6 c
  24. }
复制代码

! g8 f! ^1 r' t6 H5 E# }十一、实验结果
% @' {  k# V7 i- Y/ j( U
该程序可用匿名四轴上位机软件实时查看6轴的原始数据和姿态数据,即欧拉角:航向角(yaw)、横滚角(roll)和俯仰角(pitch)。(这里就不放截图了)。
( {5 z0 d6 y1 Q% z! e另外在LCD屏上,也可实时查看6轴的原始数据和姿态数据,如下图:
8 t* h& M0 v' u& w6 a, N 20201204235655599.png
# T) {7 N4 x  v8 X9 g8 H
; f9 }  l0 D- V% X8 S————————————————: e6 N( J* B- C9 B- [4 w) L9 v7 C7 Y
版权声明:天亮继续睡
" I9 ^6 `# R5 H9 y2 V% n
' c" u- \- [; ?2 ~) ?, W. T( x
' z2 U/ E0 l. X% \5 Q  S# w# Z2 C/ v7 r+ [) r" v( a
收藏 评论0 发布时间:2022-11-18 19:00

举报

0个回答

所属标签

相似分享

官网相关资源

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