VL6180X傳感器驅動

vl6180x_i2c.c

I2C通信

獲取VL6180x地址

這裏寫圖片描述
可以知道7位地址爲0x29
寫: 0x52
讀: 0x53

寫入數據

這裏寫圖片描述

/*
 * 通過I2C總線向某一寄存器寫入一個字節數據
 *  成功 0
 *  失敗 1 
 */
uint8 VL6180X_WriteBytes(uint8 I2C_addr,uint16 index,uint8 dat)
{
	uint8 Index_H = (uint8)(index >> 8);
        uint8 Index_L = (uint8)(index & 0xff);

	start();
	iic_write(I2C_addr | 0X00); //WRITE i2c
	if (check_ack()==0) {
		goto err;
	}
	iic_write(Index_H); //TDOS'register
	if (check_ack()==0) {
		goto err;
	}
        iic_write(Index_L); //TDOS'register
	if (check_ack()==0) {
		goto err;
	}
        
	iic_write(dat); //發送數據字節
	if (check_ack()==0) {
		goto err;
	}
        stop();
        return 0;
err:
	stop();
        return 1;
}

讀出數據

讀單個數據

/*
 * 通過I2C總線讀出某一寄存器的數據
 */
uint8 VL6180x_ReadBytes(uint8 I2C_addr, uint16 index) {
	uint8 dat;
        uint8 Index_H = (uint8)(index >> 8);
        uint8 Index_L = (uint8)(index & 0xff);

	start();
	iic_write(I2C_addr | 0X00); //WRITE i2c
	if (check_ack()==0) {
		goto err;
	}
	iic_write(Index_H); //TDOS'register
	if (check_ack()==0) {
		goto err;
	}
        iic_write(Index_L); //TDOS'register
	if (check_ack()==0) {
		goto err;
	}
        
	start(); //重發起動信號
	iic_write(I2C_addr | 0X01); //READ
	if (check_ack()==0) {
		goto err;
	}
	dat = iic_read();	//接收讀出的數據
	stop();
        return dat;
err:
	stop();
	return 0;
}

讀兩組數據

/*
 * 通過I2C總線讀出某一寄存器的數據
 */
uint16 VL6180x_Read_Two_Bytes(uint8 I2C_addr, uint16 index) {
	uint8 t;
        uint16 data_res;
	uint8 Index_H = (uint8)(index >> 8);
        uint8 Index_L = (uint8)(index & 0xff);

	start();
	iic_write(I2C_addr | 0X00); //WRITE i2c
	if (check_ack()==0) {
		goto err;
	}
	iic_write(Index_H); //TDOS'register
	if (check_ack()==0) {
		goto err;
	}
        iic_write(Index_L); //TDOS'register
	if (check_ack()==0) {
		goto err;
	}
        stop();
        
	start(); //重發起動信號
	iic_write(I2C_addr | 0X01); //READ
	if (check_ack()==0) {
		goto err;
	}
	t = iic_read();	//接收讀出的數據
 	send_ack();      
        data_res = t; 
        
	t = iic_read();	//接收讀出的數據
 	send_ack();       
        data_res = ((data_res<<8) | t);
        
//	t = iic_read();	//接收讀出的數據     
// 	send_ack();   
//        data_res = ((data_res<<16) | t);
//        
//        t = iic_read();	//接收讀出的數據     
// 	send_ack();   
//        data_res = ((data_res<<24) | t);
        
	stop();
        return data_res;
err:
	stop();
	return 0;
}

檢測ID

從文檔中獲取ID地址:
這裏寫圖片描述
地址:0x000
默認值: 0xB4

/*
*********************************************************************************************************
 1. 函 數 名: VL6180X_CheckID
 2. 功能說明: 獲取VL6180X的ID
 3. 返 回 值: VL6180X_ID
*********************************************************************************************************
*/
uint8 VL6180X_CheckID(void)
{
    uint8 data_ID;
    data_ID = VL6180x_ReadBytes(DEV_ADDR, VL6180X_IDENTIFICATION_MODEL_ID);
    return data_ID;
}

