STM32驱动VL6180X测距


VL6180测距原理就是TOF,超声波也可以测距,但是这个测距是用红外光。
VL6180X集成了测距、环境光传感器、接近传感器
测距(RANGE):0~100mm精度高,可以到200mm,但是我试过200+以上直接255了;
环境光 ambient light sensor(ALS):测光强,不同增益等级,0-100 Lux,我的模块没有这个功能,但有代码(可能会出错)。

以下是软件I2C代码,硬件I2C没试过,可能可以用,不过时序都一样

VL6180X寄存器手册

#define	VL6180X_DEFAULT_ID						0xB4
//#define I2C_DEBUG
#define VL6180X_DEFAULT_I2C_ADDR 				0x29  ///< The fixed I2C addres
/*------------------VL6180X内部寄存器------------------*/
///! Device model identification number
#define VL6180X_REG_IDENTIFICATION_MODEL_ID    0x000
///! Interrupt configuration
#define VL6180X_REG_SYSTEM_INTERRUPT_CONFIG    0x014
///! Interrupt clear bits
#define VL6180X_REG_SYSTEM_INTERRUPT_CLEAR     0x015
///! Fresh out of reset bit
#define VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET  0x016
///! Trigger Ranging
#define VL6180X_REG_SYSRANGE_START             0x018
///! Trigger Lux Reading
#define VL6180X_REG_SYSALS_START               0x038
///! Lux reading gain
#define VL6180X_REG_SYSALS_ANALOGUE_GAIN       0x03F
///! Integration period for ALS mode, high byte
#define VL6180X_REG_SYSALS_INTEGRATION_PERIOD_HI  0x040
///! Integration period for ALS mode, low byte
#define VL6180X_REG_SYSALS_INTEGRATION_PERIOD_LO  0x041
///! Specific error codes
#define VL6180X_REG_RESULT_RANGE_STATUS        0x04d
///! Interrupt status
#define VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO       0x04f
///! Light reading value
#define VL6180X_REG_RESULT_ALS_VAL             0x050
///! Ranging reading value
#define VL6180X_REG_RESULT_RANGE_VAL           0x062

#define VL6180X_ALS_GAIN_1         0x06  ///< 1x gain
#define VL6180X_ALS_GAIN_1_25      0x05  ///< 1.25x gain
#define VL6180X_ALS_GAIN_1_67      0x04  ///< 1.67x gain
#define VL6180X_ALS_GAIN_2_5       0x03  ///< 2.5x gain
#define VL6180X_ALS_GAIN_5         0x02  ///< 5x gain
#define VL6180X_ALS_GAIN_10        0x01  ///< 10x gain
#define VL6180X_ALS_GAIN_20        0x00  ///< 20x gain
#define VL6180X_ALS_GAIN_40        0x07  ///< 40x gain

#define VL6180X_ERROR_NONE         0   ///< Success!
#define VL6180X_ERROR_SYSERR_1     1   ///< System error
#define VL6180X_ERROR_SYSERR_5     5   ///< Sysem error
#define VL6180X_ERROR_ECEFAIL      6   ///< Early convergence estimate fail
#define VL6180X_ERROR_NOCONVERGE   7   ///< No target detected
#define VL6180X_ERROR_RANGEIGNORE  8   ///< Ignore threshold check failed
#define VL6180X_ERROR_SNR          11  ///< Ambient conditions too high
#define VL6180X_ERROR_RAWUFLOW     12  ///< Raw range algo underflow
#define VL6180X_ERROR_RAWOFLOW     13  ///< Raw range algo overflow
#define VL6180X_ERROR_RANGEUFLOW   14  ///< Raw range algo underflow
#define VL6180X_ERROR_RANGEOFLOW   15  ///< Raw range algo overflow

没用到之前别去看寄存器,浪费时间。。

I2C读写

VL6180X的寄存器是16位的,也就是0xXXXX,切记

//写	reg寄存器 data数据
u8 VL6180X_WriteByte(u16 reg,u8 data)
{
	uint8_t Index_H = (uint8_t)(reg >> 8);
	uint8_t Index_L = (uint8_t)(reg & 0xFF);
	
	I2C_Start();
	I2C_Send_Byte((VL6180X_DEFAULT_I2C_ADDR<<1)|0);
	if(I2C_Wait_Ack())	//等待应答
	{
		I2C_Stop();	
		return 1;		
	}
	I2C_Send_Byte(Index_H);
	I2C_Wait_Ack();	//等待ACK
	I2C_Send_Byte(Index_L);
	I2C_Wait_Ack();	//等待ACK
	I2C_Send_Byte(data);
	if(I2C_Wait_Ack())	//等待ACK
	{
		I2C_Stop();	 
		return 1;		 
	}
	I2C_Stop();
	return 0;	
}

