前言
VL53L1CB是一款测距模块,根据飞行时间(Time of Flight,TOF)来测量距离。支持I2C接口。
硬件
芯片型号:STM32F405RGT6
硬件连接:I2C2(PB10,PB11),UART6(打印调试信息)
CUBEMX配置
这里除了时钟之外,需要配置的外设有跟VL53L1通信的I2C以及打印调试信息用的UART6。详细过程跳过。。。
驱动移植
- 驱动文件下载
首先是下载官方驱动
下载完解压出来后就是这三个文件夹,BareDriver是相关驱动代码和API,Docs是文档,Example是提供的一个例程。
2. 代码移植
这个版本的例程是用HAL库来实现的,为了快速移植,我选择参考Example中的例程来移植。
主要移植的是这些函数
首先将\VL53L1CB_BareDriver_6.6.15.2625\Example\Drivers\BSP\Components\vl53l1这个文件夹复制到自己的工程中
并且在工程中添加对应的c文件(vl53l1文件夹下的所有c文件)以及头文件路径
接着将VL53L1CB_BareDriver_6.6.15.2625\Example\Projects\STM32F401RE-Nucleo\Examples\53L1A2\SimpleRanging\Src文件夹下vl53l1_platform.c和vl53l1_platform_ipp.c文件以及VL53L1CB_BareDriver_6.6.15.2625\Example\Projects\STM32F401RE-Nucleo\Examples\53L1A2\SimpleRanging\Inc下的vl53l1开头的.h文件到自己的工程文件中。
这里我把所有跟vl53l1相关的代码都放在一个文件夹下
在工程中添加.c文件和头文件路径
3. 编译工程
发现会报错。原因是工程所用的芯片跟我所用的芯片不一样,stm32xxx_hal.h文件不同,因此只需要把报错的地方将stm32xxx_hal.h替换成对应的头文件即可。我这里用的芯片对应头文件是stm32f4xx_hal.h。将两处报错的地方给修改后,编译就没问题了。
4. 测试例程移植
定义全局变量和函数
/* USER CODE BEGIN 0 */
VL53L1_Dev_t dev;
VL53L1_DEV Dev = &dev;
int status;
volatile int IntCount;
uint8_t isInterrupt = 0;
void RangingLoop(void)
{
VL53L1_MultiRangingData_t MultiRangingData;
VL53L1_MultiRangingData_t *pMultiRangingData = &MultiRangingData;
uint8_t NewDataReady = 0;
int no_of_object_found = 0, j;
printf("Ranging loop starts\n");
status = VL53L1_WaitDeviceBooted(Dev);
status = VL53L1_DataInit(Dev);
status = VL53L1_StaticInit(Dev);
/* VL53L1_SetPresetMode function is mandatory to be called even if default PresetMode is the VL53L1_PRESETMODE_RANGING */
status = VL53L1_SetPresetMode(Dev, VL53L1_PRESETMODE_RANGING);
// status = VL53L1_SetDistanceMode(Dev, VL53L1_DISTANCEMODE_SHORT);
// status = VL53L1_SetMeasurementTimingBudgetMicroSeconds(Dev, 60000);
status = VL53L1_StartMeasurement(Dev);
if(status){
printf("VL53L1_StartMeasurement failed: error = %d \n", status);
while(1);
}
if (isInterrupt){
do // HW interrupt mode
{
__WFI();
if(IntCount !=0 ){
IntCount=0;
status = VL53L1_GetMultiRangingData(Dev, pMultiRangingData);
no_of_object_found=pMultiRangingData->NumberOfObjectsFound;
printf("Count=%5d, ", pMultiRangingData->StreamCount);
printf("#Objs=%1d ", no_of_object_found);
for(j=0;j<no_of_object_found;j++){
if(j!=0)printf("\r\n ");
printf("status=%d, D=%5dmm, Signal=%2.2f Mcps, Ambient=%2.2f Mcps",
pMultiRangingData->RangeData[j].RangeStatus,
pMultiRangingData->RangeData[j].RangeMilliMeter,
pMultiRangingData->RangeData[j].SignalRateRtnMegaCps/65536.0,
pMultiRangingData->RangeData[j].AmbientRateRtnMegaCps/65536.0);
}
printf ("\r\n");
if (status==0){
status = VL53L1_ClearInterruptAndStartMeasurement(Dev);
}
}
}
while(1);
}
else{
do{ // polling mode
status = VL53L1_GetMeasurementDataReady(Dev, &NewDataReady);
HAL_Delay(1);
if((!status)&&(NewDataReady!=0)){
status = VL53L1_GetMultiRangingData(Dev, pMultiRangingData);
no_of_object_found=pMultiRangingData->NumberOfObjectsFound;
printf("Count=%5d, ", pMultiRangingData->StreamCount);
printf("#Objs=%1d ", no_of_object_found);
for(j=0;j<no_of_object_found;j++){
if(j!=0)printf("\r\n");
printf("status=%d, D=%5dmm, Signal=%2.2f Mcps, Ambient=%2.2f Mcps",
pMultiRangingData->RangeData[j].RangeStatus,
pMultiRangingData->RangeData[j].RangeMilliMeter,
pMultiRangingData->RangeData[j].SignalRateRtnMegaCps/65536.0,
pMultiRangingData->RangeData[j].AmbientRateRtnMegaCps/65536.0);
}
printf ("\r\n");
if (status==0){
status = VL53L1_ClearInterruptAndStartMeasurement(Dev);
}
}
}
while (1);
}
}
/* USER CODE END 0 */
main函数
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t byteData;
uint16_t wordData;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C2_Init();
MX_USART6_UART_Init();
/* USER CODE BEGIN 2 */
printf("VL53L1X Examples...\r\n");
Dev->I2cHandle = &hi2c2;
Dev->I2cDevAddr = 0x52;
VL53L1_RdByte(Dev, 0x010F, &byteData);
printf("VL53L1X Model_ID: %02X\n\r", byteData);
VL53L1_RdByte(Dev, 0x0110, &byteData);
printf("VL53L1X Module_Type: %02X\n\r", byteData);
VL53L1_RdWord(Dev, 0x010F, &wordData);
printf("VL53L1X: %02X\n\r", wordData);
RangingLoop();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
测试结果
注意事项:实际测试的时候,发现vl53l1开启测量后,烧录程序后,读取的数据会有问题。像这样
应该是VL53L1开启测量后,需要调用停止测量的函数,才能对其进行操作。当出现这种情况时,需要对整个硬件系统重新上电,或者重新拔插vl53l1模块,也可以在初始化前调用停止测量的函数。