獲取芯片的ID目的:

  1. 檢測通信是否成功
  2. 檢測芯片是否正常工作

初始化

這裏寫圖片描述

void VL6180X_Init(void)
{
    uint8 reset=0, timeOut=0;
    GPIO_0_OUTPUT;
    GPIO_1_OUTPUT;
//    Power_PIN_OUTPUT;
//    Power_PIN_PORT=0;
//    GPIO_0_PIN_PORT = 0;
//    GPIO_1_PIN_PORT = 0;
//    DelayMS(5);
//    Power_PIN_PORT=1;
//    DelayMS(5);
//    GPIO_0_PIN_PORT = 1;
//    GPIO_1_PIN_PORT = 1;
//    DelayMS(5);
    GPIO_0_PIN_PORT = 0;
    GPIO_1_PIN_PORT = 0;
    DelayMS(10);
    GPIO_0_PIN_PORT = 1;
    GPIO_1_PIN_PORT = 1;
    DelayMS(1);
    
    while(!(VL6180X_CheckID() == 0xB4));
    DelayMS(5);
    
    VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSTEM_FRESH_OUT_OF_RESET, 0x01);  
    while (reset!=1 && timeOut<100) {
        reset = VL6180x_ReadBytes(DEV_ADDR, VL6180X_SYSTEM_FRESH_OUT_OF_RESET);  // read fresh_out_of_reset bit
        if(reset == 1) {  // if if fresh_out_of_reset bit set, then device has been freshly initialized

            // SR03 settings AN4545 24/27 DocID026571 Rev 19 SR03 settings
            // http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00122600.pdf
            // Below are the recommended settings required to be loaded onto the VL6180X during the
            // initialisation of the device (see Section 1.3).
            // Mandatory : private registers


            VL6180X_WriteBytes(DEV_ADDR, 0x0207, 0x01);
            data_reg = VL6180x_ReadBytes(DEV_ADDR, 0x0207);

            VL6180X_WriteBytes(DEV_ADDR, 0x0208, 0x01);
            VL6180X_WriteBytes(DEV_ADDR, 0x0096, 0x00);
            VL6180X_WriteBytes(DEV_ADDR, 0x0097, 0xFD);
            VL6180X_WriteBytes(DEV_ADDR, 0x00e3, 0x00);
            VL6180X_WriteBytes(DEV_ADDR, 0x00e4, 0x04);
            data_reg = VL6180x_ReadBytes(DEV_ADDR, 0x00e4);

            VL6180X_WriteBytes(DEV_ADDR, 0x00e5, 0x02);
            VL6180X_WriteBytes(DEV_ADDR, 0x00e6, 0x01);
            VL6180X_WriteBytes(DEV_ADDR, 0x00e7, 0x03);
            VL6180X_WriteBytes(DEV_ADDR, 0x00f5, 0x02);
            VL6180X_WriteBytes(DEV_ADDR, 0x00d9, 0x05);
            VL6180X_WriteBytes(DEV_ADDR, 0x00db, 0xce);
            VL6180X_WriteBytes(DEV_ADDR, 0x00dc, 0x03);
            VL6180X_WriteBytes(DEV_ADDR, 0x00dd, 0xf8);
            VL6180X_WriteBytes(DEV_ADDR, 0x009f, 0x00);
            VL6180X_WriteBytes(DEV_ADDR, 0x00a3, 0x3c);
            VL6180X_WriteBytes(DEV_ADDR, 0x00b7, 0x00);
            VL6180X_WriteBytes(DEV_ADDR, 0x00bb, 0x3c);
            VL6180X_WriteBytes(DEV_ADDR, 0x00b2, 0x09);
            VL6180X_WriteBytes(DEV_ADDR, 0x00ca, 0x09);
            VL6180X_WriteBytes(DEV_ADDR, 0x0198, 0x01);
            VL6180X_WriteBytes(DEV_ADDR, 0x01b0, 0x17);
            VL6180X_WriteBytes(DEV_ADDR, 0x01ad, 0x00);
            VL6180X_WriteBytes(DEV_ADDR, 0x00ff, 0x05);
            VL6180X_WriteBytes(DEV_ADDR, 0x0100, 0x05);
            VL6180X_WriteBytes(DEV_ADDR, 0x0199, 0x05);
            VL6180X_WriteBytes(DEV_ADDR, 0x01a6, 0x1b);
            VL6180X_WriteBytes(DEV_ADDR, 0x01ac, 0x3e);
            VL6180X_WriteBytes(DEV_ADDR, 0x01a7, 0x1f);
            VL6180X_WriteBytes(DEV_ADDR, 0x0030, 0x00);
            data_reg = VL6180x_ReadBytes(DEV_ADDR, 0x0030);
            

            // configure range measurement for low power
            // Specify range measurement interval in units of 10 ms from 0 (= 10 ms) - 254 (= 2.55 s)

            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSRANGE_INTERMEASUREMENT_PERIOD, 0x0A); // 100 ms interval in steps of 10 ms
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSRANGE_VHV_REPEAT_RATE, 0xFF); // sets number of range measurements after which autocalibrate is performed
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSRANGE_VHV_RECALIBRATE, 0x01); // perform temperature calibration of the ranging sensor

            // Set Early Convergence Estimate for lower power consumption
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSRANGE_MAX_CONVERGENCE_TIME, 0x32); // set max convergence time to 50 ms (steps of 1 ms)
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSRANGE_RANGE_CHECK_ENABLES, 0x10 | 0x01);  // enable (0x01) early convergence estimate
            // This ECE is calculated as follows:
            // [(1 - % below threshold) x 0.5 x 15630]/ range max convergence time
            // This is ~123 ms for 50 ms max convergence time and 80% below threshold
            // This is a sixteen bit (2 byte) register with the first byte MSByte and the second LSByte
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSRANGE_EARLY_CONVERGENCE_ESTIMATE, 0x00); // set early convergence estimate to 5%
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSRANGE_EARLY_CONVERGENCE_ESTIMATE + 1, 0x7B); // set early convergence estimate to 5%

            // Configure ALS
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSALS_INTERMEASUREMENT_PERIOD, 0x0A);   // set to 100 ms
            data_reg = VL6180x_ReadBytes(DEV_ADDR, VL6180X_SYSALS_INTERMEASUREMENT_PERIOD);
            
            // Following is a 16-bit register with the first MSByte reserved

            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSALS_INTEGRATION_PERIOD, 0x00);
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSALS_INTEGRATION_PERIOD+1, 0x63);        // set ALS integration time to 100 ms in steps of 1 ms

            // The internal readout averaging sample period can be adjusted from 0 to 255. Increasing the sampling
            // period decreases noise but also reduces the effective max convergence time and increases power consumption:
            // Effective max convergence time = max convergence time - readout averaging period (see
            // Section 2.5: Range timing). Each unit sample period corresponds to around 64.5 ?s additional
            // processing time. The recommended setting is 48 which equates to around 4.3 ms
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_READOUT_AVERAGING_SAMPLE_PERIOD, 0x30);  // compromise between low noise and increased execution time
            // Gain can be 0 = 20, 1 = 10, 2 = 5, 3 = 2.5, 4 = 1.67, 5 = 1.25, 6 = 1.0 and 7 = 40
            // These are value possible for the lower nibble. The upper nibble must be 4
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSALS_ANALOGUE_GAIN, 0x40 | 1);   // Sets light and dark gain (don't change upper nibble)
            data_reg = VL6180x_ReadBytes(DEV_ADDR, VL6180X_SYSALS_ANALOGUE_GAIN);
            
            // Scalar (1 - 32, bits 4:0) to multiply raw ALS count for additonal gain, if necessary
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_FIRMWARE_RESULT_SCALER, 0x01);

            // Configure the interrupts
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSTEM_MODE_GPIO0, 0x00);                // set up GPIO 0 (set to high impedence for now)
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSTEM_MODE_GPIO1, 0x00);                // set up GPIO 1 (set to high impedence for now)
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24);     // enable sample ready interrupt

