VEML7700光照传感器驱动总结及详解

VEML7700是一款高精度环境光数字16位分辨率传感器,采用微型透明6.8 mm x 2.35 mm x 3.0 mm封装。它包括一个高灵敏度的光电二极管,一个低噪声放大器,一个16位a /D转换器,并支持一个易于使用的12C总线通信接口。

I2C器件的驱动方式很简单,其读写时序也是典型的I2C读写时序。

VEML7700包含实际的6个16位命令代码,用于操作控制、参数设置和结果缓冲。所有寄存器都可通过l2C通信访问。内置I2C接口兼容I2C模式“标准”和“快速”:10khz至400khz。2C h电平范围为1.3 V ~ 3.6 V。详细信息请参考NXP的I2C规格。读写时序如下。

 

        其从机地址只有7bit,即001 0000 = 0x10,而根据I2C总线通信方式,按照8bit为一个数据的传输,7bit从机地址之后的1个bit表示读写方向,总线地址0010 0000= 0x20用于写,0010 0001= 0x21用于读。

        VEML7700有6个用户可访问的16位命令地址,具体为00h到06h (03h未定义/保留)。

        这6个16位命令地址用于操作控制、参数设置和获取结果参数。所有寄存器都可以通过l2C通信访问。具体命令表如下所示:

 具体寄存器描述如下:

命令0:可配置增益、积分时间、存储保护数字、中断使能、上电使能

  命令1:配置照明度上限窗口值

命令2:配置照明度下限窗口值 

 命令3:工作模式配置及节电使能

 命令4:光照度高分辨率输出值

 命令5:白色通道输出值

 命令6:中断状态标志

        配置对应的命令,可获得不一样的分辨率,其量程也相对应得到调整控制,具体增益(lx/bit 即流明/位)和量程(0~120klx)如下表所示;

 后面附上实际控制代码,为模拟i2c读写接口

#define VEML_SDA_PIN         GPIO_Pin_12
#define VEML_SDA_SET_OUTPUT  GPIOB_ModeCfg(VEML_SDA_PIN,GPIO_ModeOut_PP_5mA)
#define VEML_SDA_SET_INPUT   GPIOB_ModeCfg(VEML_SDA_PIN,GPIO_ModeIN_PU)
#define VEML_SDA_H           GPIOB_SetBits(VEML_SDA_PIN)
#define VEML_SDA_L           GPIOB_ResetBits(VEML_SDA_PIN)
#define READ_VEML_SDA        !!(GPIOB_ReadPortPin(VEML_SDA_PIN))

#define VEML_SCL_PIN         GPIO_Pin_13
#define VEML_SCL_SET_OUTPUT  GPIOB_ModeCfg(VEML_SCL_PIN,GPIO_ModeOut_PP_5mA)
#define VEML_SCL_H           GPIOB_SetBits(VEML_SCL_PIN)
#define VEML_SCL_L           GPIOB_ResetBits(VEML_SCL_PIN)




#define   SlaveAddress_WR 0x20
#define   SlaveAddress_RD 0x21
#define   SlaveAddress   0x21 //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
                              //ALT  ADDRESS引脚接地时地址为0x46,接电源时地址为0xB8
uint8_t BUF[8] = {0};
uint16_t     dis_data;                       //变量
uint32_t   dis_temp;
void VEML7700_i2c_port_init(void)
{
//    GPIOB_ModeCfg(GPIO_Pin_13 | GPIO_Pin_12, GPIO_ModeIN_PU);
    VEML_SDA_SET_INPUT;
    VEML_SCL_SET_OUTPUT;
    VEML_SCL_H;
}

/**************************************
起始信号
**************************************/
void VEML7700_Start()
{
    VEML_SDA_SET_OUTPUT;
    VEML_SDA_H;//SDA = 1;                    //拉高数据线
    VEML_SCL_H;//SCL = 1;                    //拉高时钟线
    DelayUs(5);//Delay5us();                 //延时
    VEML_SDA_L;//SDA = 0;                    //产生下降沿
    DelayUs(5);//Delay5us();                 //延时
    VEML_SCL_L;//SCL = 0;                    //拉低时钟线
}

/**************************************
停止信号
**************************************/
void VEML7700_Stop()
{
    VEML_SDA_SET_OUTPUT;
    VEML_SDA_L;//SDA = 0;                    //拉低数据线
    VEML_SCL_H;//SCL = 1;                    //拉高时钟线
    DelayUs(5);//Delay5us();                 //延时
    VEML_SDA_H;//SDA = 1;                    //产生上升沿
    DelayUs(5);//Delay5us();                 //延时
}

/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void VEML7700_SendACK(uint8_t ack)
{
    VEML_SDA_SET_OUTPUT;
    if(ack == 1)
    {
        VEML_SDA_H;
    }
    else {
        VEML_SDA_L;
    }
//    SDA = ack;                  //写应答信号
    VEML_SCL_H;//SCL = 1;                    //拉高时钟线
    DelayUs(5);//Delay5us();                 //延时
    VEML_SCL_L;//SCL = 0;                    //拉低时钟线
    DelayUs(5);//Delay5us();                 //延时
}