//VL6180X读取8位数据
u8 VL6180X_ReadByte(u16 reg)
{
	u8 res;
	uint8_t Index_H = (uint8_t)(reg >> 8);
	uint8_t Index_L = (uint8_t)(reg & 0xff);
    I2C_Start(); 
	I2C_Send_Byte((VL6180X_DEFAULT_I2C_ADDR<<1)|0);//发送器件地址+写命令	
	I2C_Wait_Ack();		//等待应答 
    I2C_Send_Byte(Index_H);	//写寄存器地址
    I2C_Wait_Ack();		//等待应答
	I2C_Send_Byte(Index_L);	//写寄存器地址
	I2C_Wait_Ack();	
	
    I2C_Start();
	I2C_Send_Byte((VL6180X_DEFAULT_I2C_ADDR<<1)|1);//发送器件地址+读命令	
    I2C_Wait_Ack();		//等待应答 
	res=I2C_Read_Byte(0);//读取数据,发送nACK 
    I2C_Stop();			//产生一个停止条件 
	return res;
}

这里要取寄存器的高位和地位,因为这是十六位地址,I2C需要写两次

读取ID(无需初始化)

uint8_t VL6180X_Read_ID(void)
{
	return VL6180X_ReadByte(VL6180X_REG_IDENTIFICATION_MODEL_ID);
}

正确地址是0xB4,拿来验证下I2C的读写是否有问题,记住寄存器地址是16位的!没用16位写入地址会一直变。。(我试过)

初始化代码

uint8_t VL6180X_Init(void)
{
	if(VL6180X_Read_ID() == VL6180X_DEFAULT_ID)
	{	
		VL6180X_WriteByte(0x0207, 0x01);
		VL6180X_WriteByte(0x0208, 0x01);
		VL6180X_WriteByte(0x0096, 0x00);
		VL6180X_WriteByte(0x0097, 0xfd);
		VL6180X_WriteByte(0x00e3, 0x00);
		VL6180X_WriteByte(0x00e4, 0x04);
		VL6180X_WriteByte(0x00e5, 0x02);
		VL6180X_WriteByte(0x00e6, 0x01);
		VL6180X_WriteByte(0x00e7, 0x03);
		VL6180X_WriteByte(0x00f5, 0x02);
		VL6180X_WriteByte(0x00d9, 0x05);
		VL6180X_WriteByte(0x00db, 0xce);
		VL6180X_WriteByte(0x00dc, 0x03);
		VL6180X_WriteByte(0x00dd, 0xf8);
		VL6180X_WriteByte(0x009f, 0x00);
		VL6180X_WriteByte(0x00a3, 0x3c);
		VL6180X_WriteByte(0x00b7, 0x00);
		VL6180X_WriteByte(0x00bb, 0x3c);
		VL6180X_WriteByte(0x00b2, 0x09);
		VL6180X_WriteByte(0x00ca, 0x09);
		VL6180X_WriteByte(0x0198, 0x01);
		VL6180X_WriteByte(0x01b0, 0x17);
		VL6180X_WriteByte(0x01ad, 0x00);
		VL6180X_WriteByte(0x00ff, 0x05);
		VL6180X_WriteByte(0x0100, 0x05);
		VL6180X_WriteByte(0x0199, 0x05);
		VL6180X_WriteByte(0x01a6, 0x1b);
		VL6180X_WriteByte(0x01ac, 0x3e);
		VL6180X_WriteByte(0x01a7, 0x1f);
		VL6180X_WriteByte(0x0030, 0x00);
		
		// Recommended : Public registers - See data sheet for more detail
		VL6180X_WriteByte(0x0011, 0x10);       // Enables polling for 'New Sample ready'
									// when measurement completes
		VL6180X_WriteByte(0x010a, 0x30);       // Set the averaging sample period
									// (compromise between lower noise and
									// increased execution time)
		VL6180X_WriteByte(0x003f, 0x46);       // Sets the light and dark gain (upper
									// nibble). Dark gain should not be
									// changed. !上半字节要写入0x4	默认增益是1.0
		VL6180X_WriteByte(0x0031, 0xFF);       // sets the # of range measurements after
									// which auto calibration of system is
									// performed
		VL6180X_WriteByte(0x0040, 0x63);       // Set ALS integration time to 100ms
		VL6180X_WriteByte(0x002e, 0x01);       // perform a single temperature calibration
									// of the ranging sensor

		// Optional: Public registers - See data sheet for more detail
		VL6180X_WriteByte(0x001b, 0x09);    //测量间隔	轮询模式
									// period to 100ms	每步10ms->0-10ms
		VL6180X_WriteByte(0x003e, 0x31);      //测量周期	ALS模式
									// to 500ms		
		VL6180X_WriteByte(0x0014, 0x24);       // Configures interrupt on 'New Sample
									// Ready threshold event'
		return 0;
	}
	else return 1;
}

