STM32外设系列—BH1750

news2024/9/20 14:15:46

文章目录

  • 一、BH1750简介
  • 二、BH1750原理图
  • 三、BH1750数据手册
    • 3.1 指令集
    • 3.2 IIC通信读/写
  • 四、BH1750程序设计
    • 4.1 IIC程序
    • 4.2 BH1750初始化程序
    • 4.3 读取BH1750测量结果
    • 4.4 获取光照强度
    • 4.5 相关宏定义
  • 五、应用实例
  • 六、拓展应用
    • 6.1 实时调节LED亮度
    • 6.2 实时调整颜色阈值

一、BH1750简介

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

BH1750

BH1750有以下特点

  • I2C总线接口
  • 接近视觉灵敏度的光谱灵敏度特性
  • 输出对应亮度的数字值
  • 高分辨率(0~65535 lx)
  • 通过降低功率功能,实现低电流化
  • 50Hz / 60Hz光噪声抑制功能
  • 可以选择两种类型的I2C从属地址
  • 最小误差变动在±20%
  • 受红外线影响很小

二、BH1750原理图

BH1750原理图

  • PD —— 接近人眼反应的光敏二极管
  • AMP —— 集成运算放大器(将 PD 电流转换为 PD 电压)
  • ADC —— 模数转换获取 16 位数字数据
  • Logic + IC Interface(逻辑+ IC 界面)
  • OSC —— 内部振荡器(该时钟为内部逻辑时钟,时钟频率典型值:320kHz)

PD二极管通过光伏效应将输入光信号转换成电信号,经运放电路放大后,电压经ADC采集,再经逻辑电路转换成16位二进制数,存储在内部的寄存器中(进入光窗的光越强,光电流越大,电压就越大,所以光强可以通过电压的大小判断,但是应该注意的是,虽然电压和光强一一对应,但它们不是成正比关系,所以该芯片内部是对数据进行了线性处理,这就是为什么直接使用集成IC而不是光电二极管的原因)。BH1750引出了时钟线和数据线,单片机可以通过I2C协议与BH1750进行通讯,可选择BH1750的工作模式,提取BH1750寄存器中的照度数据。

三、BH1750数据手册

3.1 指令集

BH1750的数据手册中给出了一些指令

BH1750指令集

其中的H分辨率模式和L分辨率模式等,是BH1750的测量模式,数据手册中也给出了说明

BH1750测量模式

我们通常使用H分辨率模式,H 分辨率模式下足够长的测量时间(积分时间)能够抑制一些噪声(包括 50Hz/60Hz)。同时,H 分辨率模式的分辨率在 1lx 下,适用于黑暗场合下(少于 10 lx)。

3.2 IIC通信读/写

上面介绍,BH1750有两种从属地址,由 ADDR 端口的电平决定。

  • ADDR=“H”( ADDR ≧ 0.7VCC ) →“1011100”
  • ADDR=“L”( ADDR ≦ 0.3VCC ) →“0100011”

关于IIC通信的详细内容,这里就不再介绍了,可以去本系列的OLED篇查看。BH1750数据手册中给出了一种配置连续高分辨率模式的方法

配置连续高分辨率模式方法步骤

BH1750数据读取格式如下

BH1750数据读取格式

光照强度(单位lx)=(High Byte + Low Byte)/ 1.2 * 测量精度

四、BH1750程序设计

4.1 IIC程序

相比于之前的OLED的IIC程序,增加了主设备发送应答信号(Ack),非应答信号(NAck),读取一个字节数据程序。修改了等待应答信号程序,增加了返回值。

/*
 *==============================================================================
 *函数名称:IIC_Delay
 *函数功能:IIC延时
 *输入参数:无
 *返回值:无
 *备  注:数据手册提供
 *==============================================================================
 */
void IIC_Delay (void)
{
	u8 t = 10;
	while (t--);
}
/*
 *==============================================================================
 *函数名称:I2C_Start
 *函数功能:IIC起始信号
 *输入参数:无
 *返回值:无
 *备  注:数据手册提供
 *==============================================================================
 */
void I2C_Start (void)
{
	BH1750_SDA_Set();
	BH1750_SCL_Set();
	IIC_Delay();
	BH1750_SDA_Clr();
	IIC_Delay();
	BH1750_SCL_Clr();
	IIC_Delay();
}
/*
 *==============================================================================
 *函数名称:I2C_Stop
 *函数功能:IIC终止信号
 *输入参数:无
 *返回值:无
 *备  注:数据手册提供
 *==============================================================================
 */
