stm32f407驱动多个lv6180x模块

用一组iic总线驱动多个lv6180x模块。

//头文件

#ifndef __VL6180X_H
#define __VL6180X_H

#include "./board_iic/myiic.h"
#include "./delay/delay.h"


/*iic驱动移植****************************/
#define I2C_Init        iic_init
#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
/*************************************/

#define LV6180x_MODULE_NUM_MAX 4 //最大连接4个模块

//模块地址
#define LV6180x_MODULE_1_ADDR  0x2a
#define LV6180x_MODULE_2_ADDR  0x2b
#define LV6180x_MODULE_3_ADDR  0x2c
#define LV6180x_MODULE_4_ADDR  0x2d

typedef enum 
{
	LV6180x_MODULE_1,
	LV6180x_MODULE_2,
	LV6180x_MODULE_3,
	LV6180x_MODULE_4,

	LV6180x_MODULE_MAX //模块数量不要超过4个
}lv6180x_module_name;


typedef struct 
{
	GPIO_TypeDef* GPIOx;
	uint16_t GPIO_Pin;
}lv6180x_shdn_gpio;

typedef struct 
{
	uint8_t  lv6180x_iic_addr;
	lv6180x_shdn_gpio lv6180x_shdn;
}lv6180x_module_info;






uint8_t VL6180X_Init(void);


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


#endif

//.c驱动文件

#include "vl6180x.h"
#include <string.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

/*end****************************************************************************************/

//注册模块
static lv6180x_module_info s_lv6180x_module_info_t[LV6180x_MODULE_MAX]=
{
	{LV6180x_MODULE_1_ADDR,GPIOB,GPIO_PIN_5},
	{LV6180x_MODULE_2_ADDR,GPIOB,GPIO_PIN_3},
	{0x00,NULL,0},
	{0x00,NULL,0},
};//模块信息参数



//------------------------------------------------------
//支持lv6180x多模块连接在一组iic总线上 

//shdn引脚输出电平
static void vl6180x_shdn_set_pin(uint8_t lv6180x_name,uint8_t val)
{
	HAL_GPIO_WritePin(s_lv6180x_module_info_t[lv6180x_name].lv6180x_shdn.GPIOx,\
						s_lv6180x_module_info_t[lv6180x_name].lv6180x_shdn.GPIO_Pin,val);//
}	

//配置CL6180X模块的SHDN脚
static void vl6180x_shdn_gpio_config(lv6180x_module_info lc6180x_s)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	lv6180x_shdn_gpio SHDN_GPIOx=lc6180x_s.lv6180x_shdn;

	//打开对应RCC
	if(SHDN_GPIOx.GPIOx == GPIOA)
		__HAL_RCC_GPIOA_CLK_ENABLE();
	else if(SHDN_GPIOx.GPIOx == GPIOB)
		__HAL_RCC_GPIOB_CLK_ENABLE();
	else if(SHDN_GPIOx.GPIOx == GPIOC)
		__HAL_RCC_GPIOC_CLK_ENABLE();
	else if(SHDN_GPIOx.GPIOx == GPIOD)
		__HAL_RCC_GPIOD_CLK_ENABLE();
	else
		printf("SHDN_GPIOx.GPIOx=%#x error\r\n",SHDN_GPIOx.GPIOx);
	
	//初始化pin
    GPIO_InitStruct.Pin = SHDN_GPIOx.GPIO_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(SHDN_GPIOx.GPIOx,&GPIO_InitStruct);	

	HAL_GPIO_WritePin(SHDN_GPIOx.GPIOx,SHDN_GPIOx.GPIO_Pin,0);//拉低 不启动模块

}