初始化就是设置一些寄存器,这是官方提供的,需要设置自己的模式自己改寄存器就行了。

读取距离

//单位毫米
uint8_t VL6180X_Read_Range(void)
{
	uint8_t range = 0;
	//开启传输
	while(!(VL6180X_ReadByte(VL6180X_REG_RESULT_RANGE_STATUS) & 0x01));
	VL6180X_WriteByte(VL6180X_REG_SYSRANGE_START,0x01);	//单次触发模式
	//等待新样本就绪阈值事件(New Sample Ready threshold event)
	while(!(VL6180X_ReadByte(VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO) & 0x04));
	range = VL6180X_ReadByte(VL6180X_REG_RESULT_RANGE_VAL);
	//获取完数据,清楚中断位
	VL6180X_WriteByte(VL6180X_REG_SYSTEM_INTERRUPT_CLEAR,0x07);	//0111b 清除了三种中断标志
	return range;
}

有注释,我写的很清楚,大致是读取一些寄存器的状态,设置寄存器启动转化。最后做好处理用于下次测量。
范围是0~200mm,超了的话会直接255。

读取环境光强度

float VL6180X_Read_Lux(uint8_t Gain)
{
	float lux;
	uint8_t reg;
	reg = VL6180X_ReadByte(VL6180X_REG_SYSTEM_INTERRUPT_CONFIG);
	reg &= ~0x38;		//[5:3]清0
	reg |= (0x4<<3);	//开启转换New sample ready	开启转换
	
	VL6180X_WriteByte(VL6180X_REG_SYSALS_INTEGRATION_PERIOD_HI,0);
	VL6180X_WriteByte(VL6180X_REG_SYSALS_INTEGRATION_PERIOD_LO,100);	//101ms
	if (Gain > VL6180X_ALS_GAIN_40)
	{
		Gain = VL6180X_ALS_GAIN_40;
	}
	VL6180X_WriteByte(VL6180X_REG_SYSALS_ANALOGUE_GAIN, 0x40 | Gain);
	VL6180X_WriteByte(VL6180X_REG_SYSALS_START, 0x1);	//连续模式
	// New Sample Ready threshold event 新样本就绪
	while (4 != ((VL6180X_ReadByte(VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO) >> 3) & 0x7));
	
	lux = VL6180X_Read_HalfWold(VL6180X_REG_RESULT_ALS_VAL);
	VL6180X_WriteByte(VL6180X_REG_SYSTEM_INTERRUPT_CLEAR,0x07);	//0111b 清除了三种中断标志
	//矫正增益算法
	lux *= 0.32f; // calibrated count/lux
	switch(Gain) { 
	case VL6180X_ALS_GAIN_1: 
	break;
	case VL6180X_ALS_GAIN_1_25: 
	lux /= 1.25f;
	break;
	case VL6180X_ALS_GAIN_1_67: 
	lux /= 1.76f;
	break;
	case VL6180X_ALS_GAIN_2_5: 
	lux /= 2.5f;
	break;
	case VL6180X_ALS_GAIN_5: 
	lux /= 5;
	break;
	case VL6180X_ALS_GAIN_10: 
	lux /= 10;
	break;
	case VL6180X_ALS_GAIN_20: 
	lux /= 20;
	break;
	case VL6180X_ALS_GAIN_40: 
	lux /= 20;
	break;
	}
	lux *= 100;
	lux /= 100; // integration time in ms
	return lux;
}

需要读取两个字节