void I2C_Stop (void)
{
	BH1750_SDA_Clr();
	BH1750_SCL_Set();
	IIC_Delay();
	BH1750_SDA_Set();
}
/*
 *==============================================================================
 *函数名称:IIC_Ack
 *函数功能:CPU产生一个ACK信号
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void IIC_Ack (void)
{
	BH1750_SDA_Clr();
	IIC_Delay();
	BH1750_SCL_Set();
	IIC_Delay();
	BH1750_SCL_Clr();
	IIC_Delay();
	BH1750_SDA_Set();
}
/*
 *==============================================================================
 *函数名称:IIC_NAck
 *函数功能:CPU产生一个NACK信号
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void IIC_NAck (void)
{
	BH1750_SDA_Set();
	IIC_Delay();
	BH1750_SCL_Set();
	IIC_Delay();
	BH1750_SCL_Clr();
	IIC_Delay();	
}
/*
 *==============================================================================
 *函数名称:I2C_WaitAck
 *函数功能:IIC等待应答
 *输入参数:无
 *返回值:0:未收到应答信号;1:收到应答信号
 *备  注:无
 *==============================================================================
 */
u8 I2C_WaitAck (void)
{
	u8 re;

	BH1750_SDA_Set();
	IIC_Delay();
	BH1750_SCL_Set();
	IIC_Delay();
	if (BH1750_SDA_DATA())
	{
		re = 1;
	}
	else
	{
		re = 0;
	}
	
	BH1750_SCL_Clr();
	IIC_Delay();
	
	return re;
}
/*
 *==============================================================================
 *函数名称:Send_Byte
 *函数功能:写入一个字节
 *输入参数:dat:需要写入的数据
 *返回值:无
 *备  注:数据手册提供
 *==============================================================================
 */
void Send_Byte (u8 dat)
{
	u8 i;

	for (i = 0;i < 8;i ++)
	{
		// 发送数据时,从高位依次写入
		if (dat & 0x80)
		{
			BH1750_SDA_Set();
		}
		else
		{
			BH1750_SDA_Clr();
		}
		IIC_Delay();
		BH1750_SCL_Set();
		IIC_Delay();
		BH1750_SCL_Clr();
		
		// dat左移1位
		dat <<= 1;
	}
}
/*
 *==============================================================================
 *函数名称:IIC_Read_Byte
 *函数功能:IIC读取一个字节数据
 *输入参数:无
 *返回值:无
 *备  注:读取到的一个字节数据
 *==============================================================================
 */
u8 IIC_Read_Byte (void)
{
	u8 i;
	u8 value;
	
	// 高位在前
	value = 0;
	
	// 循环读取8bit数据
	for (i = 0; i < 8; i ++)
	{
		value <<= 1;   // 循环左移一位
		
		BH1750_SCL_Set();
		IIC_Delay();
		
		// 如果是“1”
		if (BH1750_SDA_DATA())
		{
			value ++;
		}
		
		BH1750_SCL_Clr();
		IIC_Delay();
	}
	
	return value;
}
//BH1750写一个字节
//返回值	成功:0		失败:非0 
/*
 *==============================================================================
 *函数名称:BH1750_Byte_Write
 *函数功能:BH1750写一个字节
 *输入参数:data:要写入的数据
 *返回值:0:写入成功;1/2:写入失败
 *备  注:无
 *==============================================================================
 */
u8 BH1750_Byte_Write (u8 data)
{
	I2C_Start();
	
	// 发送从设备地址,0:写
	Send_Byte (BH1750_Addr | 0);
	
	// 收到应答信号
	if(I2C_WaitAck() == 1)
	{
		return 1;
	}
	//发送控制命令
	Send_Byte(data);
	
	// 收到应答信号
	if(I2C_WaitAck() == 1)
	{
		return 2;
	}
	
	I2C_Stop();
	
	return 0;
}

4.2 BH1750初始化程序

初始化包括两部分,一部分是初始化IIC引脚,另一部分是初始化BH1750。也就是给BH1750上电,并复位。

