把代码复制上来,图太模糊了,手机拍屏幕,连截图都不是…
还有你线是怎么接的,都说清楚
代码:
#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 中,Long 模式是 2。請把 RangeStatus 跟距離一起印出來;否則毫無意義的 5633 看起來就會跟感測器卡死一模一樣。