#if 0
            // enable continuous range mode
            if(VL6180XMode == contRangeMode) {
                VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSRANGE_START, 0x03);  // start auto range mode

            }
            // enable continuous ALS mode
            if(VL6180XMode == contALSMode) {
                // Configure ALS
                VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSALS_INTERMEASUREMENT_PERIOD, 0x32);   // set to 100 ms
                // Following is a 16-bit register with the first MSByte reserved
                VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSALS_INTEGRATION_PERIOD+1, 0x32);        // set ALS integration time to 50 ms in steps of 1 ms
                VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSALS_START, 0x03);                     // start auto range mode
            }
#endif
            // Clear reset bit
            VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSTEM_FRESH_OUT_OF_RESET, 0x00);        // reset fresh_out_of_reset bit to zero
        } else {
            timeOut++;
        }
    }
    reset=0;
   
}

這段代碼可以移植官方例程,配置寄存器的值,初始化I\O口

獲取光強值

這裏寫圖片描述

uint16 ligthPollingRead(void) 
{
    uint8 status;
    uint16 alsraw;
    
    /* Wait for device ready. */
    do {
        status = VL6180x_ReadBytes(DEV_ADDR, VL6180X_RESULT_ALS_STATUS);
    } while ((status & (1 << 0)) == 0);
    
    VL6180X_WriteBytes(DEV_ADDR,VL6180X_SYSALS_START, START_SINGLE_MODE);
    data_reg = VL6180x_ReadBytes(DEV_ADDR, VL6180X_SYSALS_START);

    status = VL6180x_ReadBytes(DEV_ADDR,VL6180X_RESULT_INTERRUPT_STATUS_GPIO);
    status = status & ALS_SINGLE_MODE_MASK;

//     while (status != ALS_SINGLE_MODE_READY) {
//        status =  VL6180x_ReadBytes(DEV_ADDR, VL6180X_RESULT_INTERRUPT_STATUS_GPIO);
//        status = status & ALS_SINGLE_MODE_MASK;
//        DelayMS(1);
//    }

    alsraw = VL6180x_Read_Two_Bytes(DEV_ADDR, VL6180X_RESULT_ALS_VAL);
    //als = 0.32f * ((float) alsraw / 10.32) * (100.0f/100.0f);
    VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSTEM_INTERRUPT_CLEAR, CLEAR_ALS_INT);

    return alsraw;
}