/*
 *==============================================================================
 *函数名称:Drv_Bh1750_Init
 *函数功能:初始化BH1750
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Drv_Bh1750_Init (void)
{
	// 结构体定义
 	GPIO_InitTypeDef  GPIO_InitStructure;
	
	// 开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	// 初始化GPIO结构体
	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);
	// 全部拉高,IIC处于空闲状态
 	GPIO_SetBits(GPIOB,GPIO_Pin_6 | GPIO_Pin_7);
	
	// BH1750上电
	BH1750_Byte_Write(POWER_ON);
	
	// 复位BH1750
	BH1750_Byte_Write(MODULE_RESET);
}

4.3 读取BH1750测量结果

BH1750返回两字节的测量结果数据

/*
 *==============================================================================
 *函数名称:Drv_Bh1750_Read_Measure
 *函数功能:读取BH1750测量数据
 *输入参数:无
 *返回值:0:读取失败;其他:光照强度
 *备  注:无
 *==============================================================================
 */
u16 Drv_Bh1750_Read_Measure (void)
{
	u16 receData = 0;
	
	I2C_Start();
	
	// 发送从设备地址,1:读
	Send_Byte(BH1750_Addr | 1);
	
	if(I2C_WaitAck() == 1)
	{
		return 0;
	}
	
	// 读取高八位
	receData = IIC_Read_Byte();
	IIC_Ack();
	
	// 读取低八位
	receData = (receData << 8) + IIC_Read_Byte();
	IIC_NAck();
	I2C_Stop();
	
	return receData;   // 返回读取到的数据
}

4.4 获取光照强度

/*
 *==============================================================================
 *函数名称:Med_Bh1750_GetLightIntensity
 *函数功能:获取光照强度
 *输入参数:无
 *返回值:光照强度
 *备  注:分辨率	光照强度(单位lx)=(High Byte  + Low Byte)/ 1.2 * 测量精度
 *==============================================================================
 */
float Med_Bh1750_GetLightIntensity (void)
{
	return (float)(Drv_Bh1750_Read_Measure() / 1.1f * Resolurtion);   //返回测量光照强度
}

4.5 相关宏定义

// BH1750的地址(ADDR=“H”)
#define BH1750_Addr   0x46

// BH1750指令
#define POWER_OFF					0x00
#define POWER_ON					0x01
#define MODULE_RESET			0x07
#define	CONTINUE_H_MODE		0x10
#define CONTINUE_H_MODE2	0x11
#define CONTINUE_L_MODE		0x13
#define ONE_TIME_H_MODE		0x20
#define ONE_TIME_H_MODE2	0x21
#define ONE_TIME_L_MODE		0x23

//测量模式
#define Measure_Mode   CONTINUE_H_MODE

//分辨率	光照强度(单位lx)=(High Byte  + Low Byte)/ 1.2 * 测量精度
#if ((Measure_Mode == CONTINUE_H_MODE2)|(Measure_Mode == ONE_TIME_H_MODE2))
	#define Resolurtion		0.5
#elif ((Measure_Mode == CONTINUE_H_MODE)|(Measure_Mode == ONE_TIME_H_MODE))
	#define Resolurtion		1
#elif ((Measure_Mode == CONTINUE_L_MODE)|(Measure_Mode == ONE_TIME_L_MODE))
	#define Resolurtion		4
#endif

// SCL
#define BH1750_SCL_Clr()   GPIO_ResetBits(GPIOB,GPIO_Pin_6)
#define BH1750_SCL_Set()   GPIO_SetBits(GPIOB,GPIO_Pin_6)
// SDA
#define BH1750_SDA_Clr()   GPIO_ResetBits(GPIOB,GPIO_Pin_7)
#define BH1750_SDA_Set()   GPIO_SetBits(GPIOB,GPIO_Pin_7)

// 读取SDA电平
#define BH1750_SDA_DATA()   GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)

五、应用实例

使用串口打印光照强度,main函数如下

float gLingtIntensity = 0;

int main(void)
{
	Med_Mcu_Iint();   // 系统初始化
	
	while(1)
  {
		gLingtIntensity = Med_Bh1750_GetLightIntensity();   // 获取光照强度
		printf ("Light:%.1f lx",gLingtIntensity);   // 串口打印光照强度
		
		delay_ms(500);   //延时500ms = 0.5s
	}
}

六、拓展应用