/**************************************
接收应答信号
**************************************/
uint8_t VEML7700_RecvACK()
{
    uint8_t ack_rcv = 0;
    VEML_SDA_SET_INPUT;
    VEML_SCL_H;//SCL = 1;                    //拉高时钟线
    DelayUs(5);//Delay5us();                 //延时
    ack_rcv = READ_VEML_SDA;//CY = SDA;                   //读应答信号
    VEML_SCL_L;//SCL = 0;                    //拉低时钟线
    DelayUs(5);//Delay5us();                 //延时

    return ack_rcv;
}

/**************************************
向IIC总线发送一个字节数据
**************************************/
void VEML7700_SendByte(uint8_t dat)
{
    uint8_t i;
    VEML_SDA_SET_OUTPUT;
    for (i=0; i<8; i++)         //8位计数器
    {
        if(dat & 0x80)
        {
            VEML_SDA_H;
        }
        else {
            VEML_SDA_L;
        }
        dat <<= 1;              //移出数据的最高位
//        SDA = CY;               //送数据口
        VEML_SCL_H;//SCL = 1;                //拉高时钟线
        DelayUs(5);//Delay5us();             //延时
        VEML_SCL_L;//SCL = 0;                //拉低时钟线
        DelayUs(5);//Delay5us();             //延时
    }
    VEML7700_RecvACK();
}

/**************************************
从IIC总线接收一个字节数据
**************************************/
uint8_t VEML7700_RecvByte()
{
    uint8_t i;
    uint8_t dat = 0;

    VEML_SDA_SET_INPUT;
//    SDA = 1;                    //使能内部上拉,准备读取数据,

    for (i=0; i<8; i++)         //8位计数器
    {
        dat <<= 1;
        VEML_SCL_H;//SCL = 1;                //拉高时钟线
        DelayUs(5);//Delay5us();             //延时
        dat |= READ_VEML_SDA;             //读数据
        VEML_SCL_L;//SCL = 0;                //拉低时钟线
        DelayUs(5);//Delay5us();             //延时
    }
    return dat;
}




void Write_VEML7700_CMD(uint8_t CMD,uint16_t config_info)
{
    VEML7700_Start();                  //起始信号
    VEML7700_SendByte(SlaveAddress_WR);   //发送设备地址+写信号
    VEML7700_SendByte(CMD);    //内部寄存器地址,
    VEML7700_SendByte(config_info & 0xff);//low 8 bit
    VEML7700_SendByte((config_info >> 8) & 0xff);//high 8 bit
    VEML7700_Stop();
}



void Read_VEML7700_ALS_VAL(void)
{
    uint8_t i;
    VEML7700_Start();                          //起始信号
    VEML7700_SendByte(SlaveAddress_WR);         //发送设备地址+读信号
    VEML7700_SendByte(CMD_ALS_VAL);
    VEML7700_Start();
    VEML7700_SendByte(SlaveAddress_RD);
     for (i=0; i<3; i++)                      //连续读取2个地址数据,存储中BUF
    {
        BUF[i] = VEML7700_RecvByte();          //BUF[0]存储0x32地址中的数据
        if (i == 3)
        {
           VEML7700_SendACK(1);                //最后一个数据需要回NOACK
        }
        else
        {
          VEML7700_SendACK(0);                //回应ACK
       }
   }

    VEML7700_Stop();                          //停止信号
    DelayMs(5);
}



uint8_t VEML7700_work_task(void)
{
    static uint8_t ret = 0;
    static uint8_t cnt = 6;
    if(ret == 0)
    {
        ret = 1;
        if(cnt == 6)//运行一次,需要配置不同量程时再修改调用
        {
            Write_VEML7700_CMD(CMD_ALS_CONF_0,0x1300);   // gain = 1/8, ALS intergeration time = 25ms,protect num = 1,ALS interrupt disable,power on
            Write_VEML7700_CMD(CMD_PWR_SAVING,0x00);   //mode 1,power saving disable
        }
    }
    else {
        ret = 0;
        Read_VEML7700_ALS_VAL();//连续读出数据,存储在BUF中
        dis_data=BUF[1];//高位在前
        dis_data=(dis_data<<8)+BUF[0];//合成数据,即光照数据
        dis_temp = (uint32_t)((dis_data * 1152)/625);
        cnt++;
        if(cnt >= 5)
        {
            cnt = 0;
//            PRINT("buf0:%d,buf1:%d,dis_temp:%d\n",BUF[0],BUF[1],dis_temp);
        }
        PRINT("buf0:%d,buf1:%d,dis_temp:%d\n",BUF[0],BUF[1],dis_temp);
    }
    return ret;
}

 

 

 

物联沃分享整理
物联沃-IOTWORD物联网 » VEML7700光照传感器驱动总结及详解

发表评论