前言:本实验用CW32L012作为主控,TOF200C为激光测距模块,最终测得距离在串口助手中显示。
一、TOF200C传感器模块介绍:
TOF200C VL53L0X是ST公司推出的新一代 ToF 激光测距传感器,采用了第二代 FlightSenseTM技术,利用飞行时间(ToF)原理,通过光子的飞行来回时间与光速的计算,实现测距应用。较比上一代 VL6180X,新的器件将飞行时间测距长度扩展至 2 米,测量速度更快,能效更高。
除此之外,为使集成度过程更加快捷方便, ST 公司为此也提供了 VL53L0X 软件 API(应用编程接口)以及完整的技术文档,通过主 IIC 接口,向应用端输出测距的数据,大大降低了开发难度。VL53L0X的感测能力可以支持各种功能,包括各种创新用户界面的手势感测或接近检测,扫地机器人、服务型机器人的障碍物探测与防撞系统,家电感应面板、笔记本电脑的用户存在检测或电源开关监控器,以及无人机和物联网(IoT)产品等。下附传感器实物图,CW32L012主板。
TOF200C激光测距模块 |
CW32L012主板 |
二、TOF200C工作原理
1.发射端:内置940nm 近红外 VCSEL(垂直腔面发射激光器),发射人眼安全(Class 1)的短激光脉冲。
2.接收端:反射光子经透镜与窄带滤光片(滤环境光),打到SPAD(单光子雪崩二极管)阵列。SPAD 单光子灵敏、雪崩放大,把弱光转为电脉冲。
3.计时与计算:内置TDC(时间数字转换器),皮秒级精度记录光子往返时间t。用TCSPC(时间相关单光子计数):发数百次脉冲,统计 “时间-光子数直方图”,取主峰得精准t。距离公式:d=ct/2(光速c≈3×10的八次方米每秒,÷2 因往返)
TOF200C优点:
1.窄带滤光 +阳光抑制算法,80klux 强光稳定。
2.内置玻璃盖板校准,不用用户写校准流程。
三、软件讲解:
本TOF200C模块使用I2C进行通讯,下附Keil工程中代码例程:
vl53l0x_i2c.c以及vl53l0x_i2c.h ;bsp_VL53L0X.c以及bsp_VL53L0X.h;bsp_uart.c以及bsp_uart.h;main等核心文件
#include "vl53l0x_i2c.h"#include "cw32l012_gpio.h"#include "cw32l012_sysctrl.h"/* 端口定义 */#define PORT_VL53L0x CW_GPIOB#define GPIO_SCL GPIO_PIN_6#define GPIO_SDA GPIO_PIN_7#define PORT_XSHUT CW_GPIOA#define GPIO_XSHUT GPIO_PIN_8/* 简单循环延时 */void Simple_Delay(uint32_t count) {while(count--) {__NOP();}}/* 终极兼容延时:将频率降到 50kHz 左右,确保电平上升沿完整 */#define IIC_DELAY() Simple_Delay(1000)/* 核心策略:不再切换输入/输出方向。将 SDA 始终保持为开漏输出模式(Output_OD)。- 当我们要发送 1 或读取时,向 ODR 写入 1(释放总线,靠上拉电阻拉高)。- 当我们要发送 0 时,向 ODR 写入 0(强行拉低)。*/#define SCL_LOW() PORT_VL53L0x->BRR = GPIO_SCL#define SCL_HIGH() PORT_VL53L0x->BSRR = GPIO_SCL#define SDA_LOW() PORT_VL53L0x->BRR = GPIO_SDA#define SDA_HIGH() PORT_VL53L0x->BSRR = GPIO_SDA#define SDA_GET() ((PORT_VL53L0x->IDR & GPIO_SDA) != 0)void VL53L0X_i2c_init(void){GPIO_InitTypeDef GPIO_InitStruct = {0};__SYSCTRL_GPIOA_CLK_ENABLE();__SYSCTRL_GPIOB_CLK_ENABLE();// SCL 和 SDA 全部配置为开漏输出 + 开启内部上拉GPIO_InitStruct.Pins = GPIO_SCL | GPIO_SDA;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.IT = GPIO_IT_NONE;GPIO_Init(PORT_VL53L0x, &GPIO_InitStruct);// 强制开启内部上拉(防止外部电阻虚接)PORT_VL53L0x->PUR |= (GPIO_SCL | GPIO_SDA);// XSHUT 配置为推挽输出GPIO_InitStruct.Pins = GPIO_XSHUT;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_Init(PORT_XSHUT, &GPIO_InitStruct);// 硬件复位流程GPIO_WritePin(PORT_XSHUT, GPIO_XSHUT, GPIO_Pin_RESET);Simple_Delay(2000000);GPIO_WritePin(PORT_XSHUT, GPIO_XSHUT, GPIO_Pin_SET);Simple_Delay(2000000);SCL_HIGH();SDA_HIGH();}void IIC_Start(void){SDA_HIGH(); SCL_HIGH(); IIC_DELAY();SDA_LOW(); IIC_DELAY();SCL_LOW(); IIC_DELAY();}void IIC_Stop(void){SCL_LOW(); SDA_LOW(); IIC_DELAY();SCL_HIGH(); IIC_DELAY();SDA_HIGH(); IIC_DELAY();}uint8_t I2C_WaitAck(void){uint16_t retry = 0;SDA_HIGH(); // 释放 SDA,让传感器有机会拉低它IIC_DELAY();SCL_HIGH();IIC_DELAY(); // 给传感器留出应答时间while(SDA_GET()){retry++;if(retry > 5000){IIC_Stop();printf("WaitAck Timeout!rn"); // 增加调试打印return 1;}}SCL_LOW();IIC_DELAY();return 0;}void Send_Byte(uint8_t dat){uint8_t i;for(i = 0; i < 8; i++){if(dat & 0x80) SDA_HIGH(); else SDA_LOW();dat <<= 1;IIC_DELAY();SCL_HIGH(); IIC_DELAY();SCL_LOW(); IIC_DELAY();}}uint8_t Read_Byte(uint8_t ack){uint8_t i, receive = 0;SDA_HIGH(); // 释放总线IIC_DELAY();for(i = 0; i < 8; i++){SCL_LOW(); IIC_DELAY();SCL_HIGH(); IIC_DELAY();receive <<= 1;if(SDA_GET()) receive++;IIC_DELAY();}SCL_LOW(); IIC_DELAY();if (ack) SDA_LOW(); else SDA_HIGH();IIC_DELAY();SCL_HIGH(); IIC_DELAY();SCL_LOW(); IIC_DELAY();return receive;}// ---------------- 以下为接口封装(保持不变) ----------------uint8_t VL_IIC_Write_nByte(uint8_t SlaveAddress, uint8_t REG_Address, uint16_t len, uint8_t *buf){IIC_Start();Send_Byte(SlaveAddress);if(I2C_WaitAck()) { IIC_Stop(); return 1; }Send_Byte(REG_Address);if(I2C_WaitAck()) { IIC_Stop(); return 1; }while(len--) {Send_Byte(*buf++);if(I2C_WaitAck()) { IIC_Stop(); return 1; }}IIC_Stop();return 0;}uint8_t VL_IIC_Read_nByte(uint8_t SlaveAddress, uint8_t REG_Address, uint16_t len, uint8_t *buf){IIC_Start();Send_Byte(SlaveAddress);if(I2C_WaitAck()) { IIC_Stop(); return 1; }Send_Byte(REG_Address);if(I2C_WaitAck()) { IIC_Stop(); return 1; }IIC_Start();Send_Byte(SlaveAddress | 0x01);if(I2C_WaitAck()) { IIC_Stop(); return 1; }while(len) {*buf = Read_Byte(len > 1);buf++; len--;}IIC_Stop();return 0;}uint8_t VL53L0X_write_multi(uint8_t address, uint8_t index, uint8_t *pdata, uint16_t count){ return VL_IIC_Write_nByte(address, index, count, pdata); }uint8_t VL53L0X_read_multi(uint8_t address, uint8_t index, uint8_t *pdata, uint16_t count){ return VL_IIC_Read_nByte(address, index, count, pdata); }uint8_t VL53L0X_write_byte(uint8_t address, uint8_t index, uint8_t data){ return VL_IIC_Write_nByte(address, index, 1, &data); }uint8_t VL53L0X_write_word(uint8_t address, uint8_t index, uint16_t data){ uint8_t b[2]; b[0]=(uint8_t)(data>>8); b[1]=(uint8_t)data; return VL_IIC_Write_nByte(address, index, 2, b); }uint8_t VL53L0X_write_dword(uint8_t address, uint8_t index, uint32_t data){ uint8_t b[4]; b[0]=(uint8_t)(data>>24); b[1]=(uint8_t)(data>>16); b[2]=(uint8_t)(data>>8); b[3]=(uint8_t)data; return VL_IIC_Write_nByte(address, index, 4, b); }uint8_t VL53L0X_read_byte(uint8_t address, uint8_t index, uint8_t *pdata){ return VL_IIC_Read_nByte(address, index, 1, pdata); }uint8_t VL53L0X_read_word(uint8_t address, uint8_t index, uint16_t *pdata){ uint8_t b[2]; uint8_t s=VL_IIC_Read_nByte(address, index, 2, b); *pdata=((uint16_t)b[0]<<8)|b[1]; return s; }uint8_t VL53L0X_read_dword(uint8_t address, uint8_t index, uint32_t *pdata){ uint8_t b[4]; uint8_t s=VL_IIC_Read_nByte(address, index, 4, b); *pdata=((uint32_t)b[0]<<24)|((uint32_t)b[1]<<16)|((uint32_t)b[2]<<8)|b[3]; return s; }#ifndef __VL53L0_I2C_H#define __VL53L0_I2C_H#include <stdint.h>// 1. 统一使用标准库定义的类型(兼容旧代码)typedef uint8_t u8;typedef uint16_t u16;typedef uint32_t u32;// 2. 状态定义#define STATUS_OK 0x00#define STATUS_FAIL 0x01// 3. I2C 底层操作函数声明void VL53L0X_i2c_init(void); // 初始化引脚和复位传感器void IIC_Start(void); // 起始信号void IIC_Stop(void); // 停止信号uint8_t I2C_WaitAck(void); // 等待应答void Send_Byte(uint8_t dat); // 发送字节uint8_t Read_Byte(uint8_t ack); // 读取字节// 4. VL53L0X 官方 API 所需的底层读写接口声明// 这些声明必须存在,否则 vl53l0x_platform.c 编译会报错uint8_t VL53L0X_write_multi(uint8_t address, uint8_t index, uint8_t *pdata, uint16_t count);uint8_t VL53L0X_read_multi(uint8_t address, uint8_t index, uint8_t *pdata, uint16_t count);uint8_t VL53L0X_write_byte(uint8_t address, uint8_t index, uint8_t data);uint8_t VL53L0X_write_word(uint8_t address, uint8_t index, uint16_t data);uint8_t VL53L0X_write_dword(uint8_t address, uint8_t index, uint32_t data);uint8_t VL53L0X_read_byte(uint8_t address, uint8_t index, uint8_t *pdata);uint8_t VL53L0X_read_word(uint8_t address, uint8_t index, uint16_t *pdata);uint8_t VL53L0X_read_dword(uint8_t address, uint8_t index, uint32_t *pdata);#endif
#include "bsp_vl53l0x.h"#include "cw32l012_gpio.h"#include "cw32l012_sysctrl.h"#include "stdio.h"/* 外部延时函数声明 (需在main或sysctrl.c中实现) */extern void delay_ms(uint32_t ms);/* 全局变量定义 */VL53L0X_RangingMeasurementData_t vl53l0x_data;VL53L0X_Dev_t vl53l0x_dev; // 设备数据参数VL53L0X_DeviceInfo_t vl53l0x_dev_info; // 设备信息uint8_t AjustOK = 0; // 校准标志位/* 测量模式参数(严格对照你提供的官方建议配置) */mode_data Mode_data[] = {{(FixPoint1616_t)(0.25*65536), (FixPoint1616_t)(18*65536), 33000, 14, 10}, // 默认{(FixPoint1616_t)(0.25*65536), (FixPoint1616_t)(18*65536), 200000, 14, 10},// 高精度{(FixPoint1616_t)(0.1*65536) , (FixPoint1616_t)(60*65536), 33000, 18, 14}, // 长距离{(FixPoint1616_t)(0.25*65536), (FixPoint1616_t)(32*65536), 20000, 14, 10} // 高速};/*** @brief 打印 PAL 层错误信息* @note 依赖你提供的串口重定向 printf*/void print_pal_error(VL53L0X_Error Status) {char buf[VL53L0X_MAX_STRING_LENGTH];VL53L0X_GetPalErrorString(Status, buf);printf("VL53L0X Error: %i : %srn", Status, buf);}/*** @brief VL53L0X 综合初始化* @note 适配 CW32L012 寄存器与引脚控制*/VL53L0X_Error vl53l0x_init(VL53L0X_Dev_t *dev) {VL53L0X_Error Status = VL53L0X_ERROR_NONE;uint32_t refSpadCount;uint8_t isApertureSpads;uint8_t VhvSettings;uint8_t PhaseCal;// 1. 初始化 XSHUT 引脚 (PA8) - CW32风格__SYSCTRL_GPIOA_CLK_ENABLE();GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pins = GPIO_PIN_8;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_Init(CW_GPIOA, &GPIO_InitStruct);// 2. 初始化底层 I2C 接口 (调用适配过的模拟I2C)VL53L0X_i2c_init();// 3. 硬件唤醒流程 (CW32引脚操作)GPIO_WritePin(CW_GPIOA, GPIO_PIN_8, GPIO_Pin_RESET); // XSHUT LOWdelay_ms(20);GPIO_WritePin(CW_GPIOA, GPIO_PIN_8, GPIO_Pin_SET); // XSHUT HIGHdelay_ms(20);// 4. 设备基础设置dev->I2cDevAddr = 0x52; // 默认地址dev->comms_type = 1; // I2C 模式dev->comms_speed_khz = 400;// 5. 数据初始化Status = VL53L0X_DataInit(dev);if(Status != VL53L0X_ERROR_NONE) goto error;// 6. 获取设备信息Status = VL53L0X_GetDeviceInfo(dev, &vl53l0x_dev_info);if(Status != VL53L0X_ERROR_NONE) goto error;// 7. 静态初始化Status = VL53L0X_StaticInit(dev);if(Status != VL53L0X_ERROR_NONE) goto error;// 8. 参考 Spad 管理与校准Status = VL53L0X_PerformRefSpadManagement(dev, &refSpadCount, &isApertureSpads);if(Status != VL53L0X_ERROR_NONE) goto error;Status = VL53L0X_PerformRefCalibration(dev, &VhvSettings, &PhaseCal);if(Status != VL53L0X_ERROR_NONE) goto error;// 9. 设置为连续测量模式Status = VL53L0X_SetDeviceMode(dev, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING);if(Status != VL53L0X_ERROR_NONE) goto error;printf("VL53L0X HW Init Success!rn");return VL53L0X_ERROR_NONE;error:print_pal_error(Status);return Status;}/*** @brief 设置测量模式*/VL53L0X_Error vl53l0x_set_mode(VL53L0X_Dev_t *dev, uint8_t mode) {VL53L0X_Error Status = VL53L0X_ERROR_NONE;if(mode > 3) return VL53L0X_ERROR_INVALID_PARAMS;Status = VL53L0X_SetLimitCheckValue(dev, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, Mode_data[mode].signalLimit);if(Status != VL53L0X_ERROR_NONE) return Status;Status = VL53L0X_SetLimitCheckValue(dev, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, Mode_data[mode].sigmaLimit);if(Status != VL53L0X_ERROR_NONE) return Status;Status = VL53L0X_SetMeasurementTimingBudgetMicroSeconds(dev, Mode_data[mode].timingBudget);if(Status != VL53L0X_ERROR_NONE) return Status;Status = VL53L0X_SetVcselPulsePeriod(dev, VL53L0X_VCSEL_PERIOD_PRE_RANGE, Mode_data[mode].preRangeVcselPeriod);if(Status != VL53L0X_ERROR_NONE) return Status;Status = VL53L0X_SetVcselPulsePeriod(dev, VL53L0X_VCSEL_PERIOD_FINAL_RANGE, Mode_data[mode].finalRangeVcselPeriod);return Status;}#ifndef __BSP_VL53L0X_H#define __BSP_VL53L0X_H#include "vl53l0x_api.h"#include "vl53l0x_platform.h"#include "cw32l012.h"#include "cw32l012_gpio.h"#include <stdint.h>/* XSHUT 引脚控制宏 (PA8) - 适配 CW32 库函数 */#define VL53L0X_XSHUT_LOW() GPIO_WritePin(CW_GPIOA, GPIO_PIN_8, GPIO_Pin_RESET)#define VL53L0X_XSHUT_HIGH() GPIO_WritePin(CW_GPIOA, GPIO_PIN_8, GPIO_Pin_SET)/* 测量模式宏定义 */#define Default_Mode 0#define HIGH_ACCURACY 1#define LONG_RANGE 2#define HIGH_SPEED 3/* 模式参数结构体定义 */typedef struct {FixPoint1616_t signalLimit;FixPoint1616_t sigmaLimit;uint32_t timingBudget;uint8_t preRangeVcselPeriod;uint8_t finalRangeVcselPeriod;} mode_data;/* 全局变量外部声明 (必须与 .c 文件中的定义严格对应) */extern VL53L0X_Dev_t vl53l0x_dev;extern VL53L0X_RangingMeasurementData_t vl53l0x_data;extern mode_data Mode_data[];extern uint8_t AjustOK;/* 函数声明 *//*** @brief VL53L0X 综合初始化* @param dev 设备结构体指针* @return VL53L0X_Error 错误码*/VL53L0X_Error vl53l0x_init(VL53L0X_Dev_t *dev);/*** @brief 设置测量模式(默认/高精度/长距离/高速)* @param dev 设备结构体指针* @param mode 模式编号 (0-3)* @return VL53L0X_Error 错误码*/VL53L0X_Error vl53l0x_set_mode(VL53L0X_Dev_t *dev, uint8_t mode);/*** @brief 打印 PAL 层错误信息到串口* @param Status 错误状态码*/void print_pal_error(VL53L0X_Error Status);/*** @brief 底层模拟 I2C 初始化* @note 内部配置 PB6, PB7 为开漏输出*/void VL53L0X_i2c_init(void);#endif
#include "bsp_uart.h"#include "stdio.h"#include "cw32l012_sysctrl.h"#include "cw32l012_gpio.h"#include "cw32l012_uart.h"uint8_t u1_recv_buff[USART1_RECEIVE_LENGTH]; // 接收缓冲区uint16_t u1_recv_length = 0; // 接收数据长度uint8_t u1_recv_flag = 0; // 接收完成标志位/*** @brief 串口1初始化* @param __Baud 波特率*/void uart1_init(uint32_t __Baud){// 1. 开启 GPIOA 和 UART1 时钟__SYSCTRL_GPIOA_CLK_ENABLE();__SYSCTRL_UART1_CLK_ENABLE();// 2. 引脚配置 (TX: PA09, RX: PA10)GPIO_InitTypeDef GPIO_InitStruct = {0};// TX 引脚: PA09GPIO_InitStruct.Pins = GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_Init(CW_GPIOA, &GPIO_InitStruct);PA09_AFx_UART1TXD(); // 修正:使用对应的 PA09 复用函数// RX 引脚: PA10GPIO_InitStruct.Pins = GPIO_PIN_10;GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP; // 建议开启上拉,防止浮空噪声GPIO_Init(CW_GPIOA, &GPIO_InitStruct);PA10_AFx_UART1RXD(); // 修正:使用对应的 PA10 复用函数// 3. UART 参数配置UART_InitTypeDef UART_InitStruct = {0};UART_InitStruct.UART_BaudRate = __Baud;UART_InitStruct.UART_Source = UART_Source_PCLK;UART_InitStruct.UART_UclkFreq = SystemCoreClock; // 自动获取系统主频UART_InitStruct.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; // 开启全双工UART_Init(CW_UART1, &UART_InitStruct);// 4. 中断配置// 使使能接收完成中断 (RC) 和 接收空闲中断 (RXIDLE)UART_ITConfig(CW_UART1, UART_IT_RC | UART_IT_RXIDLE, ENABLE);UART_ClearITPendingBit(CW_UART1, UART_IT_RC);UART_ClearITPendingBit(CW_UART1, UART_IT_RXIDLE);NVIC_SetPriority(UART1_IRQn, 0);NVIC_EnableIRQ(UART1_IRQn);}/*** @brief printf 重定向*/int fputc(int ch, FILE *f){UART_SendData(CW_UART1, (uint8_t)ch);// 等待发送缓冲区空while( UART_GetFlagStatus(CW_UART1, UART_FLAG_TXE) == RESET );return ch;}/*** @brief 清除接收缓冲区*/void uart1_receive_clear(void){u1_recv_length = 0;u1_recv_flag = 0;}/*** @brief 获取接收到的数据*/uint8_t *uart1_get_data(void){if( u1_recv_flag == 1 ){return u1_recv_buff;}return NULL;}/*** @brief 串口1中断服务函数*/void UART1_IRQHandler(void){// 1. 处理接收完成中断 (RC)if (UART_GetITStatus(CW_UART1, UART_IT_RC) != RESET){if (u1_recv_length < USART1_RECEIVE_LENGTH - 1) // 预留一个位置给 ''{u1_recv_buff[u1_recv_length++] = UART_ReceiveData(CW_UART1);}UART_ClearITPendingBit(CW_UART1, UART_IT_RC);}// 2. 处理接收空闲中断 (RXIDLE)if (UART_GetITStatus(CW_UART1, UART_IT_RXIDLE) != RESET){UART_ClearITPendingBit(CW_UART1, UART_IT_RXIDLE); // 必须先清除标志位if (u1_recv_length > 0){u1_recv_buff[u1_recv_length] = ''; // 结尾补零u1_recv_flag = 1; // 标记一帧数据接收完成}}}#ifndef __BSP_UART_H#define __BSP_UART_H#include "cw32l012.h"#include <stdint.h>#include <stdio.h>// 串口缓冲区的数据长度#define USART1_RECEIVE_LENGTH 128// 修正:extern 数组时最好带上长度,或者统一格式extern uint8_t u1_recv_buff[USART1_RECEIVE_LENGTH];extern uint16_t u1_recv_length;extern uint8_t u1_recv_flag;// 外部可调用函数声明void uart1_init(uint32_t Baud);void uart1_receive_clear(void);uint8_t *uart1_get_data(void);#endif
#include "cw32l012.h"#include "cw32l012_sysctrl.h"#include "cw32l012_gpio.h"#include "bsp_uart.h"#include "bsp_VL53L0X.h"#include "vl53l0x_gen.h"#include "vl53l0x_api.h" // 确保包含 API 头文件#include <stdio.h>// 统一使用简单延时extern void Simple_Delay(uint32_t count);void RCC_Configuration(void) {SystemCoreClockUpdate();}int main(void) {VL53L0X_Error Status = VL53L0X_ERROR_NONE;RCC_Configuration();uart1_init(115200);Simple_Delay(5000000);printf("rn--- CW32 VL53L0X START ---rn");// 第一步:硬件引脚初始化printf("Step 1: Init I2C Pins...rn");VL53L0X_i2c_init();// 快速扫描验证 (只需确认 0x29 是否存在)IIC_Start();Send_Byte(0x52); // VL53L0X 默认写地址 (0x29 << 1)if (I2C_WaitAck() == 0) {printf("I2C Check: Device Found at 0x29!rn");} else {printf("I2C Check: Device NOT Found! Check wiring/XSHUT.rn");}IIC_Stop();printf("Step 1: Done.rn");// 第二步:传感器软件初始化 (逐步执行)printf("Step 2-1: VL53L0X_DataInit...rn");vl53l0x_dev.I2cDevAddr = 0x52; // 显式指定地址Status = VL53L0X_DataInit(&vl53l0x_dev);if(Status != VL53L0X_ERROR_NONE) {printf("DataInit FAILED! Error: %drn", Status);} else {printf("DataInit Success! Next: StaticInit...rn");Status = VL53L0X_StaticInit(&vl53l0x_dev);if(Status != VL53L0X_ERROR_NONE) {printf("StaticInit FAILED! Error: %drn", Status);} else {printf("StaticInit Success! Next: SpadManagement...rn");// 这一步最耗时,如果卡住,请多等一会儿uint32_t refSpadCount;uint8_t isApertureSpads;Status = VL53L0X_PerformRefSpadManagement(&vl53l0x_dev, &refSpadCount, &isApertureSpads);if(Status != VL53L0X_ERROR_NONE) {printf("SpadManagement FAILED! Error: %drn", Status);} else {printf("Step 2: ALL SUCCESS!rn");}}}// 第三步:配置测量模式 (默认使用单次测量)if(Status == VL53L0X_ERROR_NONE) {vl53l0x_set_mode(&vl53l0x_dev, 0);printf("Sensor Ready to Range...rn");}while(1) {if(Status == VL53L0X_ERROR_NONE) {Status = VL53L0X_PerformSingleRangingMeasurement(&vl53l0x_dev, &vl53l0x_data);if(Status == VL53L0X_ERROR_NONE) {printf("Distance: %d mmrn", vl53l0x_data.RangeMilliMeter);} else {printf("Ranging Error: %drn", Status);}} else {printf("Sensor Error State, check hardware.rn");Simple_Delay(10000000);}Simple_Delay(5000000);}}void assert_failed(uint8_t *file, uint32_t line) {while (1);}
四、总结与建议:
1.TOF200C为红外 dToF 激光测距,靠光飞行时间算距离,精度比超声波高、体积小。
2.量程20cm~2m,室内好用,斜测、黑面、镜面、强光下容易不准。
3.只做近距离室内测距 / 避障选TOF200C,远距离别用。
4.必须3.3V 供电,不能 5V;安装垂直正对障碍物。
5.程序加多次取平均滤波,数值更稳。
扫码加入QQ群 3群| 610403240
675