利用BH1750获取到的周围环境光强可用于许多方面,这里举几个例子,比如设计一个教室灯光控制系统,根据实际环境光强来调节灯光亮度,使室内环境光强保持在一个稳定的值。另外,比如做颜色识别时,周围环境的光照强度不同,识别的效果也不同。可以利用BH1750实时监测周围环境光照强度变化,不同的光照强度下,切换不同的颜色阈值,可以改善颜色识别的效果。这里简单介绍一下实现思路。

6.1 实时调节LED亮度

可以用PWM来控制LED的亮度。根据周围环境的光照强度的变化,实时调节PWM的占空比,达到LED亮度根据周围环境光照强度变化而变化的效果。但是需要注意光照强度与占空比的换算关系。

6.2 实时调整颜色阈值

比如使用Open MV做颜色是别时,在不同光照强度下,同一种颜色的颜色阈值不同,可以根据不同的光照强度,匹配不同的颜色阈值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/691012.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Flutter】 Flutter 状态管理 BLoC 简明使用指南

文章目录 一、前言二、Flutter BLoC 的安装和配置三、Flutter BLoC 的基本使用四、Flutter BLoC 的简单示例五、总结 一、前言 &#x1f389;想要精通 Flutter&#xff0c;掌握更多技巧和最佳实践&#xff1f;好消息来了&#xff01;&#x1f449; Flutter专栏->Flutter De…

波动率预言机:开启新的DeFi风险管理策略和衍生市场

Chainlink 喂价一直是 DeFi 生态系统的基础构建块&#xff0c;为越来越多的加密货币、大宗商品和法定货币提供准确、防篡改和聚合的价格参考数据。高质量的价格数据的可用性在 DeFi 的增长过程中起到了重要作用&#xff0c;使其总锁定资产价值在高峰期达到了 1700 亿美元&#…

基于云计算技术B/S架构的医院信息管理系统源码(HIS)

云HIS系统源码&#xff0c;采用云端SaaS服务的方式提供 基于云计算技术的B/S架构的云HIS系统&#xff0c;采用云端SaaS服务的方式提供&#xff0c;使用用户通过浏览器即能访问&#xff0c;无需关注系统的部署、维护、升级等问题&#xff0c;系统充分考虑了模板化、配置化、智能…

MySQL基础之概述

MySQL 启动、终止 //以管理员身份运行cmd net start mysql80 net stop mysql80客户端连接 客户端cmd “开始”找到MySQL 环境变量普通cmd mysql [-h 127.0.0.1] [-P 3306] -u root -p mysql -u root -p[ ] 内的参数可省略&#xff0c;若连接本地MySQL&#xff0c;则无需指定…

机器学习笔记 - 结合深度学习的基于内容的图像实例检索 利用现成的DCNN模型进行检索

一、简述 上一篇,基于内容的图像实例检索综述。 https://mp.csdn.net/mp_blog/creation/editor/131415155https://mp.csdn.net/mp_blog/creation/editor/131415155 一种方案是,为分类任务而进行大规模训练的DCNN直接充当图像检索任务的现成特征检测器,也就是说,可以…

Live800:为什么越来越多的企业选择在线客服系统?

现今&#xff0c;越来越多的企业开始使用在线客服系统&#xff0c;这是因为互联网时代已经席卷全球&#xff0c;企业需要尽可能地利用新技术&#xff0c;优化客户体验和服务。一个强大的在线客服系统可以帮助企业实现客服信息的统一管理&#xff0c;这样可以为企业带来巨大的好…

Vue Router 相关理解 基本路由 多级路由

6.1.相关理解 6.1.1.vue-router 的理解 vue的一个插件库&#xff0c;专门用来实现SPA应用 6.1.2.对SPA应用的理解 单页Web应用&#xff08;single page web application&#xff0c;SPA&#xff09;整个应用只有一个完整的页面点击页面中的导航链接不会刷新页面&#xff0c…

Find My资讯|苹果Find My技术应用于车内丢失设备

美国专利商标局正式授予苹果两项泰坦项目新专利&#xff0c;分别是扩展其针对车内丢失设备的“Find My”设备服务&#xff0c;以及用于自动驾驶汽车的高级传感器系统&#xff0c;其中传感器系统还涵盖了带有摄像头系统的车辆&#xff0c;而摄像头系统除可3D重建场景之外&#x…

通过网络流量监测分析解决堡垒主机部署后未经授权访问的3389端口问题