//写	reg寄存器 data数据
static uint8_t VL6180X_AddrWriteByte(uint8_t addr,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((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_AddrReadByte(uint8_t addr,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((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((addr<<1)|1);//发送器件地址+读命令	
    I2C_Wait_Ack();		//等待应答 
	res=I2C_Read_Byte(0);//读取数据,发送nACK 
    I2C_Stop();			//产生一个停止条件 

	return res;
}


//读取总线地址
static uint8_t VL6180X_Read_Addr(uint8_t addr)
{
	uint8_t ret_addr=0;
	ret_addr=VL6180X_AddrReadByte(addr,0x0212);
	return ret_addr;
}
//修改总线地址
static void  VL6180X_Write_Addr(uint8_t addr)
{
	VL6180X_AddrWriteByte(VL6180X_DEFAULT_I2C_ADDR,0x0212,addr);
}
//读取id
static uint8_t VL6180X_Read_ID(uint8_t addr)
{
	return VL6180X_AddrReadByte(addr,VL6180X_REG_IDENTIFICATION_MODEL_ID); 
}
//向模块写入配置参数
static uint8_t VL6180X_Modele_Write_Config(void)
{


	if(VL6180X_Read_ID(VL6180X_DEFAULT_I2C_ADDR) != VL6180X_DEFAULT_ID)//检查id是否正确
	{
		return 0 ;	
	}

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

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

		//VL6180X_AddrWriteByte(VL6180X_DEFAULT_I2C_ADDR,0x0212,0x2a);//
		

	if(VL6180X_AddrReadByte(VL6180X_DEFAULT_I2C_ADDR,VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET) == 1)
	{
		VL6180X_AddrWriteByte(VL6180X_DEFAULT_I2C_ADDR,VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET,0x00);
		printf("0x016\r\n");
	}
}


#if 0
/// @brief VL6180X_Modele_Info_register 注册模块信息
/// @param lv6180x_name 模块序列
/// @param info 信息
/// @return  1注册成功 0注册失败
uint8_t VL6180X_Modele_Info_register(lv6180x_module_name lv6180x_id,lv6180x_module_info info )
{

	if(lv6180x_id >= LV6180x_MODULE_NUM_MAX)
	{
		printf("lv6180x_id=%d error\r\n");
		return 0;
	}

	s_lv6180x_module_info_t[lv6180x_id]=info;//保存参数

	vl6180x_shdn_gpio_config(s_lv6180x_module_info_t[lv6180x_id]);//shdn脚初始化

	return 1;
}
#endif


#define VL6180X_INIT_INFO_DEBUG
/// @brief VL6180X_Init 初始化
/// @param  
/// @return 
uint8_t VL6180X_Init(void)
{
	uint8_t i=0;
	uint8_t ret=0;


	I2C_Init();//iic初始化

	for (i = 0; i < LV6180x_MODULE_NUM_MAX; i++)
	{
		if(s_lv6180x_module_info_t[i].lv6180x_iic_addr != 0x00)
		{
			vl6180x_shdn_gpio_config(s_lv6180x_module_info_t[i]);//shdn脚初始化
		}	
	}
	

	for (i = 0; i < LV6180x_MODULE_NUM_MAX; i++)
	{
		if(s_lv6180x_module_info_t[i].lv6180x_iic_addr != 0x00)
		{
			vl6180x_shdn_set_pin(i,1);//拉高引脚
			
			ret=VL6180X_Modele_Write_Config();//写入参数


			VL6180X_Write_Addr(s_lv6180x_module_info_t[i].lv6180x_iic_addr);//修改总线地址	

#ifdef	VL6180X_INIT_INFO_DEBUG	
			printf("ret =%d\r\n",ret);
			printf("VL6180X_Addr[%#x]\r\n",VL6180X_Read_Addr(s_lv6180x_module_info_t[i].lv6180x_iic_addr));
			printf("VL6180X_id[%#x]\r\n",VL6180X_Read_ID(s_lv6180x_module_info_t[i].lv6180x_iic_addr));	
#endif		
		}

		
		
	}
	
	return ret;
}



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

	//检测状态

	status= VL6180X_AddrReadByte(addr,VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO);

	range_status = status & 0x07;

	//等待新的测量就绪状态
	while (range_status != 0x04)
	{

		status =VL6180X_AddrReadByte(addr,VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO);
		range_status = status & 0x07;

 	}

}

static void VL6180_Clear_Interrupts(uint8_t addr)
{
	
	VL6180X_AddrWriteByte(addr,VL6180X_REG_SYSTEM_INTERRUPT_CLEAR,0x07);

}

//距离单位毫米
uint8_t VL6180X_Read_Range(lv6180x_module_name lv6180x_name)
{
	uint8_t range = 0;
	uint8_t iic_addr=s_lv6180x_module_info_t[lv6180x_name].lv6180x_iic_addr;

	if(iic_addr == 0x00)
	{
		return 0xff;
	}

	VL6180X_AddrWriteByte(iic_addr,VL6180X_REG_SYSRANGE_START,0x01);	//单次触发模式
	VL6180_Poll_Range(iic_addr);

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

	
	return range;
}



一组iic总线驱动多个lv6180x模块的要点。

1.每个lv6180x的物理地址总线是0x29,只要断电重启,都是该地址

2.通过0x0212寄存器,可以零时修改总线地址,替换掉0x29.修改地址只是临时的,模块断电将自动变回0x29

//修改总线地址

//修改总线地址
static void  VL6180X_Write_Addr(uint8_t addr)
{
	VL6180X_AddrWriteByte(VL6180X_DEFAULT_I2C_ADDR,0x0212,addr);
}

3.通过SHDN引脚,可以断开模块,通过驱动SHDN引脚来修改模块地址。

	for (i = 0; i < LV6180x_MODULE_NUM_MAX; i++)
	{
		if(s_lv6180x_module_info_t[i].lv6180x_iic_addr != 0x00)
		{
			vl6180x_shdn_gpio_config(s_lv6180x_module_info_t[i]);//shdn脚初始化
		}	
	}
	

	for (i = 0; i < LV6180x_MODULE_NUM_MAX; i++)
	{
		if(s_lv6180x_module_info_t[i].lv6180x_iic_addr != 0x00)
		{
			vl6180x_shdn_set_pin(i,1);//拉高引脚
			
			ret=VL6180X_Modele_Write_Config();//写入参数


			VL6180X_Write_Addr(s_lv6180x_module_info_t[i].lv6180x_iic_addr);//修改总线地址	

#ifdef	VL6180X_INIT_INFO_DEBUG	
			printf("ret =%d\r\n",ret);
			printf("VL6180X_Addr[%#x]\r\n",VL6180X_Read_Addr(s_lv6180x_module_info_t[i].lv6180x_iic_addr));
			printf("VL6180X_id[%#x]\r\n",VL6180X_Read_ID(s_lv6180x_module_info_t[i].lv6180x_iic_addr));	
#endif		
		}

//已经封装好,移植只需要简单修改几个参数就能用

1.替换成自己的iic驱动名字

/*iic驱动移植****************************/
#define I2C_Init        iic_init
#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
/*************************************/

2.LV6180x_MODULE_1_ADDR  宏定义需要设置的地址,

lv6180x_module_name 模块的名字

//模块地址
#define LV6180x_MODULE_1_ADDR  0x2a
#define LV6180x_MODULE_2_ADDR  0x2b
#define LV6180x_MODULE_3_ADDR  0x2c
#define LV6180x_MODULE_4_ADDR  0x2d

typedef enum 
{
	LV6180x_MODULE_1,
	LV6180x_MODULE_2,
	LV6180x_MODULE_3,
	LV6180x_MODULE_4,

	LV6180x_MODULE_MAX //模块数量不要超过4个
}lv6180x_module_name;

3.注册模块 

//注册模块

static lv6180x_module_info s_lv6180x_module_info_t[LV6180x_MODULE_MAX]=

{

    {LV6180x_MODULE_1_ADDR,GPIOB,GPIO_PIN_5},

    {LV6180x_MODULE_2_ADDR,GPIOB,GPIO_PIN_3},

    {0x00,NULL,0},

    {0x00,NULL,0},

};//模块信息参数

//完成移植

然后在main里面调用就好

1初始化

    if(VL6180X_Init() == 0)
    {
       delay_ms(500);
       printf("error\r\n");
    }

2.获取距离

    u8 distance_1 =0; 
    u8 distance_2 =0;   
    while(1)
    {
        
       //VL53L1_single_test(&VL53L0x_dev,&VL53L0x_data);

        distance_1=VL6180X_Read_Range(LV6180x_MODULE_1);
        distance_2=VL6180X_Read_Range(LV6180x_MODULE_2);
        printf("LV6180x_MODULE_1 ->distance_1=%d mm\r\n",distance_1);
        printf("LV6180x_MODULE_2 ->distance_2=%d mm\r\n",distance_2);
        vTaskDelay(1000);    
   
    }

完成

//第二个模块误差有点大,应该和线有关,换了线误差好了一点。连接的线要好一点,尽量短。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值