【年中粉丝节】+BH1750光照度传感器 今天就再分享下一个光照度传感器。也是比较简单,和之前的温湿度传感器一样的是使用IIC接口,所以两个器件是可以挂载在同一个总线上的,因为他们有不同的地址。 可以测1-65535lx的光度值。可以用在LCD调光方面。 下面是芯片内部架构,其实使用的是16位的ADC,输出是12位的,所以可见波动是很小的。 上面的图是描述的芯片读取数据的一个流程。 上面是芯片内部寄存器的一个表,同时下面很重要的是器模式配置,可以配置1分度的,也可以配置更高的分辨率0.5和低的4。 下面直接跳到重点,首先是确定其器件地址,我们这里把ADDR 脚拉低了所以器件地址就是上面是七位同样需要左移一位。变成0100 0110。也就是0x46。 - #include "sys.h"
- #include "delay.h"
- #include "bh1750.h"
-
-
- #define SlaveAddress 0x46 //定义器件在IIC总线中的从地址,根据ALT ADDRESS地址引脚不同修改
- uint8_t BUF[4]; //接收数据缓存区
- extern uint16_t Light_Value;
- //uint16_t Light_Value;
-
- void BH1750_PortInit()
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
-
- //PB6-SCL PB7-SDA PB12-ADDR
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); //PB6,PB7 输出高
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PB.14 PB.12
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
- GPIO_Init(GPIOC, &GPIO_InitStructure);
-
- }
-
-
- /***************************************************************
- ** 功能: 产生IIC起始信号
- ** 参数: 无参数
- ** 返回值: 无
- ****************************************************************/
- void BH1750_Start()
- {
- SDA_OUT(); //sda线输出
- IIC_SDA=1;
- IIC_SCL=1;
- delay_us(4);
- IIC_SDA=0;//START:when CLK is high,DATA change form high to low
- delay_us(4);
- IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
- }
- /***************************************************************
- ** 功能: 产生IIC停止信号
- ** 参数: 无参数
- ** 返回值: 无
- ****************************************************************/
- void BH1750_Stop()
- {
- SDA_OUT();//sda线输出
- IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
- IIC_SCL=1;
- delay_us(4);
- IIC_SDA=1;//发送I2C总线结束信号
- delay_us(4);
- }
- /***************************************************************
- ** 功能: 产生IIC应答信号
- ** 参数: 无参数
- ** 返回值: 无
- ****************************************************************/
- void BH1750_SendACK(u8 ack)
- {
- SDA_OUT(); //sda线输出
- if(ack)IIC_SDA=1; //写应答信号
- else IIC_SDA=0;
- IIC_SCL=1; //拉高时钟线
- delay_us(2); //延时
- IIC_SCL=0; //拉低时钟线
- delay_us(2); //延时
- }
-
- /***************************************************************
- ** 功能: 产生IIC接收信号
- ** 参数: 无参数
- ** 返回值: 无
- ****************************************************************/
- u8 BH1750_RecvACK()
- {
- u8 data;
- SDA_IN(); //SDA设置为输入
- IIC_SCL=1; //拉高时钟线
- delay_us(2); //延时
- data = READ_SDA; //读应答信号
- IIC_SCL=0; //拉低时钟线
- delay_us(2); //延时
- return data;
- }
- /***************************************************************
- ** 功能: 向IIC总线发送一个字节数据
- ** 参数: dat:一字节数据
- ** 返回值: 无
- ****************************************************************/
- void BH1750_SendByte(u8 dat)
- {
- u8 i,bit;
- SDA_OUT(); //sda线输出
- for (i=0; i<8; i++) //8位计数器
- {
- bit=dat&0x80;
- if(bit) IIC_SDA=1;
- else IIC_SDA=0;
- dat <<= 1; //移出数据的最高位
- IIC_SCL=1; //拉高时钟线
- delay_us(2); //延时
- IIC_SCL=0; //拉低时钟线
- delay_us(2); //延时
- }
- BH1750_RecvACK();
- }
- /***************************************************************
- ** 功能: 从IIC总线接收一个字节数据
- ** 参数: 无参数
- ** 返回值: dat:接收一字节数据
- ****************************************************************/
- u8 BH1750_RecvByte()
- {
- u8 i;
- u8 dat = 0;
- SDA_IN(); //SDA设置为输入
- IIC_SDA=1; //使能内部上拉,准备读取数据,
- for (i=0; i<8; i++) //8位计数器
- {
- dat <<= 1;
- IIC_SCL=1; //拉高时钟线
- delay_us(2); //延时
- if(READ_SDA) dat+=1;
- IIC_SCL=0; //拉低时钟线
- delay_us(2); //延时
- }
- return dat;
- }
-
- /***************************************************************
- ** 功能: 向bh1750写入命令
- ** 参数: 无参数
- ** 返回值: 无
- ****************************************************************/
- void Single_Write_BH1750(u8 REG_Address)
- {
- BH1750_Start(); //起始信号
- BH1750_SendByte(SlaveAddress); //发送设备地址+写信号
- BH1750_SendByte(REG_Address); //内部寄存器地址,
- BH1750_Stop(); //发送停止信号
- }
-
- /***************************************************************
- ** 功能: 连续读出BH1750内部数据
- ** 参数: 无参数
- ** 返回值: 无
- ****************************************************************/
- void Multiple_Read_BH1750(void)
- { u8 i;
- BH1750_Start(); //起始信号
- BH1750_SendByte(SlaveAddress+1); //发送设备地址+读信号
-
- for (i=0; i<3; i++) //连续读取2个地址数据,存储中BUF
- {
- BUF[i] = BH1750_RecvByte(); //BUF[0]存储0x32地址中的数据
- if (i == 3)
- {
- BH1750_SendACK(1); //最后一个数据需要回NOACK
- }
- else
- {
- BH1750_SendACK(0); //回应ACK
- }
- }
- BH1750_Stop(); //停止信号
- // delay_ms(150);
- }
-
- /***************************************************************
- ** 功能: 初始化BH1750
- ** 参数: 无参数
- ** 返回值: 无
- ****************************************************************/
- void BH1750_Configure(void)
- {
- BH1750_PortInit();
- Single_Write_BH1750(0x01);
- ADDR = 0; //将ADDR位初始化拉低
- }
-
- /***************************************************************
- ** 功能: 读取光照度
- ** 参数: 无参数
- ** 返回值: data:返回光照度值
- ****************************************************************/
- uint16_t Get_Bh_Value(void)
- {
- static float temp;
- // u16 data;
- int dis_data ;
- Single_Write_BH1750(0x01); // power on
- Single_Write_BH1750(0x10); // H- resolution mode
- // delay_ms(200); //延时200ms
- Multiple_Read_BH1750(); //连续读出数据,存储在BUF中
- dis_data=BUF[0];
- dis_data=(dis_data<<8)+BUF[1];//合成数据,即光照数据
- temp=(float)dis_data/1.2;
- Light_Value =(int)temp;
- return Light_Value;
- }
复制代码
上面是所有代码,我们只需要在主函数终循环。Get_Bh_Value(void);就行。 我们这里就是使用的简单模式H-resolution mode,没有用其模式2,模式二可以更改采样时间,从而提高精度。感兴趣可以自己去看下,就是比较靠后的就是模式二的用法。 当手机手电筒放到其光窗上可以测到最大54612。还没有到65535。 同样使用的是昨天的板子。
|
用的是自制的STM32F103VET6开发板