1. 前言 堡垒主机是网络安全的重要组成部分&#xff0c;但在部署后仍可能存在一些主机可以绕过堡垒主机直接访问之前的3389端口。本文将介绍如何利用网络流量监测分析方法解决这个问题&#xff0c;提供一种有效的解决方案&#xff0c;加强对网络的访问控制和安全监测。 2. 网…

[NOI2016] 网格

题目描述 跳蚤国王和蛐蛐国王在玩一个游戏。 他们在一个 &#xfffd;n 行 &#xfffd;m 列的网格上排兵布阵。其中的 &#xfffd;c 个格子中 (0≤&#xfffd;≤&#xfffd;⋅&#xfffd;)(0≤c≤n⋅m)&#xff0c;每个格子有一只蛐蛐&#xff0c;其余的格子中&#xff…

小红书美妆品牌投放流程有哪些,品牌规划

越来越多的品牌开始重视新媒体&#xff0c;很多品牌和商家纷纷将目光瞄准了小红书&#xff0c;但是由于各平台都有自己的规则&#xff0c;盲目踏入不熟悉的领域肯定是有点冒险的。那么小红书美妆品牌投放流程有哪些&#xff0c;以及品牌规划。 小红书品牌投放指南是指小红书平台…

享元模式(Flyweight)

别名 缓存&#xff08;Cache&#xff09;。 定义 享元是一种结构型设计模式&#xff0c;它摒弃了在每个对象中保存所有数据的方式 &#xff0c;通过共享多个对象所共有的相同状态&#xff0c;让你能在有限的内存容量中载入更多对象。 前言 1. 问题 假如你希望在长时间工作…

互联网+洗鞋店软件多门店多网点预约下单小程序

互联网洗鞋店软件小程序功能介绍: 1.用户端&#xff08;上门取件、送货到店、寄存网点&#xff09; 2.取货员端&#xff08;取件员拍照&#xff0c;清洗过程&#xff0c;包装拍照&#xff09; 3.多门店管理&#xff08;用户进入小程序&#xff0c;根据定位自动匹配就近门店&…

Golang每日一练(leetDay0106) 超级丑数、右侧小于当前元素的个数

目录 313. 超级丑数 Super Ugly Number &#x1f31f;&#x1f31f; 315. 计算右侧小于当前元素的个数 Count-of-smaller-numbers-after-self &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练…

easypoi 导出word并插入echart图片和文件

一 pom 文件引入&#xff1a;<!-- 目前的版本对应 poi 4.1.2 和 xmlbeans 3.1.0 , poi 3.17 和 xmlbeans 2.6.0 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version&…

新人必看的Java基础知识点大梳理

一个Java程序可以认为是一系列对象的集合&#xff0c;而这些对象通过调用彼此的方法来协同工作。下面简要介绍下类、对象、方法和实例变量的概念。 对象&#xff1a;对象是类的一个实例&#xff0c;有状态和行为。例如&#xff0c;一条狗是一个对象&#xff0c;它的状态有&…

树莓派Pico|SHELL中microPython命令行|pico sdk开发环境搭建|点灯代码|必备开发工具|gcc涉及的include文件目录

文章目录 SHELL中microPython命令行SHELL中基于microPython的控制代码Hello Pico 代码SHELL中简单点灯代码SHELL中循环亮灯代码 基于pico sdk开发环境搭建及点灯代码必备开发工具Mingw-w64&#xff1a;著名C/C编译器GCCarm-none-eabi&#xff1a;交叉编译工具Git&#xff1a;开…

js翻转数组

arr [red, green, "blue", "pink", "purple"];var arr1 [];for (var i 1; i < arr.length; i) {console.log(arr1.length)arr1[arr1.length] arr[arr.length - i];console.log(arr1.length)}console.log(arr1);

echarts饼装图自定义图例和扇形区的文字

最近因为工作需要&#xff0c;需要开发一个大屏&#xff0c;后台给的数据是这个的&#xff0c;echarts是默认将数据data例的name属性作为图例和扇形图上展示文本&#xff0c;这里我需要自定义图例信息和内容&#xff0c;通过这篇文章&#xff0c;记录下如何修改这些内容&#x…

spring IOC详解

一、IOC IoC就是Inversion of Control&#xff0c;控制反转。在Java开发中&#xff0c;IoC意味着将你设计好的类交给系统去控制&#xff0c;而不是在你的类内部控制。这称为控制反转。 下面我们以几个例子来说明什么是IoC。假设我们要设计一个Girl和一个Boy类&#xff0c;其中G…