獲取距離數據

這裏寫圖片描述

uint8 RangePollingRead(void)
{
    uint8 status;
    uint8  distance;

    /* Wait for device ready. */
    do {
        status = VL6180x_ReadBytes(DEV_ADDR, VL6180X_RESULT_RANGE_STATUS);
    } while ((status & (1 << 0)) == 0);
    
    VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSRANGE_START, START_SINGLE_MODE);
    data_reg = VL6180x_ReadBytes(DEV_ADDR, VL6180X_SYSRANGE_START);
    
    status = VL6180x_ReadBytes(DEV_ADDR, VL6180X_RESULT_INTERRUPT_STATUS_GPIO);
    status = status & RANGE_SINGLE_MODE_MASK;
    
     /* Wait for measurement ready. */
    while (status != RANGE_SINGLE_MODE_READY) {
        status = VL6180x_ReadBytes(DEV_ADDR, VL6180X_RESULT_INTERRUPT_STATUS_GPIO);
        status = status & RANGE_SINGLE_MODE_MASK;
        DelayMS(1);
    }
    
    DelayMS(10);
    distance = VL6180x_ReadBytes(DEV_ADDR, VL6180X_RESULT_RANGE_VAL);
    VL6180X_WriteBytes(DEV_ADDR, VL6180X_SYSTEM_INTERRUPT_CLEAR, CLEAR_ALS_INT);
    return distance;
}

GitHub工程源代碼:

https://github.com/lanhaixuan/CC2541_VL6180X_BMA250

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章