BH1750光照传感器超详细攻略(从原理到代码讲解,看完你就懂了)
时间:2022-11-10 06:00:00
目录
-
- 一、前言
- 二、芯片介绍
- 三、IIC通讯介绍
-
- IIC通信过程简介
- IIC通讯实例
- BH1750的通讯过程
- 四、BH1750的命令
- 五、BH1750编程教学
- 六、测试
- 七、总结
一、前言
写这篇文章有两个原因。
首先,一位弟弟告诉我,我发表的文章更倾向于工作人员。我想知道我是否能写一些大学生能用的东西。事实上,我写的大部分文章都是我在工作中总结的经验,这对初学者来说有点难以理解。
第二,我认为很多大学生都可以使用这个光传感器,但虽然有很多在线教程,但它可能无法帮助你深入了解这个传感器。我们可以在阅读策略后驱动更多,但事实上,我们不了解它的工作原理。我们无法在光传感器的基础上添加其他功能。
因此,我认为我仍然需要写一个更详细、更深入的策略来帮助你理解。我认为驱动芯片和驱动芯片是不同的。如果你学会了如何驱动一个芯片,你可以从其他类似的芯片中得出推论。否则,每次你换一个芯片,你只能找到别人写的代码。
好了,废话不多说,BH1750的解释立即开始。(注:请从头到尾看,粗略看一下,因为内容是环环相扣的,一直看,一直爽!
再多说一句,就一句,真的,我接下来讲的所有代码和相关文件都可以免费发给你,链接在文章底部,自己下载。
除此驱动外,还有另一种使用方法,请参考我发表的博文:
基于stm32驱动bh1750光照传感器的超简单编程方法
二、芯片介绍
BH1750FVI是数字光强度传感器集成芯片。很多宝藏都写在上面GY30模块实际上是用的BH1750FVI芯片,只是它把BH1750FVI芯片和周围的一些电路做在板上,然后把它们放在板上BH1750FVI引出通信引脚,方便您用单片机控制。(也就是说,大多数国产芯片都是这样的套路。拿起别人的芯片,加一点外围电路,然后再包一层外壳,换个型号,成为自己的产品。
电路工作原理:如图1所示,BH光敏二极管内部1750,操作放大器,ADC由采集、晶振等组成。PD二极管通过光生伏特效将输入光信号转换为电信号,通过操作放大电路放大ADC收集电压,然后通过逻辑电路将其转换为16位二进制数并存储在内部寄存器中(注:进入光窗的光越强,光电流越大,电压越大。因此,光的大小可以通过电压的大小来判断,但需要注意的是,虽然电压与光强一一对应,但不成正比,因此,芯片内部进行了线性处理,这就是为什么不直接使用光敏二极管集成IC的原因)。BH时钟线和数据线钟线和数据线,单片机通过I2C协议可以与BH可选择1750模块通信BH1750的工作模式也可以BH提取1750寄存器的光照数据。
引脚定义:
引脚号 | 名称 | 说明 |
---|---|---|
1 | VCC | 电压源正极 |
2 | SCL | IIC时钟线,时钟输入引脚MCU输出时钟 |
3 | SDA | IIC双向数据线IO口,用来传输数据 |
4 | ADDR | IIC地址线,接GND01000100011 ,接VCC101111000年设备地址 |
5 | GND | 负极供电电压源 |
三、IIC通讯介绍
IIC通信过程简介
既然BH1750是用IIC通们必须首先了解通信IIC通信原理。IIC由时钟线(SCL)和数据线(SDA)组成。时钟线,听这个名字就知道和时间有关。是的,它实际上管理它IIC通讯时间。顾名思义,数据线是用来传输数据的线。那时钟线和数据线有什么关系呢?你可以把时钟线理解为红绿灯,高电平是绿灯,低电平是红灯,数据线传输的每一个数据都相当于一辆车,高电平是奔驰,低电平是宝马。当绿灯亮起时,汽车可以通过,但这里的交通规则是每次绿灯亮起,只能通过一辆车。所以,IIC通信过程是红绿灯交替闪烁(即时钟线输出方波脉冲),汽车跟随过去,过去是奔驰,是传输1,过去的宝马,是传输0,连续传输8次,可以形成8个二进制数,即字节数据,重复这个过程可以实现两个设备之间的通信。
好吧,上面已经大致解释过了IIC下面补充一些细节。IIC两种通信设备有主从关系,比如我们的单片机在这里就是主设备,BH1750是从设备。
时钟线由主设备输出,从设备输入,即单片机和BH1750通信时,单片机IO口要给SCL引脚输出一个方波脉冲,因为IIC设备支持的最大通信频率一般为400kHz,也就是说,一个时钟周期(一个高电平加一个低电平为一个周期)不应小于2.5us。单片机输出时钟时,必须注意高低电平的延迟时间。延迟时间越长,通信速度越慢。此外,时钟线不会总是输出脉冲,只会在需要通信时输出,并遵循一定的规则。当需要通信时,时钟线首先输出一个启动信号,告诉我从设备开始通信。事实上,电平从高到低跳转,但高电平的持续时间不能太短。至少要看芯片手册。无论如何,延长一点是正确的。然后根据固定时间输出高低脉冲,直到停止通信,时钟线输出结束信号告诉设备我不通信,实际上电平一直在上升。
数据线传输的数据是双向的,单片机可以提供BH也可以读取1750发数据BH1750的数据(也就是BH单片机发送1750)。需要注意的是,单片机机BH1750发送的数据不是随便发送的,而是符合一定的规则。首先,单片机应先发送一个设备地址(设备地址为7位,详情请稍后讨论),然后发送一个读写位(0表示写入,1表示读取)。设备地址和读写位加起来只是一个字节,然后BH1750会给你一个回应位置,意思是我收到了。然后单片机可以发送数据,每次间隔发送1个字节。收藏也差不多,只是把单片机发送的数据改成收藏数据,这里就不多说了,以后再详细说。(注:设备地址用于区分设备,因为有时同一时钟线和数据线可能连接多个设备,即主设备发送的所有数据都可以从设备收到,所以主设备发送设备地址,告诉所有设备我给哪个设备,其他设备不执行)。
IIC通讯实例
让我们看一个实际的例子。图2是OPT3001通讯的读写过程,(OPT3001是我在项目中用到一款低功耗光照传感器,和BH1750类似,也是IIC通讯协议,感兴趣的同学可以看看我之前发的博文,解释一下。IC驱动模式),看完这张图就明白了IIC你可以在博主面前大声说:你写的博文有毛用,我知道你说的一切。如果你还有不明白的地方,坐下来听我解释。
首先,让我们看看IIC在写入过程最左边有一个Start by Master也就是说,单片机先给出起始信号,然后传输8位数据(1 0 0 0 1 A1 A0 R/W)。其中,“1 0 0 0 1 A1 A0是设备地址,因为这里有四个设备地址可供选择,所以使用A1和A(注:BH1750只有两个装置地址)R/W是读写位我上面说过,这是写入,所以这里R/W应该是0。 接着是“ACK by OPT3001,这是从设备到主设备的回应,也就是说我收到了你发送的数据,你可以继续发送,然后接下来RA7-RA0是寄存器地址(因为寄存器不止一个,所以先发地址,告诉它你下一步要把数据存储在哪里),再后面的D15-D0是两个字节的数据(这些数据存储在前面发送的地址的寄存器中)。
读取过程类似于写入,先是起始信号 读写位,然后回应,然后开始接收数据(单片机IO从输出到输入,D15-D0接收到两个字节的数据,ACK by Master单片机给OPT3001发的应答。(只要接收方发出回应,如果不回应,通讯就会结束,比如读第二个字节后面的No ACK by Master”)
好吧,如果你能坚持看到这里,那我就把你当成一个男人!!如果你明白了,恭喜你。如果你不明白,没关系。IIC一般的通信方式,后面的通信方式,BH1750的通信应该更简单。
(问:那你为什么不直接讲BH1750。答:我喜欢,你咬我呀,略略略….啪,略略啪,略别别….我错了。)
BH1750的通讯过程
其实前面之所以要先讲这个OPT3001而不是直接讲BH1750,是因为BH1750的IIC其实算是一个简化版的,不具有通用性,你学会了OPT3001的通讯方法,你再去驱动BH1750就很简单,相反,如果你只会驱动BH1750,那么换成别的IIC的芯片你就不一定会了。
好了,接下来我们来看一下BH1750的通讯,BH1750的通讯过程可以分成5步,中间3步如图3所示。
(啪啪,问:为什么要用英文的图,别以为我不知道有中文版的手册,说你是不是在装*。答:冤枉,真不是,那个中文版的图太糊了,而且英文版其实也不影响大家去看,老实说我是一个英语学渣,我还写了一篇博文讲述一个学渣如何看懂英文数据手册,有兴趣的同学可以看一下。真不是打广告哦。)
第1步:发送上电命令。(上电命令是0x01)。
因为这里没有图,我就不详细说了,发送的过程和第2步基本一致。就是把测量命令(0x10)改成上电命令(0x01)。
第2步:发送测量命令。
下面图片上的例子,ADDR引脚是接GND的,发送的测量命令是“连续高分辨率测量(0x10)”。
发送数据的过程和之前讲的OPT3001写入的过程基本一样,先是“起始信号(ST)”,接着是“器件地址+读写位”(器件地址我在上面引脚定义那里有写),然后是应答位,紧接着就是测量的命令“00010000”(关于测量命令,下面会详细说明),然后应答,最后是“结束信号(SP)”。(相比于OPT3001的写入过程,BH1750少了一个发送寄存器地址的步骤,因为它只有一个寄存器,所以就没必要了)
第3步:等待测量结束。
测量的时间手册上面有写,我这里就不列出来了,高分辨率连续测量需要等待的时间最长,手册上面写的是平均120ms,最大值180ms,所以为了保证每次读取到的数据都是最新测量的,程序上面可以延时200ms以上,当然也不用太长,浪费时间。如果你用别的测量模式,等待时间都比这个模式要短。
第4步:读取数据。
先是“起始信号(ST)”,接着是“器件地址+读写位”,然后是应答位,紧接着接收1个字节的数据(单片机在这个时候要把SDA引脚从输出改成输入了),然后给BH1750发送应答,继续接收1个字节数据,然后不应答(因为我们接收的数据只有2个字节,收完就可以结束通讯了),最后是“结束信号(SP)”。
第5步:计算结果。
接收完两个字节还不算完成,因为这个数据还不是测量出来的光照强度值,我们还需要进行计算,计算公式是:光照强度 =(寄存器值[15:0] * 分辨率) / 1.2 (单位:勒克斯lx)
因为我们从BH1750寄存器读出来的是2个字节的数据,先接收的是高8位[15:8],后接收的是低8位[7:0],所以我们需要先把这2个字节合成一个数,然后乘上分辨率,再除以1.2即可得到光照值。
例如:我们读出来的第1个字节是0x12(0001 0010),第2个字节是0x53(0101 0011),那么合并之后就是0x1253(0001 0010 0101 0011),换算成十进制也就是4691,乘上分辨率(我用的分辨率是1),再除以1.2,最后等于3909.17 lx。
四、BH1750的命令
BH1750所有的命令都在图4。这次我用的是中文版的图,方便大家看,有点糊勿怪。 这里的指令虽然多,但是实际上如果仅仅是测光照值,只用两条就够了,通电指令和测量指令。这里的几条测量指令我就不详细说了,手册上是有讲的,如果后面你们需要的话我再补上吧。寄存器也只有一个,没什么好说的。(才不是因为懒也不是因为天天都要加班)
五、BH1750编程教学
下面的编程我以stm32为例,其实换成51,stm8或者别的单片机,程序也基本一样的,不同的单片机在程序上只是引脚配置的写法不太一样,别的基本没差别。
我的这个程序是用OLED显示光照强度的,想用串口,蓝牙或者别的方式也可以。
注:我下面展示的程序跟我发给你们的工程会有一点不一样,主要是备注,因为为了让你们更好理解,我展示的代码是加了很多备注的,而工程是以前的,备注会少一点。
1、IIC驱动代码
//IIC的驱动程序没必要自己去写,能够看懂每一个函数的作用,知道IIC的通讯过程即可,我这里用的是正点原子的例程 //IIC通讯最基本的几个函数是:起始信号,结束信号,发送应答(或不应答),发送1个字节数据,接收1个字节数据 //这些我前面都有讲到,如果你前面看懂了,将上面OPT3001的时序图和这个程序结合起来看你就很容易想明白 //闲话(可以跳过):这一份程序是以前大学做项目的时候写的,其实大部分都是抄的,当时对程序的理解也是一知半解 //现在回头看,发现这个程序的兼容性很差 //虽然在这个工程上面运行是没有问题的,但是如果移植到别的工程或者用别的单片机,需要改动的地方就很多了 //比如引脚的拉高拉低,这里是直接写“SDA=1;”,但是这个SDA的定义是在正点原子自己写的一个库里面的 //如果你用别的工程,没有把这个库加进来,那么这个定义就不成立了 //最好的写法我觉得是分成两个定义SDA_High和SDA_Low //然后在头文件声明#define SDA_High GPIO_SetBits(GPIOB,GPIO_Pin_0) //#define SDA_GPIO_ResetBits(GPIOB,GPIO_Pin_0) //这样写的好处是如果要移植,只需要把 GPIO_SetBits(GPIOB,GPIO_Pin_0) 这部分换掉就行了 //比如用51,我们就可以把GPIO_SetBits(GPIOB,GPIO_Pin_0)换成P1_0=1 //同样的IIC通讯的延时函数delay_us,这里用的是定时器,也是要用到正点原子的库delay.c //其实这里我觉得可以用for函数延时,因为延时的时间比较短,也不需要很精确 //如果换了一个单片机,晶振频率不同,只需要改一下for函数延时的次数 //然后用
示波器量一下这个时间,确保是在正常通讯的时间范围内即可 /***起始信号***/ void BH1750_Start() { SDA=1; //拉高数据线 SCL=1; //拉高时钟线 delay_us(5); //延时 GPIO_ResetBits(bh1750_PORT, sda); //产生下降沿 delay_us(5); //延时 GPIO_ResetBits(bh1750_PORT, scl); //拉低时钟线 } /*****停止信号******/ void BH1750_Stop() { SDA=0; //拉低数据线 SCL=1; //拉高时钟线 delay_us(5); //延时 GPIO_SetBits(bh1750_PORT, sda); //产生上升沿 delay_us(5); //延时 } /************************************** 发送应答信号 入口参数:ack (0:ACK 1:NAK) **************************************/ void BH1750_SendACK(int ack) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = sda; GPIO_Init(bh1750_PORT, &GPIO_InitStruct); if(ack == 1) //写应答信号 SDA=1; else if(ack == 0) SDA=0; else return; SCL=1; //拉高时钟线 delay_us(5); //延时 SCL=0; //拉低时钟线 delay_us(5); //延时 } /************************************** 接收应答信号 **************************************/ int BH1750_RecvACK() { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU; /*这里一定要设成输入上拉,否则不能读出数据*/ GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin=sda; GPIO_Init(bh1750_PORT,&GPIO_InitStruct); SCL=1; //拉高时钟线 delay_us(5); //延时 if(GPIO_ReadInputDataBit(GPIOA,sda)==1)//读应答信号 mcy = 1 ; else mcy = 0 ; SCL=0; //拉低时钟线 delay_us(5); //延时 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_Init(bh1750_PORT,&GPIO_InitStruct); return mcy; } /************************************** 向IIC总线发送一个字节数据 **************************************/ void BH1750_SendByte(uchar dat)//dat是要发送的一个字节的数据 { uchar i; for (i=0; i<8; i++) //8位计数器 { if( 0X80 & dat ) //如果要发送的是1 GPIO_SetBits(bh1750_PORT,sda); else //如果要发送的是0 GPIO_ResetBits(bh1750_PORT,sda); dat <<= 1; //for循环每执行一次,要发送的数据左移1位,循环8次就把一个字节的数据发送出去了 SCL=1; //拉高时钟线 delay_us(5); //延时 SCL=0; //拉低时钟线 delay_us(5); //延时 } BH1750_RecvACK(); } /************************************** 在IIC总线接收一个字节数据 **************************************/ uchar BH1750_RecvByte() { uchar i; uchar dat = 0; //dat是存放接收到的一个字节的数据 uchar bit; GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; /*这里一定要设成输入上拉,否则不能读出数据*/ GPIO_InitStruct.GPIO_Pin = sda; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(bh1750_PORT,&GPIO_InitStruct ); GPIO_SetBits(bh1750_PORT,sda); //使能内部上拉,准备读取数据, for (i=0; i<8; i++) //8位计数器 { dat <<= 1; //循环8次,每次接收一个位,8次之后完成一个字节数据的接收 SCL=1; //拉高时钟线 delay_us(5); //延时 if( SET == GPIO_ReadInputDataBit(bh1750_PORT,sda))//读取SDA引脚的电平,如果是高电平,就是传输“1” bit = 0X01; else //电平传输的是“0” bit = 0x00; dat |= bit; //读数据 SCL=0; //拉低时钟线 delay_us(5); //延时 } GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(bh1750_PORT, &GPIO_InitStruct ); return dat; }
2、BH1750写入和读取的函数
//上面讲了IIC的几个基本的函数,包括了发送1字节和接收1字节
//但是和BH1750通讯,不仅仅是发送1个字节或者接收1个字节那么简单
//我们对BH1750发送命令的时候,是要先发送器件地址+写入位,然后发送指令
//读取数据的时候,需要先发送器件地址+读取位,然后连续读取2个字节
//如果我上面说的你都懂了,那么你就可以去看代码了,如果能跟时序图一一对应上,你就理解代码了
//另外,如果你用的不是BH1750,而是别的IIC通讯的芯片,这两个函数的写法可能也是不同的
//比如OPT3001,发送命令的时候不仅发发送命令数据还需要发送寄存器地址,所以一般函数定义的时候就要定义两个变量
//又或者一些命令是两个字节的,那么你定义的变量类型就需要注意了,函数里面也需要多发送一个字节数据
//这里不理解也无所谓,不影响学习BH1750的驱动,以后你做项目用到了别的芯片你可能就突然理解了
//写入指令
void Single_Write_BH1750(uchar REG_Address)//REG_Address是要写入的指令
{
BH1750_Start(); //起始信号
BH1750_SendByte(SlaveAddress); //发送设备地址+写信号
BH1750_SendByte(REG_Address); //写入指令
BH1750_Stop(); //发送停止信号
}
//读取指令
void mread(void)
{
uchar i;
BH1750_Start(); //起始信号
BH1750_SendByte(SlaveAddress+1); //发送设备地址+读信号
//注意:这里的for函数的i<2和下面的if函数的i==2,我发现以前的工程写的居然是3
//这里其实我们只需要读取2个字节就行了,后面的合成数据也是只用了BUF的前2个字节
//工程文件我没改,这个驱动程序以前也用在了多个项目上,读取3个字节肯定是也可以正常运行的
//但是我觉得还是改成2比较好,你们可以测试一下改成2有没有问题,测试之后一定要告诉我结果,谢谢!!
for (i=0; i<2; i++) //连续读取2个数据,存储到BUF里面
{
BUF[i] = BH1750_RecvByte(); //BUF[0]存储高8位,BUF[1]存储低8位
if (i == 1)
{
BH1750_SendACK(1); //最后一个数据需要回NOACK
}
else
{
BH1750_SendACK(0); //回应ACK
}
}
BH1750_Stop(); //停止信号
delay_ms(5);
}
3、BH1750初始化函数
//初始化BH1750,根据需要请参考pdf进行修改****
void Init_BH1750()
{
GPIO_InitTypeDef GPIO_InitStruct;
/*开启GPIOB的外设时钟*/
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = sda | scl ;
GPIO_Init(bh1750_PORT,&GPIO_InitStruct);
Single_Write_BH1750(0x01);
delay_ms(180); //延时180ms
}
4、获取光照度函数
float read_BH1750(void)
{
int dis_data; //变量
float temp1;
float temp2;
Single_Write_BH1750(0x01); //发送上电命令(0x01)
Single_Write_BH1750(0x10); //发送高分辨率连续测量命令(0x10)
delay_ms(200); //等待测量结束,其实延时180ms就行了,延时200ms只是预留多一点时间,保证通讯万无一失
mread(); //连续读出数据,存储在BUF中
dis_data=BUF[0];
dis_data=(dis_data<<8)+BUF[1]; //2个字节合成数据
temp1=dis_data/1.2;//计算光照度
temp2=10*dis_data/1.2;//把光照度放大10倍,目的是把小数点后一位数据也提取出来
temp2=(int)temp2%10;//求余得到小数点后一位
OLED_ShowString(87,2,".",12); //OLED显示小数点
OLED_ShowNum(94,2,temp2,1,12);//OLED显示小数
return temp1;//返回整数部分
}
//这里写的程序还是有点乱的,小数部分直接在read_BH1750()显示,整数部分返回,在main()函数调用的时候显示
//这...其实最好是要么都在这个函数显示,要么把temp1和temp2改成全局变量,然后都在main函数显示
//这个变量的名字也是[捂脸],算了算了,往事不堪回首。要吐槽的地方有点多,也没时间去一一改了
//不过其实也不影响你们学IIC通讯的编程方式,就这样吧
5、main函数
int main(void)
{
float light;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
delay_init(); //延时函数初始化
uart_init(9600); //串口初始化为9600
LED_Init(); //初始化与LED连接的硬件接口
Init_BH1750(); //初始化BH1750
OLED_Init(); //初始化OLED
OLED_Clear(); //清屏
while(1)
{
light=read_BH1750(); //读取BH1750的光强数据
OLED_ShowString(0,2,"light:",12); //显示光照强度
OLED_ShowNum(48,2,light,6,12); //显示光照度
OLED_ShowString(110,2,"lx",12); //显示“lx”
if(light<100)//光照度小于100lx,点亮LED灯
{
LED1=0;
OLED_ShowString(38,5,"LED-ON ",12);
}
else
{
LED1=1;
OLED_ShowString(38,5,"LED-OFF",12);
}
}
}
六、测试
我这个程序是大学的时候做的一个课程设计,现在也没有实物可以测试了,我就发我以前报告里的图给你们看一下效果吧。图5是亮度大于100lx的时候,图6是低于100lx的时候。
七、总结
要驱动BH1750,或者其他IIC通讯的芯片,最好还是先了解IIC通讯的时序,了解通讯的原理,然后才是写驱动程序。驱动程序也可以分成三部分,第一部分是IIC通讯基本的协议(一般抄就完事了),第二部分是芯片的读写过程,需要根据实际芯片的通讯方式写。第三部分是指令控制相关的函数,BH175比较简单,只有测量和计算。有些可能还有多个设置不同的模式的函数,校验数据的函数等等,不过它们其实都是发送指令,只是发不同的指令执行不同的操作而已。
OPT3001的驱动教程你们可以大概看一下:https://blog.csdn.net/ShenZhen_zixian/article/details/102876443
最后再说点闲话吧,写到这里刚好有点感触,其实写博文的初衷只是为了把工作中总结出来的一些经验记录下来,加强记忆。因为像我们这种做硬件研发的,经验是最值钱的,然后上传资源也只是为了赚点积分,因为还在大学那会想下载别人的程序的时候总是恨自己没有积分。后来发现我写的博文和上传的资源能够帮助到一些人,所以我就一直坚持着更新,哪怕每天加班也会抽空写一下文章写一下代码,即使我自己赚的积分其实一次都没用过。可能这就是传承吧,以前遇到问题的时候总能在前辈的博文中找到答案,现在轮到自己分享自己的经验给后来者了,希望我的文章也能够帮助到你。
本文用到的工程源码可以在下面的链接下载:
源码下载链接1:https://pan.baidu.com/s/1HnedCg3sC4HU8iEOf4dYOw ,提取码:xs8o
源码下载链接2:https://pan.baidu.com/s/1QOC01P5M99LzP4i1Voro6g,提取码:abcd
除了本文这个驱动外,还有另外一种使用方法,可以参考我的博文:
基于stm32驱动bh1750光照传感器的一种超简单的编程方法
创作不易,希望你们尊重别人的劳动,点赞+关注支持一下吧,谢谢大家了,博主也会继续更新更多的大学生专栏,如果你们还有什么问题,可以评论留言或者私信给我。