//VL6180X读取16位数据
u8 VL6180X_Read_HalfWold(u16 reg)
{
	u16 res;
	uint8_t Index_H = (uint8_t)(reg >> 8);
	uint8_t Index_L = (uint8_t)(reg & 0xff);
    I2C_Start(); 
	I2C_Send_Byte((VL6180X_DEFAULT_I2C_ADDR<<1)|0);//发送器件地址+写命令	
	I2C_Wait_Ack();		//等待应答 
    I2C_Send_Byte(Index_H);	//写寄存器地址
    I2C_Wait_Ack();		//等待应答
	I2C_Send_Byte(Index_L);	//写寄存器地址
	I2C_Wait_Ack();	
	
    I2C_Start();
	I2C_Send_Byte((VL6180X_DEFAULT_I2C_ADDR<<1)|1);//发送器件地址+读命令	
    I2C_Wait_Ack();		//等待应答 
	res = I2C_Read_Byte(1);//读取数据,发送ACK 
	res <<= 8;
	res |= I2C_Read_Byte(0);//读取数据,发送nACK 
    I2C_Stop();			//产生一个停止条件 
	return res;
}

光强的我没试过,这些代码都是移植Arduino的驱动到STM32,我看了寄存器大概知道什么意思。这个代码要是能用可以说一句,让大家放心。

测试代码

int main()
{
	/*Parameter Configuration*/
	u8 ex_Range = 0;
	/*Init*/
	delay_init(168);
	USART_Config();
	MY_I2C_GPIO_Config();	//I2C初始化
	/*Configuration Operation*/
	printf("\r\nVL6180X测距实验\r\n");
	if(VL6180X_Init() == 0)	printf("\r\nVL6180X初始化成功!\r\n");
	delay_ms(2000);
	/*LOOP*/
	while(1)
	{
		ex_Range = VL6180X_Read_Range();
		printf("\r\n Current Range:%d mm",ex_Range);
		delay_ms(100);
	}
}
  • 18
    点赞
  • 120
    收藏
    觉得还不错? 一键收藏
  • 28
    评论
### 回答1: STM32驱动VL53L0激光测距传感器可以使用STM32的GPIO(通用输入输出)和I2C(串行总线)功能来实现。 首先,我们需要将VL53L0传感器连接到STM32开发板。将传感器的VIN引脚连接到STM32的正电源引脚,GND引脚连接到GND引脚,XSHUT引脚连接到STM32的GPIO引脚(用于控制传感器的电源开关),SCL引脚连接到STM32的I2C时钟引脚,SDA引脚连接到STM32的I2C数据引脚。 接下来,在STM32的程序中,我们需要初始化GPIO和I2C模块。通过设置GPIO引脚为输出模式和输入模式,我们可以控制传感器的XSHUT引脚和读取传感器的测距数据。使用I2C模块,我们可以通过发送和接收数据来与传感器进行通信。 然后,我们可以在程序中编写相应的代码来配置传感器的参数和读取测距数据。通过发送特定的命令和配置字节,我们可以设置测距传感器的工作模式、测量范围、测量速度等参数。通过接收传感器返回的测距数据,我们可以获取到物体到传感器的距离信息。 最后,在程序中我们可以根据实际需求来使用测距数据进行后续处理,比如显示距离值、控制其他设备的操作等。 总结来说,STM32驱动VL53L0激光测距传感器的过程包括连接硬件、初始化GPIO和I2C模块、配置传感器参数和读取测距数据。通过这些步骤,我们可以在STM32开发板上成功地使用VL53L0传感器进行激光测距。 ### 回答2: STM32驱动VL53L0激光测距传感器可以通过以下步骤实现: 1. 硬件连接:将VL53L0传感器与STM32微控制器相连接。具体连接方法可以参考VL53L0与STM32芯片的数据手册或者引脚连接图进行连接。 2. 引用库文件:在STM32的开发环境中,引入VL53L0的相关库文件。这些库文件通常包含了VL53L0传感器的初始化、配置和读取等功能函数。 3. 初始化配置:使用库文件提供的函数,对VL53L0传感器进行初始化配置。这些配置包括传感器的工作模式、测量范围、测量速度和传感器的增益等参数。 4. 数据读取:通过库文件提供的函数,从VL53L0传感器中获取距离测量数据。一般情况下,可以通过单次测量函数获取单个测量值,或者使用连续测量函数获取连续的测量数据。 5. 数据处理与应用:将获取到的距离测量数据进行处理与应用。处理包括对数据进行滤波、校准、运算等操作,以获得更准确的测量结果。应用可以包括距离监测、障碍物检测、距离控制等功能。 需要注意的是,为了确保VL53L0传感器正常工作,还需要配置合适的时钟频率、引脚电平等参数,以及适当的电源供应。此外,还应注意数据传输的稳定性、测量精度与速度之间的权衡。 总结来说,通过STM32驱动VL53L0激光测距传感器,需要进行硬件连接、引用库文件、初始化配置、数据读取及数据处理与应用等步骤。这样可以实现对VL53L0测距传感器的驱动和使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值