BH1750光照强度传感器详解(STM32)

传感器介绍

BH1750是一款数字型光照强度传感器,能够获取周围环境的光照强度。内置16bitAD转换器,其测量范围在0~65535 lx(勒克斯,光照强度的单位),不区分环境光源。BH1750可用于调节手机屏幕和键盘的背光功率,或者用于智能灯光控制,比如,随着外界光照强度的变化调节灯光亮度。

 

 

以下是BH1750光照传感器的参数:

    

供电电压 

DC:3-5V

供给电流

200uA

工作温度

-40~+85℃

测量分辨率

0~65535 lx

接口

IIC

最小误差变动

20%

尺寸

13.9mm×18.5mm(GY-302)

15.1mm×32.6mm(GY-20)

 传感器原理

 

 

 

1.原理图

 

以下是传感器的引脚描述:

 

引脚名称

描述

VCC

供给电压3~5V

SCL

I2C总线时钟线

SDA

I2C总线数据线

ADDR

I2C地址引脚

GND

电源地

 

2.工作原理(结构框图)

 

  • PD —— 接近人眼反应的光敏二极管

  • AMP —— 集成运算放大器(将PD电流转换为PD电压)

  • ADC —— 模数转换获取16位数字数据

  • Logic + I2C Interface(逻辑+I2C界面)

  • OSC —— 内部振荡器(内部逻辑时钟,频率典型值:320kHz)

 

PD二极管通过光伏效应将输入光信号转换成电信号,经运放电路放大后,电压经ADC采集,再经逻辑电路转换成16位二进制数,存储在内部的寄存器中。

BH1750引出了时钟线和数据线,单片机可以通过I2C协议与BH1750进行通讯,可选择BH1750的工作模式,提取BH1750寄存器中的照度数据

程序设计 

 

1. main.c文件

#include "stm32f10x.h"#include "led.h"#include "usart.h"#include "delay.h"#include "oled.h"#include "bh1750.h"
/*****************毕业设计****************** STM32 * 项目 : 2.BH1750光照强度传感器实验 * 版本 : V1.0 * 日期 : 2024.8.5 * MCU : STM32F103C8T6 * 接口 : 参看bh1750.h
**********************BEGIN***********************/
u16 light;u8 buff[30];
int main(void){ SystemInit();//配置系统时钟为72M delay_init(72); LED_Init(); LED_On();
USART1_Config();//串口初始化 OLED_Init(); BH1750_Init(); printf("Start \n"); delay_ms(1000);
//显示“光照强度:” OLED_ShowChinese(1,1, 4); OLED_ShowChinese(1,2, 5); OLED_ShowChinese(1,3, 34); OLED_ShowChinese(1,4, 1); OLED_ShowChar(1, 9, ':'); while (1) { light = bh_data_read(); printf("光照强度: %d \r\n",light); LED_Toggle(); sprintf((char *)buff,"%5d",light); OLED_ShowString(1,10,buff); delay_ms(500);
}}

 

2. bh1750.h文件

#ifndef __BH1750_H#define __BH1750_H#include "sys.h"#include "delay.h"
/*****************毕业设计****************** STM32 * 文件 : BH1750光照强度传感器h文件 * 版本 : V1.0 * 日期 : 2024.8.5 * MCU : STM32F103C8T6 * 接口 : 见代码
**********************BEGIN***********************/
/***************根据自己需求更改****************///BH1750引脚宏定义#define BH1750_GPIO_CLK RCC_APB2Periph_GPIOB#define BH1750_GPIO_PORT GPIOB#define BH1750_SCL_GPIO_PIN GPIO_Pin_13#define BH1750_SDA_GPIO_PIN GPIO_Pin_12
#define IIC_SCL PBout(13) //SCL#define IIC_SDA PBout(12) //SDA #define READ_SDA PBin(12) //输入SDA #define ADDR 0x23//0100011#define uchar unsigned char /*********************END**********************/
#define BHAddWrite 0x46 //从机地址+最后写方向位#define BHAddRead 0x47 //从机地址+最后读方向位#define BHPowDown 0x00 //关闭模块#define BHPowOn 0x01 //打开模块等待测量指令#define BHReset 0x07 //重置数据寄存器值在PowerOn模式下有效#define BHModeH1 0x10 //高分辨率 单位1lx 测量时间120ms#define BHModeH2 0x11 //高分辨率模式2 单位0.5lx 测量时间120ms#define BHModeL 0x13 //低分辨率 单位4lx 测量时间16ms#define BHSigModeH 0x20 //一次高分辨率 测量 测量后模块转到 PowerDown模式#define BHSigModeH2 0x21 //同上类似#define BHSigModeL 0x23 // 上类似
void Single_Write_BH1750(uchar REG_Address);void BH1750_Init(void);void bh_data_send(u8 command);u16 bh_data_read(void);
//IIC所有操作函数void BH1750_IIC_Init(void); //初始化IIC的IO口 void BH1750_IIC_Start(void); //发送IIC开始信号void BH1750_IIC_Stop(void); //发送IIC停止信号void BH1750_IIC_Send_Byte(u8 txd); //IIC发送一个字节u8 BH1750_IIC_Read_Byte(unsigned char ack);//IIC读取一个字节u8 BH1750_IIC_Wait_Ack(void); //IIC等待ACK信号void BH1750_IIC_Ack(void); //IIC发送ACK信号void BH1750_IIC_NAck(void); //IIC不发送ACK信号
void BH1750_IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);u8 BH1750_IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif

 

3. bh1750.c文件

