单片机学习小组
直播中

新疆切糕

13年用户 1266经验值
私信 关注

VEML6040颜色传感器是如何利用I2C总线进行数据传输呢

VEML6040是什么?VEML6040颜色传感器的外围电路是怎样的?
VEML6040颜色传感器是如何利用I2C总线进行数据传输呢?

回帖(1)

王芳

2022-2-14 14:34:19
1 VEML6040颜色传感器

1.1 芯片简介

关于VEML6040颜色传感器的详细介绍可以到这个网址去看

简单点来说,VEML6040是一款颜色传感器,可以获取当前颜色的RGBW值(W值有什么用我也不知道),然后通过计算得到色坐标,最终得到采集的颜色。
VEML6040适用于3.3V的单片机系统,采用I2C总线传输数据,使用OPLG封装(这种封装手焊很难的,因为引脚在芯片正下面)

芯片长这样的,手册里面也给出了推荐的焊盘尺寸:

手册里面得到4个焊盘的大小是不一样的,在立创商城里面也给出了推荐的尺寸:

这里面给出的是4个一样的,我实际用的这种封装焊接过,大小正好,但是还是差点,我推荐用手册中给出的,但是可以画成一样的4个焊盘。
1.2 芯片外围电路

手册中给出了芯片的推荐电路:

外围电路非常简单,
1.GND接地就可以
2.VDD接电源,但是要接0.1UF的电容滤波,所以在给芯片供电的时候,电源线要先经过电容再接入芯片
3.I2C的2根数据线分别接入单片机的I2C总线的引脚。当然你也可以使用I/O口软件模拟I2C的时序,这样的话就直接接2个普通的I/O口就可以了。
4.2跟数据线要通过2个上啦电阻拉高至3.3V(电源电压)

2 I2C总线

至于什么是I2C总线,百度比我解释的更加清楚,大家可以自己去查,VEML6040采用的是I2C总线进行数据传输,我们得首先知道I2C中的几个命令:

还有VEML6040在进行数据传输的时候的方式,手册里面给出了在进行获取颜色数据时候的时序:

3 基于STM32的程序

3.1 I2C驱动

首先我们应该写出I2C的驱动程序,就是上面说的那几个信号,开始、结束、应答信号。我这里采用的是是使用软件模拟的方式来驱动。
3.1.1 I/O口设置

使用软件模拟的话,就随便使用2个I/O就可以了,I/O口设置为输出模式就可以

__HAL_RCC_GPIOB_CLK_ENABLE();
   GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


3.1.2 开始信号

这里的SDA1和SCL1是我之前久宏定义好的,就是对应相应的I/O口

void IIC1_Start(void)
{
        SDA1_OUT();     //sda线输出
        SDA1=1;                    
        SCL1=1;
        delay_us(4);
        SDA1=0;//START:when CLK is high,DATA change form high to low
        delay_us(4);
        SCL1=0;//钳住I2C总线,准备发送或接收数据
}         
3.1.3 停止信号

void IIC1_Stop(void)
{
        SDA1_OUT();//sda线输出
        SCL1=0;
        SDA1=0;//STOP:when CLK is high DATA change form low to high
        delay_us(4);
        SCL1=1;
        SDA1=1;//发送I2C总线结束信号
        delay_us(4);                                                                  
}


3.1.4 等待应答信号

这里的SDA1_IN()是把这个I/O口设置为输入模式
我这里使操作寄存器实现的,就是把相应的寄存器置位就可以。

//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
#define SDA7_IN() {GPIOB->CRH&=0XF0FFFFFF;GPIOB->CRH|=(u32)8<<24;}
u8 IIC1_Wait_Ack(void)
{
        u8 ucErrTime=0;
        SDA1_IN();      //SDA设置为输入  
        SDA1=1;delay_us(1);          
        SCL1=1;delay_us(1);         
        while(Read_SDA1)
        {
                ucErrTime++;
                if(ucErrTime>250)
                {
                        IIC1_Stop();
                        return 1;
                }
        }
        SCL1=0;//时钟输出0           
        return 0;  
}
3.1.5 应答信号

