BH1750光照传感器详解(STM32)

目录

一、介绍

二、传感器原理

1.原理图

2.工作原理:结构框图

三、程序设计

main.c文件

bh1750.h文件

bh1750.c文件

四、实验效果

五、资料获取

项目分享


一、介绍

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

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

|--------|--------------------------------------------|
| 供电电压 | DC:3~5V |
| 供给电流 | 200uA |
| 工作温度 | -40~+85℃ |
| 测量分辨率 | 0~65535 lx |
| 接口 | I2C |
| 最小误差变动 | 20% |
| 尺寸 | 13.9mm×18.5mm(GY-302) 15.1mm×32.6mm(GY-20) |

哔哩哔哩视频链接:

https://www.bilibili.com/video/BV14T421678Q/?share_source=copy_web&vd_source=097fdeaf6b6ecfed8a9ff7119c32faf2

(资料分享见文末)

二、传感器原理

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.使用STM32F103C8T6读取BH1750光照传感器采集的数据,通过串口发送至电脑

2.将读取得到的光照强度数据同时在OLED上显示

|------------|------|
| BH1750_SCL | PB13 |
| BH1750_SDA | PB12 |
| OLED_SCL | PB11 |
| OLED_SDA | PB10 |
| 串口 | 串口1 |

main.c文件

cpp 复制代码
#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							
 * BILIBILI	:	辰哥单片机设计
 * CSDN			:	辰哥单片机设计
 * 作者			:	辰哥 

**********************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);

  }
}

bh1750.h文件

cpp 复制代码
#ifndef __BH1750_H
#define __BH1750_H
#include "sys.h"
#include "delay.h"

/*****************辰哥单片机设计******************
											STM32
 * 文件			:	BH1750光照强度传感器h文件                   
 * 版本			: V1.0
 * 日期			: 2024.8.5
 * MCU			:	STM32F103C8T6
 * 接口			:	见代码							
 * BILIBILI	:	辰哥单片机设计
 * CSDN			:	辰哥单片机设计
 * 作者			:	辰哥

**********************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

bh1750.c文件

cpp 复制代码
#include "BH1750.h"
#include "delay.h"

/*****************辰哥单片机设计******************
											STM32
 * 文件			:	BH1750光照强度传感器h文件                   
 * 版本			: V1.0
 * 日期			: 2024.8.5
 * MCU			:	STM32F103C8T6
 * 接口			:	见代码							
 * BILIBILI	:	辰哥单片机设计
 * CSDN			:	辰哥单片机设计
 * 作者			:	辰哥

**********************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; 
}

四、实验效果

五、资料获取

项目分享

相关推荐
电子科技圈16 分钟前
芯科科技出展CES 2026并展出如何加速互联智能的未来
科技·嵌入式硬件·mcu·物联网·iot
点灯小铭5 小时前
基于单片机的多路热电偶温度监测与报警器
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
tianyue10010 小时前
STM32G431 ADC 多个channel 采集
stm32·单片机·嵌入式硬件
longson.11 小时前
怎样避免空间碎片而且高效的分配空间
嵌入式硬件·缓存
清风66666611 小时前
基于单片机的水泵效率温差法测量与报警系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
焦糖码奇朵、12 小时前
课设:基于Arduino的无线LED开关控制系统
嵌入式硬件·物联网·arduino·信息与通信·信号处理
z203483152013 小时前
定时器练习报告
单片机·嵌入式硬件
zk0013 小时前
内容分类目录
单片机·嵌入式硬件
安生生申13 小时前
STM32 ESP8266连接ONENET
c语言·stm32·单片机·嵌入式硬件·esp8266
广药门徒13 小时前
电子器件烧毁的底层逻辑与避坑指南
单片机·嵌入式硬件