|
最近给朋友调试了STM32F407驱动VL53L0的激光测距,安装在机器人上的,遇到一些问题,这里发帖纪录一下。2 R: F$ v+ l, s f% U, X
关于VL53L0的资料和代码在正点原子那里都有,但是正点原子只是驱动了一路VL53L0,很多问题都需要我们自己解决,一路的VL53L0非常简单,随便参考一下例程就能完美解决,但是一旦涉及到多路设备,就会出现一堆问题,最突出最主要的就是多个VL53L0的地址设置,把握不住就会出现只有一路能正常使用的问题。
( i1 @6 s/ r7 z& E
, Y, z( R( J( \. ^6 | {' ^VL53L0X 简介
: @' i3 A. R0 D. g6 K) ~9 qVL53L0X 是 ST 公司推出的新一代 ToF 激光测距传感器,采用了第二代 FlightSenseTM技术,利用飞行时间(ToF)原理,通过光子的飞行来回时间与光速的计算,实现测距应用。较比上一代 VL6180X,新的器件将飞行时间测距长度扩展至 2 米,测量速度更快,能效更高。除此之外,为使集成度过程更加快捷方便, ST 公司为此也提供了 VL53L0X 软件 API(应用编程接口)以及完整的技术文档,通过主 IIC 接口,向应用端输出测距的数据,大大降低了开发难度。. X# O7 c- O2 ]. w* |
VL53L0X 特点包括:
; ~7 _3 C! j l, X" b2 Y①, 使用 940nm 无红光闪烁激光器,该频段的激光为不可见光,且不危害人眼。6 s& U8 p+ x9 o/ R. W
②,系统视野角度(FOV)可达 25 度,传感器的感测有效工作直径扩展到 90 厘米。) h3 E/ N( w( V: I% s( U$ y
③,采用脉冲式测距技术,避免相位式测距检测峰值的误差,利用了相位式检测中除波峰以外的光子。
- |) P k/ }1 N④,多种精度测量和工作模式的选择。+ ^. ^+ I8 l* z/ x
⑤,测距距离能扩至到 2 米。
: E: _9 {! x0 E⑥, 正常工作模式下功耗仅 20mW,待机功耗只有 5uA。
- O4 L. X7 {- D- [' j }% J⑦,高达 400Khz 的 IIC 通信接口。 @3 r, N7 V1 V& Z4 r4 G
⑧,超小的封装尺寸: 2.4mm × 4.4mm × 1mm。
6 h/ S- S% B( GVL53L0X 工作模式 p `' Q$ c; r1 E( `- }& F6 @
VL53L0X 传感器提供了 3 种测量模式, Single ranging(单次测量)、 Continuous ranging(连续测量)、以及 Timed ranging(定时测量),下面我们将简单介绍下:
0 O' N* t) C+ V7 G7 J# W& W(1) Single ranging(单次测量),在该模式下只触发执行一次测距测量,测量结束后,VL53L0X 传感器会返回待机状态,等待下一次触发。6 I0 `! F# Z6 @2 z% ~5 p
(2) Continuous ranging(连续测量),在该模式下会以连续的方式执行测距测量。一旦测量结束,下一次测量就会立即启动,用户必须停止测距才能返回到待机状态,最后的一次测量在停止前完成。
: n( n4 g5 L j0 j, B* p(3) Timed ranging(定时测量),在该模式下会以连续的方式执行测距测量。测量结束后,在用户定义的延迟时间之后,才会启动下一次测量。用户必须停止测距才能返回到待机状态,最后的一次测量在停机前完成。根据以上的测量模式, ST 官方提供了 4 种不同的精度模式,如表格所示: 
# P) O) Z1 Y9 @+ c6 \8 \7 M从表格可以看到,针对不同的精度模式,测量时间也是有所区别的,测量时间最快为高速模式,只需 20ms 内就可以采样一次,但精度确存在有±5%的误差范围。而在长距离精度模式下,测距距离能达到 2m,测量时间在 33ms 内,但测量时需在黑暗条件(无红外线)的环境下。所以在实际的应用中,需根据当前的要求去选择合适的精度模式,以达到最佳的测量效果。
2 A3 p5 V: K% o以上资料来源于正点原子的《AN1703C ATK-VL53L0X 激光测距模块使用说明》。这里摘录一部分,方便进入主题。/ u9 e4 q. e4 z
因为今天是调试多路的VL53L0X设备,这里不完全借鉴正点原子的例程,但是官方提供的驱动我们还是必须要用的。, v E3 y- U4 @* k. V# v' q! M
如果想要快速上手,文末直接下载我的代码,我的驱动库经过自己的修改,和正点原子有些不同。: D0 D9 K6 I, ?% K9 G* `
我们直接从代码入手吧!
1 f" W' R: o% r1 {& \" b9 Q7 ~在初始化VL53L0X之前,我们必须初始化IIC外设,此次遵循正点原子的方法,用模拟IIC。
- #ifndef _VL53L0X_I2C_H- j/ o) d7 \1 c) e
- ; ]! o9 a3 ~3 c6 e6 f
- #define _VL53L0X_I2C_H
; z9 U3 b3 u# Y$ N -
" r( t( ]/ n; k8 W; o- e0 a/ N -
3 }+ h$ z, a) c( v6 _4 j! y -
" R& h9 D: e, F& g A% P2 L - #include "stm32f10x.h"/ j5 h8 G3 }7 a
-
! R( W0 n) r% x+ g3 k - #include "stm32f10x_i2c.h"
; s0 F2 q$ m( ?9 @" H6 M1 C, n5 ~ - - V a# j" d7 h6 e5 U' I
-
# g; s/ ]: s5 V' {% [. c6 m7 f# ` - 5 s% g& r& z3 \
- //四个VL53L0挂载在同一个IIC总线下,所以使用四个片选信号--2019/10/30
7 P7 _4 Z& ]6 V# E. M* M4 D - ! t( U( x* m9 @6 I
- //!!!!!!!注意:重新使能设备后,设备iic的地址会恢复为默认值0x52--2019/10/30; n9 s# s" m# p$ P
-
0 o n0 n3 y4 f* W7 Q% N- C - //VL53L0 0
2 @0 B# b7 }9 l - ( P2 T( \# f" Q. O$ c
- #define I2C_SCL_GPIO GPIOB
: o' K. U* q% N- B) X -
2 y* A' G9 K) f+ A3 S - #define I2C_PIN_SCL GPIO_Pin_8
$ @/ n& {, N$ J+ X' { - 3 b- E- ]; B# p9 k" w& d& w* q' g
- #define I2C_SCL_HIGH() GPIO_SetBits(I2C_SCL_GPIO,I2C_PIN_SCL) + Q9 p- y$ a- K8 E N7 l
-
# Y5 w. S' C k/ o: H9 O - #define I2C_SCL_LOW() GPIO_ResetBits(I2C_SCL_GPIO,I2C_PIN_SCL)
+ T+ U4 d: D+ G9 \6 \1 ^& z( Y -
* ~& i* P, D2 _, U+ f! [& L - , U2 r7 u0 h% B/ U, {3 H; T
-
, i5 s, g A/ O1 R; ?9 Y4 E& d/ ] - #define I2C_SDA_GPIO GPIOB
) y. w7 Q, b. l' L0 B* P - 8 u) G: e& J$ I+ O
- #define I2C_PIN_SDA GPIO_Pin_9
/ T9 l( }( i8 @" l) E- s% z -
; W1 ]9 \/ I5 ^# R" f4 Y. p - #define I2C_SDA_HIGH() GPIO_SetBits(I2C_SDA_GPIO,I2C_PIN_SDA)
" ^2 w. t% R' @8 l - 2 F1 C5 ~. j w1 V0 ]) s
- #define I2C_SDA_LOW() GPIO_ResetBits(I2C_SDA_GPIO,I2C_PIN_SDA)
+ ]) T) v! u7 ^- y/ P -
5 k L# Z! q4 R/ ]2 [2 D - #define I2C_SDA_STATE GPIO_ReadInputDataBit(I2C_SDA_GPIO,I2C_PIN_SDA)
* L7 x/ ^" l5 d% O' N G -
. }& s- i2 n' U9 k - 2 }6 j, L+ q; ]$ H8 d
-
6 X( t) z' w3 o. b6 n - //片选使能--2019/10/30
6 Y$ }) t( Z8 T8 a - : l$ Y" ^6 L. s7 p
- #define I2C_X_GPIO GPIOB; A/ _' j' y$ V+ b+ ~2 j4 v/ e, R
- + ^0 U2 W6 P' L
- #define I2C_PIN_X0 GPIO_Pin_12
b4 W% T5 ~( q$ }/ o -
4 e: W. r, Y% Z( Y' x3 Q1 d - #define I2C_X0_HIGH() GPIO_SetBits(I2C_X_GPIO,I2C_PIN_X0) " A9 A0 i+ B, t' m' }1 l
-
3 I4 Z8 O2 c t4 J) K+ @+ J6 H$ @* r3 _ - #define I2C_X0_LOW() GPIO_ResetBits(I2C_X_GPIO,I2C_PIN_X0)
/ a1 J1 P! E9 g3 N4 V, n - / x S* x3 D" U2 P; B7 d X, b
-
: l, p+ t) y. Z5 O+ p' F8 M. l+ ~ - # l. `! E9 i& j# B
- #define I2C_PIN_X1 GPIO_Pin_132 k3 p8 u5 K( L: C; y N' b3 B
-
^5 n1 x! ^% g$ ?- w - #define I2C_X1_HIGH() GPIO_SetBits(I2C_X_GPIO,I2C_PIN_X1)
% m! `% T; k2 l - w" ~3 f& \6 @0 d S% B
- #define I2C_X1_LOW() GPIO_ResetBits(I2C_X_GPIO,I2C_PIN_X1)
6 u- }/ X' t" l' f- g - 8 e8 b1 {0 o, x- {' x$ ^( x
-
# Z: |) C2 C: i9 |, }+ X - 2 w& J. V- Q8 |6 Q
- #define I2C_PIN_X2 GPIO_Pin_14- x& e! W0 ?' v/ f" {' K S
-
* Q: V/ ?* ]; d. _( g9 ~0 g - #define I2C_X2_HIGH() GPIO_SetBits(I2C_X_GPIO,I2C_PIN_X2)
1 H3 d$ g' U9 V' Z8 J3 F -
& C8 B* O5 U; B- E7 } - #define I2C_X2_LOW() GPIO_ResetBits(I2C_X_GPIO,I2C_PIN_X2)
0 Z: ] r: _$ Y! E% B6 x - - o. j5 `6 }! ~/ X5 J- g5 ]2 t
- ! Q1 {- ~( Z2 B& s
-
3 N* c# b0 M5 k7 O2 O - #define I2C_PIN_X3 GPIO_Pin_15
6 w( e5 G- z- b# ]: b E- Z( d: I - % A* \6 b/ O* h6 T$ R$ l. {
- #define I2C_X3_HIGH() GPIO_SetBits(I2C_X_GPIO,I2C_PIN_X3) - P1 k; c8 }0 u8 J
-
0 w% O9 D# S* U, y/ X, o - #define I2C_X3_LOW() GPIO_ResetBits(I2C_X_GPIO,I2C_PIN_X3)4 J$ M* u* ^1 e0 {
-
C4 t6 n9 c6 N- e - 4 `% S% u5 W4 L! f: x$ B4 [
-
: g# T% T/ G/ B* S! T$ ] - void i2c_init(void);1 m' \% s0 c# m- B# V1 S0 r
- ! e( I* X. O$ _" U# d
- uint8_t i2c_write(uint8_t addr, uint8_t reg, uint32_t len, uint8_t * data);
0 B$ \! l; s$ k -
$ o# O. s* y2 o% o' p - uint8_t i2c_read(uint8_t addr, uint8_t reg, uint32_t len, uint8_t *buf);
, s3 L2 m7 N% h8 @ - * F w! R, t2 z' p8 Z+ w. U' j
-
, u5 V' L2 k6 ?- m1 L' ^ - 6 ~% Q, g) i% Y* s
- ; Q6 ?% o$ J, a3 g
-
+ H- s) d6 x1 F - #endif
复制代码- void i2c_init(void)3 M, P; F( l: a& U- K7 A
- 1 [7 P8 A+ S$ _' b
- {4 F, q! m2 C' ]' ~7 L& z9 }
- 6 @: x/ O( c# v6 x/ A
- GPIO_InitTypeDef GPIO_InitStructure;9 Z* x* i! _8 ^. w1 I; {3 w+ ]# A
- 0 H4 S' e6 G# \2 |4 w$ O) P/ W/ U2 Q; ^1 f
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
& O' F( J) S! c; D - " L2 A7 ^+ J6 c% ^* K0 n- R8 X# b
- 0 A6 v/ f: U, r8 `) }* o
-
" {1 ?5 y( ^* F$ N k c - //模拟iic配置( d: S* _2 _2 x& V% `7 X
-
* Q$ g4 b# |7 g3 g2 a - GPIO_InitStructure.GPIO_Pin = I2C_PIN_SCL;7 N9 }: z+ s! h- U& ]# V* `
-
6 ^5 z8 t' H1 j% ` - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;* j+ f( \( s# Y$ I' \; y6 y
- 6 C, c; c1 Q; ~" Z
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
4 b/ ~* d. _ K( o1 ~5 q% I -
9 t5 h$ L* V( A4 i" O - GPIO_Init(I2C_SCL_GPIO, &GPIO_InitStructure); R4 g7 x' l7 d' P" Y' s& O
-
. |4 N* l( _; K, D - ; q, x, }& [ V6 p) r- I* H
- . D$ ]) a. {1 w
- GPIO_InitStructure.GPIO_Pin = I2C_PIN_SDA;( T; a/ i ?6 e) z$ T, T' \
-
2 v; T% V$ H( \0 L - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;0 B/ m9 `# N8 f2 m+ N* M$ \% ], d
- $ y, [3 M# x% u5 Y* r
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;9 Y4 i/ q9 {, a7 p- Z! O
-
4 L. _' ?3 V4 x/ t8 ^6 a' W% V - GPIO_Init(I2C_SDA_GPIO, &GPIO_InitStructure);
8 ^5 @: u# n, T6 J' Q$ } -
; V! l' U+ X- w - 7 ` w8 j. I, N) Q
-
6 C: d' ~; {- y& q! [ - //片选使能配置
; u7 \' y: j, ^: f* s- x -
5 ?( Q5 O1 |* e4 v) _8 u2 c - GPIO_InitStructure.GPIO_Pin = I2C_PIN_X0;
8 [1 a4 _& K7 _9 |( O -
5 o# F1 ^, S0 K) k - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;! @/ r0 ?/ s+ S: h8 \1 J& U5 X% m
- 5 N# x& s* x" T0 K5 w1 c) T
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
& N% U' }! P0 ~6 s$ t - F/ o) t8 S6 X* y" O
- GPIO_Init(I2C_X_GPIO, &GPIO_InitStructure);* q' D4 s8 B7 C4 ]# V7 S7 t i
- 6 C5 D' I4 L4 \" l$ f% ^
- ( J. j8 o+ P; Z8 r3 Y* ]& d( x) S
-
( ?) @% w+ x2 @; L' [4 n: ] - GPIO_InitStructure.GPIO_Pin = I2C_PIN_X1;7 [" ?7 l- S9 I. B0 o' |* L
- " t3 @- {' ^6 |+ `* Z- x
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;- e o: ~, y! e
-
3 b4 Z5 Y' p$ }1 W m - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;/ {6 ^$ G) z# P" V5 N) L
- 3 ^7 o7 R$ S+ Z$ }2 o! [
- GPIO_Init(I2C_X_GPIO, &GPIO_InitStructure);& h) N9 @- [. h1 W2 E
-
7 z% u' ?, y" k5 k8 C* j9 s' s) } -
0 R0 f* K; R, B& t* ~* z - % D8 I) C" M# A8 `
- GPIO_InitStructure.GPIO_Pin = I2C_PIN_X2;$ e! R' r, N5 Y+ j8 ~- Q# n7 X
-
$ P2 H7 i" r7 o# j. G& c1 v3 ? - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ t! I( ?% z, n! ^7 {, x - 7 p- }' q% b# m: s! v9 M: y/ U" n- q
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;7 a- Y7 z* Z' F
- % L, C6 H; |1 v, t5 p/ c0 M
- GPIO_Init(I2C_X_GPIO, &GPIO_InitStructure);
& I% x8 A/ {5 h# o3 S6 W - $ i1 r e/ ] _
-
b- L2 d* R6 e6 ~$ \ -
; [- `0 l* s w$ ? - GPIO_InitStructure.GPIO_Pin = I2C_PIN_X3;
1 ]+ @* f9 b0 M -
/ v1 ]1 I8 V+ Y* j9 \ - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;" [; }7 {) b2 o( T% M. K& g
- : B. y# w- D) |, L! Q5 A5 `
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;1 [, J/ i3 F; P6 ?3 U0 r) \# x
- + z3 k$ E2 O% f& W
- GPIO_Init(I2C_X_GPIO, &GPIO_InitStructure);
, {2 |2 Y" E( \+ l0 ] -
1 h7 }$ J: A7 D7 ~ -
! j2 G* \3 V; x4 F - 7 s" C$ a7 {+ B7 q6 N% K
- I2C_X0_LOW(); * @ X. }6 U( _ ~! L' B5 n) b0 g
- 5 X3 }/ C7 V" e4 h4 d
- I2C_X1_LOW();
2 G1 u" G+ d' C* x) V4 r( J -
m$ l2 [0 Z3 r/ I% S6 c" q' e - I2C_X2_LOW();
$ f1 N! U9 H/ Z) _$ s( x/ n8 ~ - * i9 X- d; u# O5 @; ]
- I2C_X3_LOW();
( q( \$ `* \8 G -
+ ~+ T; }3 e7 {! u - delay_ms(20);: [3 k! u& G2 A1 @, z' o
- + B; X: ?0 ]! r' n
- }
复制代码 3 j4 C1 U1 J, q- l. x& X; y$ z
$ p% _% _' j/ I1 J1 j- B
在模块初始化时调用IIC外设初始化,同时初始化4个测距模块。 -
! p. G6 m) q- s/ ] - {
; |$ }1 Y! A2 {/ a- u6 b0 M/ x5 u# O - - ]/ A5 r: c8 @! M( z9 ?' l w
- / c, k" [; A Z# e/ H
-
/ n9 ~' j8 m& p% G - VL53L0X_Error Status = VL53L0X_ERROR_NONE; //初始值赋值为0$ n; i% X- X+ u5 C* q$ q
-
! l# S( u& @# Z0 r - 3 H4 l: f i) V t# I
- ! U0 H, v- y" P% r# Z8 k
- //初始化一定按照这个顺序执行,否则不成功
s" M2 L0 ^' g( H6 X - * Z$ U) J& c7 }9 \. t3 F
- VL53L0X_i2c_init(); 2 S" V! } q8 P
-
$ v! I5 N4 S% s0 y - vl53l0x_initX(&vl53l0x_dev0,0);
9 i: I; B8 N- j- r3 u5 n) s3 n - " w6 p* S* Q6 G; N, S( N
- vl53l0x_initX(&vl53l0x_dev1,1);/ M1 W7 @" G$ W* X& h
-
! b2 _! Z; `9 p - vl53l0x_initX(&vl53l0x_dev2,2);, y6 _3 A. d# [+ l
-
3 U: E1 V$ n% p+ Z) K# n# Z. w - vl53l0x_initX(&vl53l0x_dev3,3);
1 L4 Z2 s' B* Z+ H8 K' W -
Q. x9 v; n( [# l8 Y; p% x, W - 1 R% C- [3 D o# Q+ Z' e% F& z9 A
- " h0 V: H# z4 W$ R3 D
- return Status; //返回0
+ {1 V- }( n+ A6 y, @9 U -
' H! S; F$ r+ Y" P - }
复制代码 2 d% |* R& T. e0 r+ r0 H2 d
' B( ~6 a0 _) |/ R
在vl53l0x_initX()函数便去别去正点原子的驱动,这里是全文的重点,很多单设备发展到多设备这里都会出问题,在初始化设备时一定要设置设备的IIC地址。 2 \. h: r: e1 T9 A
//单个VL53L0初始化
8 e% r2 G/ {, e# EVL53L0X_Error vl53l0x_initX( VL53L0X_Dev_t *pMyDevice ,u8 vl53l0_x_id)1 x m0 u0 V6 k5 h( ]. p
{ d k4 E2 B' @
VL53L0X_Error Status = VL53L0X_ERROR_NONE; //初始值赋值为0
( ]6 r* w/ i% K1 O
% d4 {* s; }- {7 t. D pMyDevice->I2cDevAddr = 0x52; //iic地址 0x52是默认地址,要初始化必须先写0x52,才能初始化,之后再通过软件修改
1 D# k( u, r' i0 J v3 d- K pMyDevice->comms_type = 1; //选择IIC还是SPI iic=1;SPI=0: N& O8 O- s2 j6 @* H v/ {
pMyDevice->comms_speed_khz = 400; //iic速率
% l( c! h8 P j: I3 d3 z- v 8 c6 z- v* O; {* v
5 ?' G! `1 c L& S/ R5 \+ g //正点原子的VL53L0用户手册上写明了再次使能时地址会恢复为0x52,所以只能使能一次,设置好地址即可,这里是核心
9 ?& ?7 T) F9 o( V% w x3 ^* H switch(vl53l0_x_id)
/ M: f& w' B4 v: l" D {- C- d4 b# {+ \$ d/ w: r# \ i
case 0:
8 P. y1 \9 [3 V/ v2 F0 R* [* t I2C_X0_HIGH();
2 i- n2 a7 \1 [; I1 l delay_ms(20);+ z9 u3 o4 l- _' n; V- B' w
vl53l0x_Addr_set(pMyDevice,0x60);//设置第一个VL53L0X传感器I2C地址- R9 I2 }$ W) Z$ D
break;% i: G. M1 L8 e% P# T& q
case 1: 8 r/ l" j8 J$ u( n+ a0 R
I2C_X1_HIGH();
0 P9 t+ }2 }3 F$ u. M% s Y. ~ delay_ms(20);6 ]* e! r( e5 i* m+ ]2 B+ U
vl53l0x_Addr_set(pMyDevice,0x62);//设置第一个VL53L0X传感器I2C地址, U, `# e' z$ H3 {3 E% R
break;& z+ U1 Q' a! g
case 2:
9 E4 L6 l$ |+ p' W- k! [ I2C_X2_HIGH();
3 Y! u2 z5 b+ Y delay_ms(20);% _7 r. b0 n. m8 P
vl53l0x_Addr_set(pMyDevice,0x64);. o3 o4 @. Z0 r
break;( l9 d: C) {" P& ]! e
case 3: 8 R) H- M! J. A7 Z9 ^+ d1 [+ [
I2C_X3_HIGH();
2 C" T4 `4 L* o% W; L K, {) ? C* }2 E delay_ms(20);
# m; w- h" P. t$ S9 }; e0 V6 l vl53l0x_Addr_set(pMyDevice,0x66);# x2 Y9 _+ Y5 l
break;4 F. }" h U; @5 B" I0 P# c; n7 R4 u+ Y
}$ G$ Y, y6 Q3 o: ~7 ^( b6 W
! j4 M) R. g; r6 \1 g% V5 t
Status = VL53L0X_DataInit(pMyDevice); // Data initialization //VL53L0X_DataInit:一次设备的初始化,初始化成功返回0
) b+ p' X6 k' d+ b) Z if(Status != VL53L0X_ERROR_NONE){ //判断如果状态不为0 打印错误信息
$ x$ r. w6 Y- \ print_pal_error(Status);
( c) g& E1 @4 [' Y# J6 C: h return Status; // 返回错误值 可通过此值DEBUG查找错误位置
# d2 q6 N0 i0 {' _" Q, @ }5 U0 G7 Q8 N* _" h1 {
# S9 n) d9 d4 d) Y! i( O
Status = VL53L0X_GetDeviceInfo(pMyDevice, &vl53l0x_dev_info); //读取给定设备的设备信息
3 p1 L* A: k% l( { if(Status != VL53L0X_ERROR_NONE){
f: w4 I7 g$ @" Q3 {4 S8 i print_pal_error(Status);
7 y5 @: O ?+ ~9 D$ H& O4 Q7 m return Status;: S. A* `) g* P8 Y, m0 M, L
}
; Y4 l+ ?3 q E: Y& h% }2 @ printf("VL53L0X_GetDeviceInfo:\n");
" y# p: p+ Q* a, {$ o printf("Device Name : %s\n", vl53l0x_dev_info.Name); //设备名
4 Y( `# b+ \. b printf("Device Type : %s\n", vl53l0x_dev_info.Type); //产品类型VL53L0X = 1, VL53L1 = 2
+ W1 E8 A: n. Q! c printf("Device ID : %s\n", vl53l0x_dev_info.ProductId); // 设备ID/ C" z4 v6 M8 Z
printf("ProductRevisionMajor : %d\n", vl53l0x_dev_info.ProductRevisionMajor);& A/ S8 B# D- v# T
printf("ProductRevisionMinor : %d\n", vl53l0x_dev_info.ProductRevisionMinor);
) r" t. O, k9 ~( [6 F9 Z3 m6 g' m- ^- X7 w
if ((vl53l0x_dev_info.ProductRevisionMajor != 1) && (vl53l0x_dev_info.ProductRevisionMinor != 1)){
" W& N2 d( F4 G* c# w: M printf("Error expected cut 1.1 but found cut %d.%d\n",
: M y6 O; a( c: r! [' E& }2 a vl53l0x_dev_info.ProductRevisionMajor, vl53l0x_dev_info.ProductRevisionMinor);
5 E5 D1 R: v4 R8 G* l$ ] Status = VL53L0X_ERROR_NOT_SUPPORTED;
4 b( l6 B3 t' b$ h print_pal_error(Status); D( \. ?7 U) z( K; K$ D% X6 X
return Status;, [4 G5 L, X, r3 }- q/ H) j9 z2 L
}7 v) M5 H! D+ y
. ^9 ~ p5 R; T4 u
Status = vl53l0x_measure_init(pMyDevice); //测量配置
* P/ a8 P7 @) x5 a* U vl53l0x_status = Status;, ~; D8 L! G: {" z% w* ^
if(Status != VL53L0X_ERROR_NONE){ //判断如果不为0打印错误信息
# `) O |6 V: {5 R, C print_pal_error(Status);3 V: L, E7 ]* g/ u- s
return Status;% [, X' f) Z# z f6 G" [5 t
} ) E1 Y. ~$ I# |' m) h {
} 模块的初始化顺序是:使用默认地址初始化设备---修改传感器IIC地址---再次初始化---测量配置! \2 Y V U( J3 M
所以在这个传感器的初始化中我们先用默认的0X52地址将VL53L0X模块初始化,初始化完成后方可修改其地址,这里使用SWITCH函数判断用户配置的地址,避免函数重写,减小代码尺寸。修改完地址调用VL53L0X_DataInit()函数进行模块的再次初始化,使修改生效。注意:VL53L0X不能保存地址,如果掉电后地址会恢复为默认的0X52,同时修改完地址后只能执行一次初始化,更多的初始化次数会也会导致地址复位。这在硬件的处理上要加倍注意。: N, `6 Z8 s& F _8 C( `
在这里我翻车了,因为硬件不在我的手边,我都是远程帮助调试,没看到硬件,我的朋友一直反应各种问题,最多的就是测距有问题,测出的数据都是错的,或者只有一个传感器可以使用。我检查了很多遍的代码,始终找不到原因,还好他自己也想到了硬件的问题(因为他们硬件干过很多错事,都是一些小白容易犯的,但是那个老员工比较粗心,也会犯错),最后发现是线的质量太差,线的长度太长,IVL53L0X模块安装的位置不好,因为模块安装在可动部件上的,导致每次移动都会导致模块短暂的掉电,导致地址复位。后来加装模块的减震装置更换屏蔽线解决问题。
. ~7 U1 T& P; ]+ Q& T复位完成便可以测试: 
8 s# t# ]' [$ Q5 `5 _. d8 c) z
. `) L: d* u- A8 \
- VL53L0X_Error vl53l0x_start_single_test(VL53L0X_Dev_t *pdev, \
5 [8 I3 O K0 E) j0 K; a - 5 e/ q$ `- E7 y8 R+ J" W
- VL53L0X_RangingMeasurementData_t *pdata)
: { m2 ~5 s3 F3 M; R -
( i2 @. n3 i9 w# q6 W$ u1 J( P5 H# f - {+ N) r, |$ y, ~- E! Y0 |' p0 V, w: H
- " b H: h! I' u, t: h& [) Y
- int i=0,j=0,sum=0;5 f- P, s1 w) F
- , {6 p t6 l2 J8 A ]* @
- VL53L0X_Error status = VL53L0X_ERROR_NONE;
5 Z8 [% o+ j" U3 e - # E% g- u& q, K* Z
-
# M) L! `! f7 J9 G; ^ -
% X7 ]; _ @9 T& Q8 d6 i - if(vl53l0x_status != VL53L0X_ERROR_NONE): \/ W5 \" H, u
- Y; p7 e* s8 B5 Y' F$ h: [
- return vl53l0x_status;0 c+ m" F6 V! m( S* C4 p# s
-
$ v( U2 m. e2 a0 K - ; p J. N: |% v& c8 Z4 w2 h
-
3 H E7 s8 l. O' y, a3 O6 G7 p - status = VL53L0X_PerformSingleRangingMeasurement(pdev, pdata); 执行单次测距并获取测距测量数据
4 K6 [, @( y7 T6 ^. P8 @ - & R' P2 U3 ?( B0 N
- if(status != VL53L0X_ERROR_NONE){
% ?0 U$ w) F( t# Y+ l v6 m" O2 N6 F - 9 Z) w0 r" K0 a( e( f
- printf("error:Call of VL53L0X_PerformSingleRangingMeasurement\n");
" A5 |$ k$ F8 z- l; l - 6 x0 Q; x# {4 E3 C
- return status;" j5 ]9 z1 @/ g: Y. A
-
3 T4 J1 T3 N* h5 Q - }
* S+ Z0 F1 O2 I/ R. o7 z -
$ Z/ m& {1 f% y! j$ ~ -
t4 A H: z. j' ?5 r( e - . Q$ l$ }6 s: j! L- Y5 ]
- for(i=0;i<5;i++)0 m% L# d$ ? d8 z/ C
-
9 Z, Y' M' f0 r( t' v. t+ G - sum+=pdata->RangeMilliMeter; J9 E! M2 B, N% N
- d* l: s( m; f3 R' C+ t# u) [
- pdata->RangeMilliMeter=sum/5;; I) p7 j y e
-
% T2 X( x* I" s2 D - printf("%d\r\n",pdata->RangeMilliMeter);6 X1 u: d5 m& T; b, i2 T3 ^% d
-
. g. v8 d9 F* h; ` - return status;- n( d) a% G; A
-
, u5 y( ?+ U6 b* R; o - }
复制代码 ) k) u& |$ ~8 U ]1 c
% Y1 Z2 u( I! ^
打印测试结果,通过! 
. a% Q! d# S' l0 o% {9 @$ N
主函数循环测试,因为项目对代码的速度要求不高,所以一些状态判断代码中还有保留,这里跟着原子走,没做太多改变。# M( R% y Q {: {; I9 |
因为这个项目是帮助朋友做的调试,而且他们的项目还在研发期,太多的东西不能介绍,照片啥的都放弃了。一个简短的帖子,希望能帮到大家把握住该模块,蟹蟹。0 D- c+ r8 s( p8 ^7 b
---------------------$ z9 H7 Y7 U7 [$ w9 h% @; Z
作者:呐咯密密
; T: D y/ h* b4 S6 y( ]* @' B |