把代码复制上来,图太模糊了,手机拍屏幕,连截图都不是…
还有你线是怎么接的,都说清楚
代码:
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "MyI2C2.h"
#include "VL53L1X_api.h"
// 声明官方库里的全局变量
extern uint16_t dev;
int main(void)
{
VL53L1X_ERROR status;
uint16_t dist = 0;
uint8_t dataReady = 0;
OLED_Init();
MyI2C2_Init();
Delay_ms(200);
// 1. 传感器初始化
status = VL53L1X_SensorInit(dev);
if (status != 0) {
OLED_Printf(0, 0, OLED_8X16, "Init Err:%d", status);
OLED_Update();
while(1);
}
OLED_Printf(0, 0, OLED_8X16, "Sensor OK!");
OLED_Update();
Delay_ms(500);
// 2. 切换到长距离模式(最大测距4米)
// 必须在初始化之后,开始测距之前调用
VL53L1X_SetDistanceMode(dev, 3);
// 1. 启动测距(这一步之前漏掉了,必须加上!)
// 启动测距
VL53L1X_StartRanging(dev);
uint32_t caliCount = 0; // 用于记录自校准时间
while (1)
{
uint8_t dataReady = 0;
// 检查传感器数据是否准备就绪
VL53L1X_CheckForDataReady(dev, &dataReady);
if (dataReady)
{
// 读取距离
VL53L1X_GetDistance(dev, &dist);
// 清除中断标志(必须清除,传感器才会继续测距)
VL53L1X_ClearInterrupt(dev);
// 过滤掉启动阶段的垃圾数据(如 65535)
if (dist > 20 && dist < 4000) {
OLED_Printf(0, 0, OLED_8X16, "Dist:%4d mm", dist);
} else {
// 如果还在读取无效数据,显示等待提示并尝试重启测距
if(dist == 65535 && caliCount < 300) {
caliCount++;
VL53L1X_StartRanging(dev); // 重新触发,辅助它退出校准状态
OLED_Printf(0, 0, OLED_8X16, "Calibrating... ");
} else {
OLED_Printf(0, 0, OLED_8X16, "Dist: Out of R "); // 启动测距
VL53L1X_StartRanging(dev);
uint32_t caliCount = 0; // 用于记录自校准时间
while (1)
{
uint8_t dataReady = 0;
// 检查传感器数据是否准备就绪
VL53L1X_CheckForDataReady(dev, &dataReady);
if (dataReady)
{
// 读取距离
VL53L1X_GetDistance(dev, &dist);
// 清除中断标志(必须清除,传感器才会继续测距)
VL53L1X_ClearInterrupt(dev);
// 过滤掉启动阶段的垃圾数据(如 65535)
if (dist > 20 && dist < 4000) {
OLED_Printf(0, 0, OLED_8X16, "Dist:%4d mm", dist);
} else {
// 如果还在读取无效数据,显示等待提示并尝试重启测距
if(dist == 65535 && caliCount < 300) {
caliCount++;
VL53L1X_StartRanging(dev); // 重新触发,辅助它退出校准状态
OLED_Printf(0, 0, OLED_8X16, "Calibrating... ");
} else {
OLED_Printf(0, 0, OLED_8X16, "Dist: Out of R ");
OLED_Printf(0, 16, OLED_8X16, "Dist: %d ",dist);
}
}
OLED_Update(); // 刷新屏幕显示
}
Delay_ms(10);
}
}
}
OLED_Update(); // 刷新屏幕显示
}
Delay_ms(10);
}
}
VL53LXX-U2的接法:
SCL接B11 SDA接B10 XSHUT没有接
先改一个明显的错误:你用的是 VL53L1X_... 这套 ULD API,VL53L1X_SetDistanceMode() 的参数只有 1=Short、2=Long,没有 3。想设长距离模式应写成:
status = VL53L1X_SetDistanceMode(dev, 2);
另外,5633 不一定代表传感器“卡住”了。你的代码只判断距离是否小于 4000,却没有读取 RangeStatus。无目标、反射信号太弱或测量无效时,距离寄存器同样可能给出一个数,这个数不能直接当真实距离用。
建议先别加校准、重启这些逻辑,每帧把下面几项都打印出来:
-
CheckForDataReady()的返回值和dataReady -
GetDistance()的返回值 -
GetRangeStatus()的结果 -
原始
dist
RangeStatus==0 再使用距离;非 0 就按无效测量处理。还有,SetDistanceMode()、StartRanging()、ClearInterrupt() 的返回值现在全被丢掉了,先逐项打印,基本就能定位是参数、I2C 通信还是测量状态的问题。
这段代码把问题绕复杂了。VL53L1X 启动后是连续测距,不是每次读到异常值都要重新 StartRanging(),更没有什么“连续启动 300 次辅助退出校准”的标准流程。先把 caliCount 和那一大段重启逻辑删掉。
你现在至少有两个明确问题:
-
ULD 的长距离模式是
SetDistanceMode(dev, 2),不是 3。 -
只看
dist,没看RangeStatus,所以 5633 到底是有效测量还是无效结果,代码自己也不知道。
还有一点:OLED 只在 dataReady 为 1 时更新。如果后续 dataReady 一直为 0,屏幕当然会停在旧数值,看起来像“死了”。把 dataReady 和各函数返回值也显示出来,就能区分“没有新数据”和“一直得到无效距离”。
最小流程就应该是:初始化一次 → 启动一次 → 等 ready → 读 RangeStatus 和 Distance → ClearInterrupt → 继续等下一帧。先用这个跑通,再谈滤波和校准。
在改动更多固件之前,我会先把模块放到一个已知正常的台架环境中:短线连接、约 300–500 mm 外放一个固定的白色目标、避免强烈阳光,并且不要遮挡光学元件。如果传感器上还有保护膜,请将其撕掉。
然后按以下顺序检查硬件:
-
读取传感器 ID。对于 VL53L1X ULD API,它应该是
0xEACC;不要根据通用的VL53LXX-V2板卡丝印来推断芯片型号。 -
在一次 16 位寄存器读取期间,用示波器观察 SDA 和 SCL。检查寄存器地址字节顺序、数据字节顺序、ACK 应答以及重复起始条件。初始化成功并不一定能证明每个多字节事务都正确。
-
在测距期间确认模块处的供电,而不仅仅是在传感器空闲时确认。
-
然后才检查 XSHUT。许多这类转接板已经将它上拉,而在轮询
CheckForDataReady()时不需要 GPIO1。
另外,也务必修正 SetDistanceMode(dev, 3)——在这个 ULD API 中,长距离模式是 2。在输出距离的同时打印 RangeStatus;否则,一个毫无意义的 5633 看起来会完全像传感器卡死了一样。



