STM32F407驱动VL6180X激光测距模块

相比较VL53L0x模块,vl6180x更适合短距离测距,200mm下时误差只有1-2mm.代码也更简捷。

本次实验用 stm32f407ve + freertos +hal库开发  ,vl6180x使用 io模拟iic通信,单模块通信

VL6180x只需要接4个脚

vin -> 3.3v

gnd ->0v

sda -> iic_sda (PB9)

scl ->iic_scl (PB8)

//vl6180x模块驱动代码------------------------------------------------------

//头文件就行一些寄存器

#ifndef __VL6180X_H
#define __VL6180X_H

#include "./board_iic/myiic.h"


#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



uint8_t VL6180X_Init(void);


//距离单位毫米
uint8_t VL6180X_Read_Range(void);


#endif

//.c配置文件

#include "vl6180x.h"
#include "./delay/delay.h"
/*iic驱动移植****************************/
#define I2C_Start iic_start
#define I2C_Stop iic_stop
#define I2C_Wait_Ack iic_wait_ack
#define I2C_Send_Byte iic_send_byte
#define I2C_Read_Byte iic_read_byte
/*************************************/



//写	reg寄存器 data数据
static uint8_t VL6180X_WriteByte(uint16_t reg,uint8_t 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位数据
static uint8_t VL6180X_ReadByte(uint16_t reg)
{
	uint8_t res=0;
	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;
}



static uint8_t VL6180X_Read_ID(void)
{
	uint8_t id=0;
	id=VL6180X_ReadByte(VL6180X_REG_IDENTIFICATION_MODEL_ID);
	printf("id=%#x\r\n",id);
	return id;
}

static void VL6180X_IIC_Init(void)
{
	iic_init();
}

/// @brief VL6180X_Init 初始化
/// @param  
/// @return 1成功 0失败
uint8_t VL6180X_Init(void)
{
	uint8_t ret=0;
	VL6180X_IIC_Init();

	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'
		ret= 1;
	}

	if(VL6180X_ReadByte(0x016) == 1)
	{
		VL6180X_WriteByte(0x016, 0x00);
		printf("0x016\r\n");
	}

	 return ret;
}



static uint8_t VL6180_Poll_Range(void)
{
	uint8_t status=0;
	uint8_t range_status=0;

	//检测状态
	status = VL6180X_ReadByte(0x04f); 
	range_status = status & 0x07;

	//等待新的测量就绪状态
	while (range_status != 0x04) {
	status = VL6180X_ReadByte(VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO);
	range_status = status & 0x07;
	//	delay_ms(1); // (can be removed)
 	}

}

static void VL6180_Clear_Interrupts(void)
{
	VL6180X_WriteByte(VL6180X_REG_SYSTEM_INTERRUPT_CLEAR,0x07);
}

//距离单位毫米
uint8_t VL6180X_Read_Range(void)
{
	uint8_t range = 0;

	//开启传输
	VL6180X_WriteByte(VL6180X_REG_SYSRANGE_START,0x01);	//单次触发模式

	VL6180_Poll_Range();

	range = VL6180X_ReadByte(VL6180X_REG_RESULT_RANGE_VAL);
	
	//获取完数据,清楚中断位
	VL6180_Clear_Interrupts();

	return range;
}

//这就是VL6180X的驱动代码了,非常简洁

代码是参考这位博主的http://t.csdnimg.cn/zXgDH,但是我全部移植代码会卡死在获取状态哪里,然后根据官网demo做了一下修改。

现在这个代码是可以用的。

//初始化VL6180X模块
void app_check_task_init(void)
{


    while(VL6180X_Init() == 0)
    {
       delay_ms(1000);
       printf("error\r\n");
    }

    delay_ms(1000);
}
//线程调用 1s获取一次距离
void check_task(void *pvParameters)
{
    u8 distance =0;   
    while(1)
    {
        
       //VL53L1_single_test(&VL53L0x_dev,&VL53L0x_data);

        distance=VL6180X_Read_Range();

        printf("distance=%d mm\r\n",distance);
        vTaskDelay(1000);    
   
    }
}

打印出来的信息

200mm以下,精度很高。

/*iic驱动移植****************************/
#define I2C_Start iic_start
#define I2C_Stop iic_stop
#define I2C_Wait_Ack iic_wait_ack
#define I2C_Send_Byte iic_send_byte
#define I2C_Read_Byte iic_read_byte

只需要替换一下自己iic函数名就能用了,iic驱动就不用多说了。

VL6180X模块就这样了,理论上移植换一下io口或者替换其他mcu的库,应该直接就能用了,问题不大。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值