/** * @file VL53L4CD_Driver.h * @brief VL53L4CD 测距传感器驱动接口 * * 基于 ST VL53L4CD ULD 和 Pololu 参考实现,寄存器地址均为 16 位, * 通过项目现有硬件 I2C0 (PA9/PA10) 访问。 */ #ifndef VL53L4CD_DRIVER_H #define VL53L4CD_DRIVER_H #include #include /* 板载默认 7 位 I2C 地址,VL53L4CD 出厂默认 0x29 */ #define VL53L4CD_I2C_ADDR 0x29U /* 寄存器地址 */ #define VL53L4CD_REG_I2C_SLAVE_DEVICE_ADDRESS 0x0001U #define VL53L4CD_REG_VHV_TIMEOUT_MACROP_LOOP_BOUND 0x0008U #define VL53L4CD_REG_XTALK_PLANE_OFFSET_KCPS 0x0016U #define VL53L4CD_REG_XTALK_X_PLANE_GRADIENT_KCPS 0x0018U #define VL53L4CD_REG_XTALK_Y_PLANE_GRADIENT_KCPS 0x001AU #define VL53L4CD_REG_RANGE_OFFSET_MM 0x001EU #define VL53L4CD_REG_INNER_OFFSET_MM 0x0020U #define VL53L4CD_REG_OUTER_OFFSET_MM 0x0022U #define VL53L4CD_REG_GPIO_HV_MUX_CTRL 0x0030U #define VL53L4CD_REG_GPIO_TIO_HV_STATUS 0x0031U #define VL53L4CD_REG_SYSTEM_INTERRUPT 0x0046U #define VL53L4CD_REG_RANGE_CONFIG_A 0x005EU #define VL53L4CD_REG_RANGE_CONFIG_B 0x0061U #define VL53L4CD_REG_SIGMA_THRESHOLD 0x0064U #define VL53L4CD_REG_MIN_COUNT_RATE_RTN_LIMIT 0x0066U #define VL53L4CD_REG_INTERMEASUREMENT_MS 0x006CU #define VL53L4CD_REG_THRESH_HIGH 0x0072U #define VL53L4CD_REG_THRESH_LOW 0x0074U #define VL53L4CD_REG_SYSTEM_INTERRUPT_CLEAR 0x0086U #define VL53L4CD_REG_SYSTEM_START 0x0087U #define VL53L4CD_REG_RESULT_RANGE_STATUS 0x0089U #define VL53L4CD_REG_RESULT_SPAD_NB 0x008CU #define VL53L4CD_REG_RESULT_SIGNAL_RATE 0x008EU #define VL53L4CD_REG_RESULT_AMBIENT_RATE 0x0090U #define VL53L4CD_REG_RESULT_SIGMA 0x0092U #define VL53L4CD_REG_RESULT_DISTANCE 0x0096U #define VL53L4CD_REG_RESULT_OSC_CALIBRATE_VAL 0x00DEU #define VL53L4CD_REG_FIRMWARE_SYSTEM_STATUS 0x00E5U #define VL53L4CD_REG_IDENTIFICATION_MODEL_ID 0x010FU /* 等待固件启动 / 数据就绪的最大时间 */ #define VL53L4CD_BOOT_TIMEOUT_MS 200U #define VL53L4CD_DATA_TIMEOUT_MS 500U /* 一次结果块读包含的字节数:0x89..0x97 */ #define VL53L4CD_RESULT_BLOCK_SIZE 15U /* 测距状态码(已由原始状态映射为用户可读状态) */ typedef enum { VL53L4CD_STATUS_RANGE_VALID = 0, /* 测距有效 */ VL53L4CD_STATUS_SIGMA_FAIL, /* Sigma 超限 */ VL53L4CD_STATUS_SIGNAL_FAIL, /* 信号强度不足 */ VL53L4CD_STATUS_MIN_RANGE_FAIL, /* 目标过近 */ VL53L4CD_STATUS_PHASE_FAIL, /* 相位故障 */ VL53L4CD_STATUS_HW_FAIL, /* 硬件故障 */ VL53L4CD_STATUS_NO_TARGET, /* 未检测到目标 */ VL53L4CD_STATUS_SIGNAL_FAIL_NEAR, /* 近距离信号不足 */ VL53L4CD_STATUS_OUT_OF_BOUNDS, /* 超出边界 */ VL53L4CD_STATUS_XTALK_SIGNAL_FAIL, /* 串扰信号失败 */ VL53L4CD_STATUS_LOW_SIGNAL_FAIL, /* 低信号失败 */ VL53L4CD_STATUS_CROSSTALK_SIGNAL_FAIL,/* 串扰信号失败 */ VL53L4CD_STATUS_AMBIENT_SIGNAL_FAIL, /* 环境光信号失败 */ VL53L4CD_STATUS_SNSPD_AMBIENT_FAIL, /* 单光子雪崩二极管环境光失败 */ VL53L4CD_STATUS_UNKNOWN = 255 /* 未知状态 */ } vl53l4cd_range_status_t; /* 单次测量结果 */ typedef struct { uint16_t distance_mm; /* 距离,单位 mm */ uint8_t range_status; /* 测距状态码 */ uint8_t number_of_spad; /* 有效 SPAD 数 */ uint32_t signal_rate_kcps; /* 信号速率,单位 kcps */ uint32_t ambient_rate_kcps; /* 环境光速率,单位 kcps */ uint32_t signal_per_spad_kcps; /* 每 SPAD 信号速率 */ uint32_t ambient_per_spad_kcps; /* 每 SPAD 环境光速率 */ uint16_t sigma_mm; /* Sigma,单位 mm */ } vl53l4cd_result_t; /** * @brief 初始化 VL53L4CD * @param[in] none * @retval true: 初始化成功; false: 初始化失败 */ bool vl53l4cd_init(void); /** * @brief 启动连续测距 * @param[in] none * @retval true: 启动成功; false: 启动失败 */ bool vl53l4cd_start_ranging(void); /** * @brief 停止连续测距 * @param[in] none * @retval true: 停止成功; false: 停止失败 */ bool vl53l4cd_stop_ranging(void); /** * @brief 检查是否有新测距结果 * @param[in] none * @retval true: 有新结果; false: 无新结果或读取失败 */ bool vl53l4cd_data_ready(void); /** * @brief 清除测距完成中断 * @param[in] none * @retval true: 清除成功; false: 清除失败 */ bool vl53l4cd_clear_interrupt(void); /** * @brief 读取并解析一次测距结果 * @param[out] result: 结果结构体指针 * @retval true: 读取成功; false: 读取失败 */ bool vl53l4cd_get_result(vl53l4cd_result_t *result); /** * @brief 设置测距时序预算和测距周期 * @param[in] timing_budget_ms: 10..200 ms * @param[in] inter_measurement_ms: 当前驱动只支持 0(连续模式) * @retval true: 设置成功; false: 参数无效或设置失败 */ bool vl53l4cd_set_range_timing(uint8_t timing_budget_ms, uint32_t inter_measurement_ms); /** * @brief 写入手动指定的距离偏移量 * @param[in] offset_mm: 偏移量,单位 mm,可为负 * @retval true: 成功; false: 失败 */ bool vl53l4cd_set_offset(int16_t offset_mm); /** * @brief 写入串扰(玻璃反射)补偿值,透过玻璃测距时使用 * @details 写 XTALK_PLANE_OFFSET_KCPS (0x0016) 并将 X/Y 梯度寄存器清零, * 寄存器值为 xtalk_kcps * 512 * @param[in] xtalk_kcps: 串扰补偿值,单位 kcps,范围 0..127 * @retval true: 成功; false: 参数无效或写入失败 */ bool vl53l4cd_set_xtalk(uint16_t xtalk_kcps); /** * @brief 读取当前生效的串扰补偿值 * @param[out] xtalk_kcps: 返回串扰值,单位 kcps * @retval true: 成功; false: 失败 */ bool vl53l4cd_get_xtalk(uint16_t *xtalk_kcps); /** * @brief 读取当前生效的距离偏移量 * @param[out] offset_mm: 返回偏移量,单位 mm * @retval true: 成功; false: 失败 */ bool vl53l4cd_get_offset(int16_t *offset_mm); /** * @brief 以当前目标执行一次偏移校准 * @param[in] target_distance_mm: 目标实际距离,单位 mm,范围 10..1000 * @param[in] num_samples: 有效采样次数,范围 5..255 * @param[out] measured_offset_mm: 计算得到的偏移量,单位 mm * @retval true: 校准并写入成功; false: 失败 */ bool vl53l4cd_calibrate_offset(uint16_t target_distance_mm, uint16_t num_samples, int16_t *measured_offset_mm); /** * @brief 执行一次串扰校准(透过玻璃安装时使用) * @details 参照 ST ULD vl53l4cd_calibration.c 的 CalibrateXtalk 流程,定点数实现: * 先清零串扰补偿,热机 10 帧,然后采样有效测距帧, * xtalk = (1 - 平均距离/目标距离) * 平均信号/平均SPAD数,上限 127 kcps。 * 校准期间传感器被独占,主循环上报会暂停。 * @param[in] target_distance_mm: 玻璃后方目标的实际距离,单位 mm,范围 10..5000 * @param[in] num_samples: 采样次数,范围 5..255,ST 建议至少 10 * @param[out] measured_xtalk_kcps: 计算得到的串扰值,单位 kcps * @retval true: 校准并写入成功; false: 失败(含有效样本不足或串扰超限) */ bool vl53l4cd_calibrate_xtalk(uint16_t target_distance_mm, uint16_t num_samples, uint16_t *measured_xtalk_kcps); /** * @brief 读一个 8 位寄存器 * @param[in] reg: 16 位寄存器地址 * @param[out] value: 返回值指针 * @retval true: 成功; false: 失败 */ bool vl53l4cd_read_reg8(uint16_t reg, uint8_t *value); /** * @brief 读一个 16 位寄存器 * @param[in] reg: 16 位寄存器地址 * @param[out] value: 返回值指针 * @retval true: 成功; false: 失败 */ bool vl53l4cd_read_reg16(uint16_t reg, uint16_t *value); /** * @brief 写一个 8 位寄存器 * @param[in] reg: 16 位寄存器地址 * @param[in] value: 写入值 * @retval true: 成功; false: 失败 */ bool vl53l4cd_write_reg8(uint16_t reg, uint8_t value); /** * @brief 写一个 16 位寄存器 * @param[in] reg: 16 位寄存器地址 * @param[in] value: 写入值 * @retval true: 成功; false: 失败 */ bool vl53l4cd_write_reg16(uint16_t reg, uint16_t value); #endif /* VL53L4CD_DRIVER_H */