#include "BH1750.h"#include "delay.h"
/*****************毕业设计****************** STM32 * 文件 : BH1750光照强度传感器h文件 * 版本 : V1.0 * 日期 : 2024.8.5 * MCU : STM32F103C8T6 * 接口 : 见代码
**********************BEGIN***********************/
typedef unsigned char BYTE;//BYTE BUF[8]; //接收数据缓存区 //iic接口初始化
/**** 设置SDA为输出**/void SDA_OUT(void){ GPIO_InitTypeDef GPIO_InitStructer; GPIO_InitStructer.GPIO_Pin= BH1750_SDA_GPIO_PIN; GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructer.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_Init(BH1750_GPIO_PORT, &GPIO_InitStructer);}

/**** 设置SDA为输入**/void SDA_IN(void){ GPIO_InitTypeDef GPIO_InitStructer; GPIO_InitStructer.GPIO_Pin= BH1750_SDA_GPIO_PIN; GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructer.GPIO_Mode=GPIO_Mode_IPU; GPIO_Init(BH1750_GPIO_PORT, &GPIO_InitStructer);}

void Single_Write_BH1750(uchar REG_Address){ BH1750_IIC_Start(); //起始信号 BH1750_IIC_Send_Byte(BHAddWrite); //发送设备地址+写信号 BH1750_IIC_Send_Byte(REG_Address); //内部寄存器地址, // BH1750_SendByte(REG_data); //内部寄存器数据, BH1750_IIC_Stop(); //发送停止信号}
void BH1750_Init(void){ GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(BH1750_GPIO_CLK, ENABLE); //使能A端口时钟 GPIO_InitStructure.GPIO_Pin = BH1750_SCL_GPIO_PIN|BH1750_SDA_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz GPIO_Init(BH1750_GPIO_PORT, &GPIO_InitStructure); //初始化GPIOD3,6 GPIO_SetBits(BH1750_GPIO_PORT,BH1750_SCL_GPIO_PIN|BH1750_SDA_GPIO_PIN);
//Single_Write_BH1750(0x01); bh_data_send(BHPowOn); //BH1750上电 bh_data_send(BHReset); //BH1750复位 bh_data_send(BHModeH2); //BH1750写入测量模式:选择的是分辨率是4lx,测量时间是16ms的}
//产生IIC起始信号void BH1750_IIC_Start(void){ 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_IIC_Stop(void){ SDA_OUT();//sda线输出 IIC_SCL=0; IIC_SDA=0;//STOP:when CLK is high DATA change form low to high delay_us(4); IIC_SCL=1; IIC_SDA=1;//发送I2C总线结束信号 delay_us(4); }//等待应答信号到来//返回值:1,接收应答失败// 0,接收应答成功u8 BH1750_IIC_Wait_Ack(void){ u8 ucErrTime=0; SDA_IN(); //SDA设置为输入 IIC_SDA=1;delay_us(1); IIC_SCL=1;delay_us(1); while(READ_SDA) { ucErrTime++; if(ucErrTime>250) { BH1750_IIC_Stop(); return 1; } } IIC_SCL=0;//时钟输出0 return 0; } //产生ACK应答void BH1750_IIC_Ack(void){ IIC_SCL=0; SDA_OUT(); IIC_SDA=0; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0;}//不产生ACK应答 void BH1750_IIC_NAck(void){ IIC_SCL=0; SDA_OUT(); IIC_SDA=1; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0;} //IIC发送一个字节//返回从机有无应答//1,有应答//0,无应答 void BH1750_IIC_Send_Byte(u8 txd){ u8 t; SDA_OUT(); IIC_SCL=0;//拉低时钟开始数据传输 for(t=0;t<8;t++) { //IIC_SDA=(txd&0x80)>>7; if((txd&0x80)>>7) IIC_SDA=1; else IIC_SDA=0; txd<<=1; delay_us(2); //对TEA5767这三个延时都是必须的 IIC_SCL=1; delay_us(2); IIC_SCL=0; delay_us(2); } } //读1个字节,ack=1时,发送ACK,ack=0,发送nACK u8 BH1750_IIC_Read_Byte(unsigned char ack){ unsigned char i,receive=0; SDA_IN();//SDA设置为输入 for(i=0;i<8;i++ ) { IIC_SCL=0; delay_us(2); IIC_SCL=1; receive<<=1; if(READ_SDA)receive++; delay_us(1); } if (!ack) BH1750_IIC_NAck();//发送nACK else BH1750_IIC_Ack(); //发送ACK return receive;}
/*************************************************************************************/void bh_data_send(u8 command){ do{ BH1750_IIC_Start(); //iic起始信号 BH1750_IIC_Send_Byte(BHAddWrite); //发送器件地址 }while(BH1750_IIC_Wait_Ack()); //等待从机应答 BH1750_IIC_Send_Byte(command); //发送指令 BH1750_IIC_Wait_Ack(); //等待从机应答 BH1750_IIC_Stop(); //iic停止信号}
u16 bh_data_read(void){ u16 buf; BH1750_IIC_Start(); //iic起始信号 BH1750_IIC_Send_Byte(BHAddRead); //发送器件地址+读标志位 BH1750_IIC_Wait_Ack(); //等待从机应答 buf=BH1750_IIC_Read_Byte(1); //读取数据 buf=buf<<8; //读取并保存高八位数据 buf+=0x00ff&BH1750_IIC_Read_Byte(0); //读取并保存第八位数据 BH1750_IIC_Stop(); //发送停止信号 return buf; }

实验演示

 

 

 

 

posted @ 2024-12-17 21:23  jefften  阅读(4232)  评论(0)    收藏  举报