这里的SDA1_OUT()是把这个I/O口设置为输出模式
我这里使操作寄存器实现的,就是把相应的寄存器置位就可以。

//不产生ACK应答                    
void IIC1_NAck(void)
{
        SCL1=0;
        SDA1_OUT();
        SDA1=1;
        delay_us(2);
        SCL1=1;
        delay_us(2);
        SCL1=0;
}       
   

3.1.7 给指定地址发送信号


void IIC1_Send_Byte(u8 txd)
{                        
    u8 t;   
        SDA1_OUT();             
    SCL1=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        SDA1=(txd&0x80)>>7;
                        if(txd==1) SDA1=1;
                        if(txd==0) SDA1=0;       
        txd<<=1;           
                delay_us(2);   
                SCL1=1;
                delay_us(2);
                SCL1=0;       
                delay_us(2);
    }         
}
经过以上几个步骤,I2C的驱动代码基本上就完成了。
3.2 VEML6040驱动

3.2.1 读取数据

这个函数可以在制定的地址读取数据

#define VEML6040_ADDR 0x20
u16 VEML6040_1_ReadByte(u16 ReadAddr)                                        //指定地址读取一个字节
{
   u16 data=0;
        u8 m***=0;
        u8 l***=1;
         IIC1_Start();
                IIC1_Send_Byte(VEML6040_ADDR);           //发送写命令
        if(IIC1_Wait_Ack()==1)  return 1;
        IIC1_Send_Byte(ReadAddr);
        if(IIC1_Wait_Ack()==1)  return 1;  
       
          IIC1_Start();
       
        IIC1_Send_Byte((VEML6040_ADDR)+1);  //
                if(IIC1_Wait_Ack()==1)  return 1;
       
          l***=IIC1_Read_Byte(0);                   
          m***=IIC1_Read_Byte(0);  
       
          IIC1_Stop();
          data=((uint16_t)m*** << 8)|l***;
          return data;
}
3.2.2 写入数据

这个函数可以在制定的地址写入制定的数据或者命令,用来设置颜色传感器里面的一些参数
uint8_t VEML6040_1_Write_Bytes(uint8_t res,uint8_t cmd)

{
                uint8_t m***,l***;
          m***=0x00;
                l***=cmd;
          IIC1_Start();
       
          IIC1_Send_Byte(VEML6040_ADDR);
    if(IIC1_Wait_Ack()==1)  return 1;
     
                IIC1_Send_Byte(res);
                if(IIC1_Wait_Ack()==1)  return 1;  

                IIC1_Send_Byte(l***);
                if(IIC1_Wait_Ack()==1)  return 1;
          
          IIC1_Send_Byte(m***);
                if(IIC1_Wait_Ack()==1)  return 1;
          IIC1_Stop();
          return 0;
}
3.3 设置参数

这里的意思是向0X10这个地址里面写入了0X00这个命令,是用来设置传感器的相应参数,
                veml_1_Ack = VEML6040_1_Write_Bytes(0x10,0x00);         
如果你想设置别的参数,只需要按照手册里面的表格设置相应的参数就可以了
3.4 读取数据

分别从不同的地址读取不同的颜色数据

                 if(veml_1_Ack==0)
                 {
                         VEML6040_No_Read(1,0x08);
                   VEML6040_1_R = VEML6040_1_ReadByte(0x08);//红       
                   VEML6040_1_G = VEML6040_1_ReadByte(0x09);//绿
                   VEML6040_1_B = VEML6040_1_ReadByte(0x0A);//蓝       
                   VEML6040_1_W = VEML6040_1_ReadByte(0x0B);//白
                 }
举报

更多回帖

发帖
×
20
完善资料,
赚取积分