OPT3001是一款可如人眼般测量光强的单芯片照度计,测量范围0.01 lux-83k lux,使用IIC进行数据通信。它的引脚如下:
它的应用框图如下:
其中SCL,SDA为IIC通信脚,需接上拉电阻
ADDR的接线影响IIC通信地址
INT为中断输出,可设置光强阈值并通过该引脚触发警报
芯片采用IIC通信,有关IIC通信原理可参考:
IIC通信原理-CSDN博客文章浏览阅读298次,点赞5次,收藏8次。这样看起来,区分起止信号与数据电平是不是就更加容易些了,但是嘛由于只有一根数据线了,缺点就是无法同时收发了,因此它是半双工通信的。一般的IIC器件,比如EEPROM,此时会发送要写入或读取的地址,如往0x0000地址写入数字1,那么会先发送0x0000,等到回码后再发送0x01,之后在收到应答后结束通信。前面在讲UART时提到过通信传输所需要的几个必要条件,首先得知道什么时候通信开始,什么时候通信结束,然后就是如何去解析数据了,根据这几点,我们来谈谈IIC是如何实现通信的。从图上可以看到,IIC规定的。https://blog.csdn.net/u011436603/article/details/136007075 光强的获取也很简单,只需要读取寄存器的值,再根据寄存器各位含义稍作转换一下即可,寄存器地址及各位的含义如下:
更具体的各位的含义就得查阅手册了,不过如果只需要获取光强的话,可以直接参考下面的代码:
u16 OPT_ReadUserReg(u8 addr) //读寄存器
{
u8 lsb,msb;
OPT_I2cStartCondition();
OPT_I2cWriteByte(0x88);
OPT_I2cWriteByte(addr);
OPT_I2cStopCondition();
OPT_I2cStartCondition();
OPT_I2cWriteByte(0x89);
msb = OPT_I2cReadByte();
lsb=OPT_I2cReadByte();
OPT_I2cStopCondition();
return (msb<<8)|lsb;
}
void OPT_WriteUserReg(u8 addr,u16 value) //写寄存器
{
OPT_I2cStartCondition();
OPT_I2cWriteByte(0x88);
OPT_I2cWriteByte(addr);
OPT_I2cWriteByte((u8)(value>>8));
OPT_I2cWriteByte((u8)(value&0x00ff));
OPT_I2cStopCondition();
}
float OPT_ReadResult(void)
{
u16 result;
u16 exponent;
u16 raw;
raw = OPT_ReadUserReg(0x00); //读result
result = raw & 0x0fff;
exponent = (raw & 0xf000) >> 12;
return result * 0.01 *(2<<exponent);
}
float OPT_Measure(void)
{
OPT_SCL_OUTPUT();
OPT_SDA_OUTPUT();
OPT_WriteUserReg(0x01,0xcc10); //配置寄存器
delay_ms(800);
return OPT_ReadResult();//获取光强
}
OPT_Measure函数即为最终的获取函数,在这个函数里首先对芯片进行了配置,然后调用OPT_ReadResult去获取光强。而OPT_ReadResult则是读取了0x01地址,即Result寄存器的值,然后再获取E[3:0]的值。
再然后根据手册提供的公式获取到最终的目标值
这里提供的例程仅仅是采集了光强值,并没有用到阈值报警等,因为获取到光强后就可以自己通过软件去设定阈值以及报警事件了,并不一定需要硬件来触发,当然感兴趣的也可以自行研究。
2024.7.19补充驱动时序函数(模拟方式)
void OPT_SCL_OUTPUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void OPT_SCL_INPUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void OPT_SDA_OUTPUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void OPT_SDA_INPUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void OPT_I2cStartCondition(void)
{
OPT_SCL_OUTPUT();
OPT_SDA_OUTPUT();
OPT_SDA_HIGH();
OPT_SCL_HIGH();
delay_us(30);
OPT_SDA_LOW();
delay_us(30);
OPT_SCL_LOW();
}
void OPT_I2cStopCondition(void)
{
OPT_SCL_OUTPUT();
OPT_SDA_OUTPUT();
OPT_SDA_LOW();
OPT_SCL_HIGH();
delay_us(30);
OPT_SDA_HIGH();
delay_us(30);
OPT_SCL_LOW();
}
void OPT_I2cAcknowledge(void)
{
OPT_SCL_OUTPUT();
OPT_SDA_OUTPUT();
OPT_SDA_LOW();
OPT_SCL_HIGH();
delay_us(80);
OPT_SCL_LOW();
delay_us(80);
}
void OPT_I2cNoAcknowledge(void)
{
OPT_SCL_OUTPUT();
OPT_SDA_OUTPUT();
OPT_SDA_HIGH();
OPT_SCL_HIGH();
delay_us(80);
OPT_SCL_LOW();
delay_us(80);
}
u8 OPT_I2cReadByte(void)
{
u8 i, val = 0;
OPT_SCL_OUTPUT();
OPT_SDA_OUTPUT();
OPT_SDA_HIGH();
OPT_SDA_INPUT();
for(i = 0; i < 8; i++)
{
val <<= 1;
OPT_SCL_HIGH();
if(Bit_SET == OPT_SDA_STATE())
{
val |= 0x01;
}
OPT_SCL_LOW();
}
OPT_SDA_OUTPUT();
OPT_SDA_HIGH();
return (val);
}
u8 OPT_I2cWriteByte(u8 byte)
{
u8 i, ack;
OPT_SCL_OUTPUT();
OPT_SDA_OUTPUT();
for(i = 0; i < 8; i++)
{
if(byte & 0x80)
{
OPT_SDA_HIGH();
}
else
{
OPT_SDA_LOW();
}
OPT_SCL_HIGH();
delay_us(80);
OPT_SCL_LOW();
delay_us(80);
byte <<= 1;
}
OPT_SDA_INPUT();
OPT_SCL_HIGH();
if(Bit_SET == OPT_SDA_STATE())
{
ack = ACK_ERROR;
}
else
{
ack = ACK_OK;
}
OPT_SCL_LOW();
OPT_SDA_OUTPUT();
OPT_SDA_HIGH();
return (ack);
}