1.0
This commit is contained in:
55
App/VL53L0X_API/platform/README.md
Normal file
55
App/VL53L0X_API/platform/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# VL53L0X 多传感器模板(STM32H743 + FreeRTOS)
|
||||
|
||||
这组模板按固定顺序组织 4 颗 VL53L0X:
|
||||
|
||||
1. 左上
|
||||
2. 左下
|
||||
3. 右上
|
||||
4. 右下
|
||||
|
||||
## 文件说明
|
||||
|
||||
- `vl53l0x_platform.h/.c`
|
||||
- ST 官方 API 的平台适配层
|
||||
- 不再把 `hi2c1` 硬编码到驱动里
|
||||
- 读写失败时不会污染 `RdWord/RdDWord` 输出
|
||||
- `PollingDelay()` 在调度器已启动时使用 `vTaskDelay()`
|
||||
|
||||
- `vl53_board.h/.c`
|
||||
- 4 颗 VL53L0X 的板级管理层
|
||||
- 负责 `XSHUT` 拉低/逐个拉起/逐个改地址
|
||||
- 默认运行地址:0x54 / 0x56 / 0x58 / 0x5A(8-bit 写法)
|
||||
|
||||
- `vl53_task.h/.c`
|
||||
- FreeRTOS 任务骨架
|
||||
- 10ms 周期轮询一遍 4 颗传感器
|
||||
- 采集结果写成一个快照,避免上层散读散写
|
||||
|
||||
## 你需要改的地方
|
||||
|
||||
只要改 `vl53_board.c` 里的 `g_vl53_hw_cfg[]`:
|
||||
|
||||
- `hi2c`
|
||||
- `xshut_port`
|
||||
- `xshut_pin`
|
||||
- `gpio1_port` / `gpio1_pin`(如果暂时不用中断,可保持 `NULL/0`)
|
||||
|
||||
## 集成方式
|
||||
|
||||
1. 保留 ST 官方 API 的 `vl53l0x_api*.c`、`vl53l0x_def.h` 等核心文件不动。
|
||||
2. 用本模板替换你原来的 `vl53l0x_platform.h/.c`。
|
||||
3. 新增 `vl53_board.*` 和 `vl53_task.*` 到 `App/sensors/` 或你自己的目录。
|
||||
4. 在 CubeMX 里保留任务壳函数,在任务壳里调用 `AppVl53_TaskLoop()`。
|
||||
5. 不要把 VL53 逻辑塞进你 20ms 的 `canTxTask`。
|
||||
|
||||
## 建议任务频率
|
||||
|
||||
- `canTxTask`: 保持 20ms
|
||||
- `vl53Task`: 10ms 唤醒,内部读 ready 后取数
|
||||
- 估计/控制:50–100Hz
|
||||
|
||||
## 备注
|
||||
|
||||
- 地址写法用的是 **8-bit**,默认地址是 `0x52`。
|
||||
- 多颗同总线时,必须所有器件先 `XSHUT=RESET`,然后逐个拉起并改地址。
|
||||
- 这版模板默认走“单任务采集 + 快照共享”,适合你当前的 ASER 架构。
|
||||
166
App/VL53L0X_API/platform/vl53_board.c
Normal file
166
App/VL53L0X_API/platform/vl53_board.c
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "vl53_board.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "robot_params.h"
|
||||
|
||||
/* ================= 卡尔曼滤波底层实现 ================= */
|
||||
static void vl53_kalman_init(Vl53Kalman_t *kf, float q, float r) {
|
||||
kf->x = 0.0f;
|
||||
kf->p = 1.0f;
|
||||
kf->q = q;
|
||||
kf->r = r;
|
||||
kf->initialized = 0;
|
||||
}
|
||||
|
||||
static float vl53_kalman_update(Vl53Kalman_t *kf, float measurement) {
|
||||
if (kf->initialized == 0) {
|
||||
kf->x = measurement;
|
||||
kf->initialized = 1;
|
||||
return kf->x;
|
||||
}
|
||||
kf->p = kf->p + kf->q;
|
||||
float k = kf->p / (kf->p + kf->r);
|
||||
kf->x = kf->x + k * (measurement - kf->x);
|
||||
kf->p = (1.0f - k) * kf->p;
|
||||
return kf->x;
|
||||
}
|
||||
|
||||
/* ================= ST 官方配置序列 ================= */
|
||||
static VL53L0X_Error vl53_do_static_init(VL53L0X_DEV dev, uint32_t timing_budget_us)
|
||||
{
|
||||
VL53L0X_Error status;
|
||||
uint32_t ref_spad_count = 0u;
|
||||
uint8_t is_aperture_spads = 0u;
|
||||
uint8_t vhv_settings = 0u;
|
||||
uint8_t phase_cal = 0u;
|
||||
|
||||
status = VL53L0X_StaticInit(dev);
|
||||
if (status != VL53L0X_ERROR_NONE) return status;
|
||||
|
||||
status = VL53L0X_PerformRefSpadManagement(dev, &ref_spad_count, &is_aperture_spads);
|
||||
if (status != VL53L0X_ERROR_NONE) return status;
|
||||
|
||||
status = VL53L0X_PerformRefCalibration(dev, &vhv_settings, &phase_cal);
|
||||
if (status != VL53L0X_ERROR_NONE) return status;
|
||||
|
||||
status = VL53L0X_SetDeviceMode(dev, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING);
|
||||
if (status != VL53L0X_ERROR_NONE) return status;
|
||||
|
||||
status = VL53L0X_SetMeasurementTimingBudgetMicroSeconds(dev, timing_budget_us);
|
||||
if (status != VL53L0X_ERROR_NONE) return status;
|
||||
|
||||
status = VL53L0X_SetLimitCheckEnable(dev, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 1u);
|
||||
if (status != VL53L0X_ERROR_NONE) return status;
|
||||
|
||||
status = VL53L0X_SetLimitCheckEnable(dev, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 1u);
|
||||
if (status != VL53L0X_ERROR_NONE) return status;
|
||||
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* ================= 核心管理器 API ================= */
|
||||
VL53L0X_Error Vl53Board_Init(Vl53Board_t *board, const Vl53BoardHwCfg_t *hw_cfgs, uint8_t count, uint32_t timing_budget_us)
|
||||
{
|
||||
if ((board == NULL) || (hw_cfgs == NULL) || (count == 0) || (count > VL53_MAX_DEVS_PER_BOARD)) {
|
||||
return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
memset(board, 0, sizeof(Vl53Board_t));
|
||||
board->dev_count = count;
|
||||
board->timing_budget_us = (timing_budget_us == 0u) ? 33000u : timing_budget_us;
|
||||
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
board->dev[i].name = hw_cfgs[i].name;
|
||||
board->dev[i].id = hw_cfgs[i].id;
|
||||
board->dev[i].comms_type = 1u;
|
||||
board->dev[i].comms_speed_khz = 400u;
|
||||
board->dev[i].is_present = 0u;
|
||||
|
||||
VL53L0X_PlatformAttachBus(&board->dev[i], hw_cfgs[i].hi2c, VL53L0X_DEFAULT_ADDR_8BIT, 100u, NULL);
|
||||
VL53L0X_PlatformAttachPins(&board->dev[i], hw_cfgs[i].xshut_port, hw_cfgs[i].xshut_pin, NULL, 0);
|
||||
|
||||
VL53L0X_PlatformSetXShut(&board->dev[i], GPIO_PIN_RESET);
|
||||
|
||||
/* 初始化卡尔曼滤波器:Q/R 从 robot_params.h 读取 */
|
||||
vl53_kalman_init(&board->kf[i], PARAM_VL53_KALMAN_Q, PARAM_VL53_KALMAN_R);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
if (VL53L0X_PlatformSetXShut(&board->dev[i], GPIO_PIN_SET) != VL53L0X_ERROR_NONE) continue;
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
|
||||
board->dev[i].I2cDevAddr = VL53L0X_DEFAULT_ADDR_8BIT;
|
||||
if (VL53L0X_PlatformChangeAddress(&board->dev[i], hw_cfgs[i].runtime_addr_8bit) != VL53L0X_ERROR_NONE) continue;
|
||||
if (VL53L0X_DataInit(&board->dev[i]) != VL53L0X_ERROR_NONE) continue;
|
||||
if (vl53_do_static_init(&board->dev[i], board->timing_budget_us) != VL53L0X_ERROR_NONE) continue;
|
||||
|
||||
board->init_mask |= (uint8_t)(1u << i);
|
||||
board->dev[i].is_present = 1u;
|
||||
}
|
||||
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
VL53L0X_Error Vl53Board_StartContinuous(Vl53Board_t *board)
|
||||
{
|
||||
if (board == NULL) return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
for (uint8_t i = 0; i < board->dev_count; i++) {
|
||||
if (board->init_mask & (1u << i)) VL53L0X_StartMeasurement(&board->dev[i]);
|
||||
}
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
VL53L0X_Error Vl53Board_StopContinuous(Vl53Board_t *board)
|
||||
{
|
||||
if (board == NULL) return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
for (uint8_t i = 0; i < board->dev_count; i++) {
|
||||
if (board->init_mask & (1u << i)) VL53L0X_StopMeasurement(&board->dev[i]);
|
||||
}
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
VL53L0X_Error Vl53Board_ReadAll(Vl53Board_t *board, Vl53BoardSnapshot_t *snapshot)
|
||||
{
|
||||
if (board == NULL || snapshot == NULL) return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
|
||||
memset(snapshot, 0, sizeof(Vl53BoardSnapshot_t));
|
||||
snapshot->tick_ms = xTaskGetTickCount() * portTICK_PERIOD_MS;
|
||||
|
||||
for (uint8_t i = 0; i < board->dev_count; i++) {
|
||||
if ((board->init_mask & (1u << i)) == 0u) {
|
||||
snapshot->range_status[i] = 255u;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t ready = 0u;
|
||||
if (VL53L0X_GetMeasurementDataReady(&board->dev[i], &ready) != VL53L0X_ERROR_NONE) continue;
|
||||
|
||||
if (ready) {
|
||||
VL53L0X_RangingMeasurementData_t data;
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
if (VL53L0X_GetRangingMeasurementData(&board->dev[i], &data) == VL53L0X_ERROR_NONE) {
|
||||
/* 1. 写入原始数据 */
|
||||
snapshot->range_mm[i] = data.RangeMilliMeter;
|
||||
snapshot->range_status[i] = data.RangeStatus;
|
||||
|
||||
if (data.RangeStatus == 0u) {
|
||||
/* 2. 标记有效并更新卡尔曼滤波器 */
|
||||
snapshot->valid_mask |= (1u << i);
|
||||
snapshot->range_mm_filtered[i] = vl53_kalman_update(&board->kf[i], (float)data.RangeMilliMeter);
|
||||
} else {
|
||||
/* 测距失败时,滤波值维持上一次的历史最佳估计不变 */
|
||||
snapshot->range_mm_filtered[i] = board->kf[i].x;
|
||||
}
|
||||
|
||||
VL53L0X_ClearInterruptMask(&board->dev[i], 0u);
|
||||
}
|
||||
} else {
|
||||
/* 如果没准备好,把上一帧的历史值顺延下来,防止读到 0 */
|
||||
snapshot->range_mm_filtered[i] = board->kf[i].x;
|
||||
}
|
||||
}
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
59
App/VL53L0X_API/platform/vl53_board.h
Normal file
59
App/VL53L0X_API/platform/vl53_board.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef VL53_BOARD_H
|
||||
#define VL53_BOARD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "vl53l0x_api.h"
|
||||
#include "vl53l0x_platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define VL53_MAX_DEVS_PER_BOARD 4
|
||||
|
||||
typedef struct {
|
||||
I2C_HandleTypeDef *hi2c;
|
||||
GPIO_TypeDef *xshut_port;
|
||||
uint16_t xshut_pin;
|
||||
uint8_t runtime_addr_8bit;
|
||||
const char *name;
|
||||
uint8_t id;
|
||||
} Vl53BoardHwCfg_t;
|
||||
|
||||
/* ================= 内部卡尔曼滤波器结构 ================= */
|
||||
typedef struct {
|
||||
float x; // 最优估计值 (滤波后的距离)
|
||||
float p; // 估计误差协方差
|
||||
float q; // 过程噪声
|
||||
float r; // 测量噪声
|
||||
uint8_t initialized; // 防止第一次开机从0缓慢爬升
|
||||
} Vl53Kalman_t;
|
||||
|
||||
/* ================= 快照数据结构 (对外接口) ================= */
|
||||
typedef struct {
|
||||
uint32_t tick_ms;
|
||||
uint16_t range_mm[VL53_MAX_DEVS_PER_BOARD]; /* 接口1:原始硬件数据 */
|
||||
float range_mm_filtered[VL53_MAX_DEVS_PER_BOARD]; /* 接口2:卡尔曼平滑数据 */
|
||||
uint8_t range_status[VL53_MAX_DEVS_PER_BOARD];
|
||||
uint8_t valid_mask;
|
||||
} Vl53BoardSnapshot_t;
|
||||
|
||||
typedef struct {
|
||||
VL53L0X_Dev_t dev[VL53_MAX_DEVS_PER_BOARD];
|
||||
Vl53Kalman_t kf[VL53_MAX_DEVS_PER_BOARD]; /* 每个传感器配备一个专属卡尔曼滤波器 */
|
||||
uint8_t init_mask;
|
||||
uint8_t dev_count;
|
||||
uint32_t timing_budget_us;
|
||||
} Vl53Board_t;
|
||||
|
||||
VL53L0X_Error Vl53Board_Init(Vl53Board_t *board, const Vl53BoardHwCfg_t *hw_cfgs, uint8_t count, uint32_t timing_budget_us);
|
||||
VL53L0X_Error Vl53Board_StartContinuous(Vl53Board_t *board);
|
||||
VL53L0X_Error Vl53Board_StopContinuous(Vl53Board_t *board);
|
||||
VL53L0X_Error Vl53Board_ReadAll(Vl53Board_t *board, Vl53BoardSnapshot_t *snapshot);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VL53_BOARD_H */
|
||||
315
App/VL53L0X_API/platform/vl53l0x_platform.c
Normal file
315
App/VL53L0X_API/platform/vl53l0x_platform.c
Normal file
@@ -0,0 +1,315 @@
|
||||
#include "vl53l0x_platform.h"
|
||||
#include "vl53l0x_api.h"
|
||||
|
||||
#if VL53_USE_FREERTOS_DELAY
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#endif
|
||||
|
||||
#if defined(configSUPPORT_STATIC_ALLOCATION) || defined(configUSE_MUTEXES)
|
||||
#include "semphr.h"
|
||||
#define VL53_USE_FREERTOS_MUTEX 1
|
||||
#else
|
||||
#define VL53_USE_FREERTOS_MUTEX 0
|
||||
#endif
|
||||
|
||||
static VL53L0X_Error vl53_hal_to_pal(HAL_StatusTypeDef hal_status)
|
||||
{
|
||||
switch (hal_status) {
|
||||
case HAL_OK:
|
||||
return VL53L0X_ERROR_NONE;
|
||||
case HAL_TIMEOUT:
|
||||
return VL53L0X_ERROR_TIME_OUT;
|
||||
default:
|
||||
return VL53L0X_ERROR_CONTROL_INTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
static VL53L0X_Error vl53_validate_dev(VL53L0X_DEV Dev)
|
||||
{
|
||||
if ((Dev == NULL) || (Dev->hi2c == NULL)) {
|
||||
return VL53L0X_ERROR_CONTROL_INTERFACE;
|
||||
}
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
static VL53L0X_Error vl53_bus_lock(VL53L0X_DEV Dev)
|
||||
{
|
||||
#if VL53_USE_FREERTOS_MUTEX
|
||||
if ((Dev != NULL) && (Dev->bus_lock != NULL)) {
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
const TickType_t wait_ticks = pdMS_TO_TICKS((Dev->io_timeout_ms == 0u) ? 10u : Dev->io_timeout_ms);
|
||||
if (xSemaphoreTake((SemaphoreHandle_t)Dev->bus_lock, wait_ticks) != pdTRUE) {
|
||||
return VL53L0X_ERROR_TIME_OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)Dev;
|
||||
#endif
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
static void vl53_bus_unlock(VL53L0X_DEV Dev)
|
||||
{
|
||||
#if VL53_USE_FREERTOS_MUTEX
|
||||
if ((Dev != NULL) && (Dev->bus_lock != NULL)) {
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
(void)xSemaphoreGive((SemaphoreHandle_t)Dev->bus_lock);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)Dev;
|
||||
#endif
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_LockSequenceAccess(VL53L0X_DEV Dev)
|
||||
{
|
||||
(void)Dev;
|
||||
/* Shared I2C bus is already serialized per I/O transaction below. */
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_UnlockSequenceAccess(VL53L0X_DEV Dev)
|
||||
{
|
||||
(void)Dev;
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
void VL53L0X_PlatformAttachBus(VL53L0X_DEV Dev,
|
||||
I2C_HandleTypeDef *hi2c,
|
||||
uint8_t i2c_addr_8bit,
|
||||
uint16_t io_timeout_ms,
|
||||
void *bus_lock)
|
||||
{
|
||||
if (Dev == NULL) {
|
||||
return;
|
||||
}
|
||||
Dev->hi2c = hi2c;
|
||||
Dev->I2cDevAddr = i2c_addr_8bit;
|
||||
Dev->io_timeout_ms = (io_timeout_ms == 0u) ? 100u : io_timeout_ms;
|
||||
Dev->bus_lock = bus_lock;
|
||||
}
|
||||
|
||||
void VL53L0X_PlatformAttachPins(VL53L0X_DEV Dev,
|
||||
GPIO_TypeDef *xshut_port,
|
||||
uint16_t xshut_pin,
|
||||
GPIO_TypeDef *gpio1_port,
|
||||
uint16_t gpio1_pin)
|
||||
{
|
||||
if (Dev == NULL) {
|
||||
return;
|
||||
}
|
||||
Dev->xshut_port = xshut_port;
|
||||
Dev->xshut_pin = xshut_pin;
|
||||
Dev->gpio1_port = gpio1_port;
|
||||
Dev->gpio1_pin = gpio1_pin;
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_PlatformSetXShut(VL53L0X_DEV Dev, GPIO_PinState state)
|
||||
{
|
||||
if ((Dev == NULL) || (Dev->xshut_port == NULL)) {
|
||||
return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
}
|
||||
HAL_GPIO_WritePin(Dev->xshut_port, Dev->xshut_pin, state);
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_PlatformBootDevice(VL53L0X_DEV Dev, uint32_t reset_low_ms, uint32_t boot_wait_ms)
|
||||
{
|
||||
VL53L0X_Error status = VL53L0X_PlatformSetXShut(Dev, GPIO_PIN_RESET);
|
||||
if (status != VL53L0X_ERROR_NONE) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
vTaskDelay(pdMS_TO_TICKS(reset_low_ms));
|
||||
} else {
|
||||
HAL_Delay(reset_low_ms);
|
||||
}
|
||||
|
||||
status = VL53L0X_PlatformSetXShut(Dev, GPIO_PIN_SET);
|
||||
if (status != VL53L0X_ERROR_NONE) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
vTaskDelay(pdMS_TO_TICKS(boot_wait_ms));
|
||||
} else {
|
||||
HAL_Delay(boot_wait_ms);
|
||||
}
|
||||
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
uint32_t VL53L0X_PlatformGetTick(void)
|
||||
{
|
||||
return HAL_GetTick();
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_WriteMulti(VL53L0X_DEV Dev, uint8_t index, uint8_t *pdata, uint32_t count)
|
||||
{
|
||||
HAL_StatusTypeDef hal_status;
|
||||
VL53L0X_Error status;
|
||||
|
||||
if ((pdata == NULL) || (count == 0u) || (count > 255u)) {
|
||||
return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
}
|
||||
status = vl53_validate_dev(Dev);
|
||||
if (status != VL53L0X_ERROR_NONE) {
|
||||
return status;
|
||||
}
|
||||
status = vl53_bus_lock(Dev);
|
||||
if (status != VL53L0X_ERROR_NONE) {
|
||||
return status;
|
||||
}
|
||||
|
||||
hal_status = HAL_I2C_Mem_Write(Dev->hi2c,
|
||||
Dev->I2cDevAddr,
|
||||
index,
|
||||
I2C_MEMADD_SIZE_8BIT,
|
||||
pdata,
|
||||
(uint16_t)count,
|
||||
Dev->io_timeout_ms);
|
||||
vl53_bus_unlock(Dev);
|
||||
return vl53_hal_to_pal(hal_status);
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_ReadMulti(VL53L0X_DEV Dev, uint8_t index, uint8_t *pdata, uint32_t count)
|
||||
{
|
||||
HAL_StatusTypeDef hal_status;
|
||||
VL53L0X_Error status;
|
||||
|
||||
if ((pdata == NULL) || (count == 0u) || (count > 255u)) {
|
||||
return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
}
|
||||
status = vl53_validate_dev(Dev);
|
||||
if (status != VL53L0X_ERROR_NONE) {
|
||||
return status;
|
||||
}
|
||||
status = vl53_bus_lock(Dev);
|
||||
if (status != VL53L0X_ERROR_NONE) {
|
||||
return status;
|
||||
}
|
||||
|
||||
hal_status = HAL_I2C_Mem_Read(Dev->hi2c,
|
||||
Dev->I2cDevAddr,
|
||||
index,
|
||||
I2C_MEMADD_SIZE_8BIT,
|
||||
pdata,
|
||||
(uint16_t)count,
|
||||
Dev->io_timeout_ms);
|
||||
vl53_bus_unlock(Dev);
|
||||
return vl53_hal_to_pal(hal_status);
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_WrByte(VL53L0X_DEV Dev, uint8_t index, uint8_t data)
|
||||
{
|
||||
return VL53L0X_WriteMulti(Dev, index, &data, 1u);
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_WrWord(VL53L0X_DEV Dev, uint8_t index, uint16_t data)
|
||||
{
|
||||
uint8_t buffer[2];
|
||||
buffer[0] = (uint8_t)(data >> 8);
|
||||
buffer[1] = (uint8_t)(data & 0xFFu);
|
||||
return VL53L0X_WriteMulti(Dev, index, buffer, 2u);
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_WrDWord(VL53L0X_DEV Dev, uint8_t index, uint32_t data)
|
||||
{
|
||||
uint8_t buffer[4];
|
||||
buffer[0] = (uint8_t)(data >> 24);
|
||||
buffer[1] = (uint8_t)(data >> 16);
|
||||
buffer[2] = (uint8_t)(data >> 8);
|
||||
buffer[3] = (uint8_t)(data & 0xFFu);
|
||||
return VL53L0X_WriteMulti(Dev, index, buffer, 4u);
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_RdByte(VL53L0X_DEV Dev, uint8_t index, uint8_t *data)
|
||||
{
|
||||
if (data == NULL) {
|
||||
return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
}
|
||||
return VL53L0X_ReadMulti(Dev, index, data, 1u);
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_RdWord(VL53L0X_DEV Dev, uint8_t index, uint16_t *data)
|
||||
{
|
||||
uint8_t buffer[2] = {0u, 0u};
|
||||
VL53L0X_Error status;
|
||||
|
||||
if (data == NULL) {
|
||||
return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
}
|
||||
status = VL53L0X_ReadMulti(Dev, index, buffer, 2u);
|
||||
if (status == VL53L0X_ERROR_NONE) {
|
||||
*data = (((uint16_t)buffer[0]) << 8) | buffer[1];
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_RdDWord(VL53L0X_DEV Dev, uint8_t index, uint32_t *data)
|
||||
{
|
||||
uint8_t buffer[4] = {0u, 0u, 0u, 0u};
|
||||
VL53L0X_Error status;
|
||||
|
||||
if (data == NULL) {
|
||||
return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
}
|
||||
status = VL53L0X_ReadMulti(Dev, index, buffer, 4u);
|
||||
if (status == VL53L0X_ERROR_NONE) {
|
||||
*data = (((uint32_t)buffer[0]) << 24)
|
||||
| (((uint32_t)buffer[1]) << 16)
|
||||
| (((uint32_t)buffer[2]) << 8)
|
||||
| ((uint32_t)buffer[3]);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_UpdateByte(VL53L0X_DEV Dev, uint8_t index, uint8_t AndData, uint8_t OrData)
|
||||
{
|
||||
VL53L0X_Error status;
|
||||
uint8_t data = 0u;
|
||||
|
||||
status = VL53L0X_RdByte(Dev, index, &data);
|
||||
if (status != VL53L0X_ERROR_NONE) {
|
||||
return status;
|
||||
}
|
||||
data = (uint8_t)((data & AndData) | OrData);
|
||||
return VL53L0X_WrByte(Dev, index, data);
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_PollingDelay(VL53L0X_DEV Dev)
|
||||
{
|
||||
(void)Dev;
|
||||
#if VL53_USE_FREERTOS_DELAY
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
vTaskDelay(pdMS_TO_TICKS(2u));
|
||||
} else {
|
||||
HAL_Delay(2u);
|
||||
}
|
||||
#else
|
||||
HAL_Delay(2u);
|
||||
#endif
|
||||
return VL53L0X_ERROR_NONE;
|
||||
}
|
||||
|
||||
VL53L0X_Error VL53L0X_PlatformChangeAddress(VL53L0X_DEV Dev, uint8_t new_addr_8bit)
|
||||
{
|
||||
VL53L0X_Error status;
|
||||
|
||||
if (new_addr_8bit == 0u) {
|
||||
return VL53L0X_ERROR_INVALID_PARAMS;
|
||||
}
|
||||
status = VL53L0X_SetDeviceAddress(Dev, new_addr_8bit);
|
||||
if (status == VL53L0X_ERROR_NONE) {
|
||||
Dev->I2cDevAddr = new_addr_8bit;
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
vTaskDelay(pdMS_TO_TICKS(2u));
|
||||
} else {
|
||||
HAL_Delay(2u);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
89
App/VL53L0X_API/platform/vl53l0x_platform.h
Normal file
89
App/VL53L0X_API/platform/vl53l0x_platform.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef VL53L0X_PLATFORM_H
|
||||
#define VL53L0X_PLATFORM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "main.h"
|
||||
|
||||
#ifndef VL53L0X_SINGLE_DEVICE_DRIVER
|
||||
#define VL53L0X_SINGLE_DEVICE_DRIVER 0
|
||||
#endif
|
||||
|
||||
#include "vl53l0x_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef VL53_USE_FREERTOS_DELAY
|
||||
#define VL53_USE_FREERTOS_DELAY 1
|
||||
#endif
|
||||
|
||||
#ifndef VL53L0X_COPYSTRING
|
||||
#define VL53L0X_COPYSTRING(dst, src) strcpy((dst), (src))
|
||||
#endif
|
||||
|
||||
#ifndef VL53L0X_DEFAULT_ADDR_8BIT
|
||||
#define VL53L0X_DEFAULT_ADDR_8BIT 0x52u
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
VL53L0X_DevData_t Data;
|
||||
uint8_t I2cDevAddr; /* ST API expects 8-bit address, default 0x52 */
|
||||
uint8_t comms_type;
|
||||
uint16_t comms_speed_khz;
|
||||
|
||||
I2C_HandleTypeDef *hi2c;
|
||||
GPIO_TypeDef *xshut_port;
|
||||
uint16_t xshut_pin;
|
||||
GPIO_TypeDef *gpio1_port; /* optional */
|
||||
uint16_t gpio1_pin;
|
||||
|
||||
void *bus_lock; /* optional shared mutex/lock handle */
|
||||
const char *name;
|
||||
uint8_t id; /* user label: 1=左上, 2=左下, 3=右上, 4=右下 */
|
||||
uint8_t is_present;
|
||||
uint16_t io_timeout_ms;
|
||||
} VL53L0X_Dev_t;
|
||||
|
||||
typedef VL53L0X_Dev_t* VL53L0X_DEV;
|
||||
|
||||
#define PALDevDataGet(Dev, field) ((Dev)->Data.field)
|
||||
#define PALDevDataSet(Dev, field, data) ((Dev)->Data.field = (data))
|
||||
|
||||
VL53L0X_Error VL53L0X_LockSequenceAccess(VL53L0X_DEV Dev);
|
||||
VL53L0X_Error VL53L0X_UnlockSequenceAccess(VL53L0X_DEV Dev);
|
||||
|
||||
VL53L0X_Error VL53L0X_WriteMulti(VL53L0X_DEV Dev, uint8_t index, uint8_t *pdata, uint32_t count);
|
||||
VL53L0X_Error VL53L0X_ReadMulti(VL53L0X_DEV Dev, uint8_t index, uint8_t *pdata, uint32_t count);
|
||||
VL53L0X_Error VL53L0X_WrByte(VL53L0X_DEV Dev, uint8_t index, uint8_t data);
|
||||
VL53L0X_Error VL53L0X_WrWord(VL53L0X_DEV Dev, uint8_t index, uint16_t data);
|
||||
VL53L0X_Error VL53L0X_WrDWord(VL53L0X_DEV Dev, uint8_t index, uint32_t data);
|
||||
VL53L0X_Error VL53L0X_RdByte(VL53L0X_DEV Dev, uint8_t index, uint8_t *data);
|
||||
VL53L0X_Error VL53L0X_RdWord(VL53L0X_DEV Dev, uint8_t index, uint16_t *data);
|
||||
VL53L0X_Error VL53L0X_RdDWord(VL53L0X_DEV Dev, uint8_t index, uint32_t *data);
|
||||
VL53L0X_Error VL53L0X_UpdateByte(VL53L0X_DEV Dev, uint8_t index, uint8_t AndData, uint8_t OrData);
|
||||
VL53L0X_Error VL53L0X_PollingDelay(VL53L0X_DEV Dev);
|
||||
|
||||
void VL53L0X_PlatformAttachBus(VL53L0X_DEV Dev,
|
||||
I2C_HandleTypeDef *hi2c,
|
||||
uint8_t i2c_addr_8bit,
|
||||
uint16_t io_timeout_ms,
|
||||
void *bus_lock);
|
||||
|
||||
void VL53L0X_PlatformAttachPins(VL53L0X_DEV Dev,
|
||||
GPIO_TypeDef *xshut_port,
|
||||
uint16_t xshut_pin,
|
||||
GPIO_TypeDef *gpio1_port,
|
||||
uint16_t gpio1_pin);
|
||||
|
||||
VL53L0X_Error VL53L0X_PlatformSetXShut(VL53L0X_DEV Dev, GPIO_PinState state);
|
||||
VL53L0X_Error VL53L0X_PlatformBootDevice(VL53L0X_DEV Dev, uint32_t reset_low_ms, uint32_t boot_wait_ms);
|
||||
VL53L0X_Error VL53L0X_PlatformChangeAddress(VL53L0X_DEV Dev, uint8_t new_addr_8bit);
|
||||
uint32_t VL53L0X_PlatformGetTick(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VL53L0X_PLATFORM_H */
|
||||
18
App/VL53L0X_API/platform/vl53l0x_platform_log.h
Normal file
18
App/VL53L0X_API/platform/vl53l0x_platform_log.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _VL53L0X_PLATFORM_LOG_H_
|
||||
#define _VL53L0X_PLATFORM_LOG_H_
|
||||
|
||||
/* 1. 解决 TRACE_MODULE_API 未定义的报错 */
|
||||
#define TRACE_MODULE_API 0
|
||||
|
||||
/* 2. 强行屏蔽官方所有【带下划线】的底层日志宏 */
|
||||
#define _LOG_FUNCTION_START(...) (void)0
|
||||
#define _LOG_FUNCTION_END(...) (void)0
|
||||
#define _LOG_FUNCTION_END_FMT(...) (void)0
|
||||
|
||||
/* 3. 强行屏蔽官方所有【不带下划线】的普通日志宏 */
|
||||
#define LOG_FUNCTION_START(...) (void)0
|
||||
#define LOG_FUNCTION_END(...) (void)0
|
||||
#define LOG_FUNCTION_END_FMT(...) (void)0
|
||||
#define VL53L0X_ErrLog(...) (void)0
|
||||
|
||||
#endif /* _VL53L0X_PLATFORM_LOG_H_ */
|
||||
15
App/VL53L0X_API/platform/vl53l0x_types.h
Normal file
15
App/VL53L0X_API/platform/vl53l0x_types.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _VL53L0X_TYPES_H_
|
||||
#define _VL53L0X_TYPES_H_
|
||||
|
||||
/* 引入现代 C 语言标准整数类型库 */
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
/* 核心修复:填补 ST 官方定义的定点数类型 */
|
||||
typedef uint32_t FixPoint1616_t;
|
||||
|
||||
#endif /* _VL53L0X_TYPES_H_ */
|
||||
Reference in New Issue
Block a user