使用BH1750(GY-302)光照传感器的方法
BH1750(GY-302)的使用,(光照传感器)
提示:文章写完后,目录可以 自动生成,如何生成可参考右边的帮助文档
前言
直接在网上购买BH1750 传感器模块
本课题使用STM32F103-mini
提示:以下是本篇文章正文内容,下面案例可供参考
一、BH1750是什么?
BH1750FVI是一款数字型光强度传感器集成芯片。某宝上面很多写着GY30模块,那些其实也是用BH1750FVI芯片,只不过是它把BH1750FVI芯片以及外围的一些电路做到了一个板子上面,然后把BH1750FVI的通讯引脚引出来方便你们用单片机控制而已。(话说大部分国产芯片都是这个套路,把人家的芯片拿过来,加一点外围电路,然后重新包一层外壳,换个型号,就变成自己的产品了)
电路工作原理:如图1所示,BH1750的内部由光敏二极管、运算放大器、ADC采集、晶振等组成。PD二极管通过光生伏特效应将输入光信号转换成电信号,经运算放大电路放大后,由ADC采集电压,然后通过逻辑电路转换成16位二进制数存储在内部的寄存器中(注:进入光窗的光越强,光电流越大,电压就越大,所以通过电压的大小就可以判断光照大小,但是要注意的是电压和光强虽然是一一对应的,但不是成正比的,所以这个芯片内部是做了线性处理的,这也是为什么不直接用光敏二极管而用集成IC的原因)。BH1750引出了时钟线和数据线,单片机通过I2C协议可以与BH1750模块通讯,可以选择BH1750的工作方式,也可以将BH1750寄存器的光照度数据提取出来。
**
引脚定义
**:
名称 | 说明 |
---|---|
VCC | 供电电压源正极 |
SCL | IIC时钟线,时钟输入引脚,由MCU输出时钟 |
SDA | IIC数据线,双向IO口,用来传输数据 |
ADDR | IIC地址线,接GND时器件地址为0100011 ,接VCC时器件地址为1011100 |
GND | 供电电压源负极 |
简单介绍一下IIC
IIC由时钟线(SCL)和数据线(SDA)组成。时钟线,听这个名字就知道和时间有关系,没错,它其实管理着IIC的通讯时间。而数据线,顾名思义就是用来传输数据的线。那么时钟线和数据线它们是什么关系呢?你可以把时钟线理解为红绿灯,高电平是绿灯,低电平是红灯,而数据线传输的每一个数据则相当于一辆汽车,高电平是奔驰,低电平是宝马。当绿灯亮了的时候,汽车就可以过去,只不过这里的交通规则是每亮一次绿灯,只能通过一辆汽车。所以,IIC通讯的过程就是红绿灯交替闪烁(也就是时钟线输出方波脉冲),汽车跟着一辆一辆的过去,过去的是奔驰,就是传输了一个“1”,过去的宝马,就是传输了一个“0”,连续传输8次,就可以组成一个8位的二进制数,也就是一个字节的数据,反复这个过程就能实现两个设备之间的通讯。
二、使用步骤
1.编写BH1750的头文件
代码如下(示例):
#ifndef BH1750_H
#define BH1750_H
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
//IIC总线地址接口定义
#define IIC_SCL PBout(3)
#define IIC_SDA_OUT PAout(15)
#define IIC_SDA_IN PAin(15)
#define IIC_INPUT_MODE_SET() {GPIOA->CRH&=0x0FFFFFFF;GPIOA->CRH|=0x80000000;}
#define IIC_OUTPUT_MODE_SET() {GPIOA->CRH&=0x0FFFFFFF;GPIOA->CRH|=0x30000000;}
#define IIC_WRITE 0 // 写
#define IIC_READ 1 // 读
#define SlaveAddress 0x46 //BH1750地址
extern u8 BUF[3];
//函数声明
void BH1750_IIC_Init(void);
void BH1750_Start();
void BH1750_Stop();
void BH1750_SendACK(char ack);
char BH1750_RecvACK();
void BH1750_SendByte(u8 data);
void Single_Write_BH1750(u8 REG_Address);
void Multiple_Read_BH1750();
float Get_Sunlight_Value();
u8 BH1750_RecvByte();
#endif
2.编写BH1750的主程序
代码如下(示例):
#include "BH1750.h"
#include "delay.h"
#include "usart.h"
/*
函数功能: IIC总线初始化
硬件连接:
SCL-PB3
SDA-PA15
*/
u8 BUF[3];
void BH1750_IIC_Init(void)
{
/*1. 开时钟*/
RCC->APB2ENR|=1<<2; //PA
RCC->APB2ENR|=1<<3; //PB
RCC->APB2ENR|=1<<0; //开启AFIO时钟
/*2. 配置模式*/
AFIO->MAPR |= 0x2<<24;//关闭JTAG-DP,启用SW-DP
GPIOA->CRH&=0x0FFFFFFF;
GPIOA->CRH|=0x30000000;
GPIOB->CRL&=0xFFFF0FFF;
GPIOB->CRL|=0x00003000;
/*3. 上拉*/
GPIOA->ODR|=0x1<<15;
GPIOB->ODR|=0x1<<3;
//printf("BH1750 IIC_Init OK! \n");
}
/**************************************
起始信号
**************************************/
void BH1750_Start()
{
IIC_OUTPUT_MODE_SET(); //配置输出模式
IIC_SDA_OUT = 1; //拉高数据线
IIC_SCL = 1; //拉高时钟线
delay_us(5); //延时
IIC_SDA_OUT = 0; //产生下降沿
delay_us(5); //延时
IIC_SCL = 0; //拉低时钟线
}
/*
函数功能: 停止信号
*/
void BH1750_Stop()
{
IIC_OUTPUT_MODE_SET(); //配置输出模式
IIC_SDA_OUT = 0; //拉低数据线
IIC_SCL = 1; //拉高时钟线
delay_us(5); //延时
IIC_SDA_OUT = 1; //产生上升沿
delay_us(5); //延时
}
/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void BH1750_SendACK(char ack)
{
IIC_OUTPUT_MODE_SET(); //配置输出模式
IIC_SCL = 0; //拉低时钟线
if(ack) IIC_SDA_OUT = 1;
else IIC_SDA_OUT = 0; //写应答信号
delay_us(2); //延时
IIC_SCL = 1; //拉高时钟线
delay_us(5); //延时
IIC_SCL = 0; //拉低时钟线
}
/**************************************
接收应答信号
**************************************/
char BH1750_RecvACK()
{
u8 cnt=0;
IIC_INPUT_MODE_SET();//输入模式
IIC_SDA_OUT=1;
delay_us(1);
IIC_SCL=1;
delay_us(1);
while(IIC_SDA_IN)//等待应答
{
cnt++;
delay_us(1);
if(cnt>=250)//等待时间过长,产生停止信号,返回1,表示接收应答失败
{
BH1750_Stop();
//printf("N0 ACK\n");
return 1;
}
}
IIC_SCL=0;//应答成功,则SCL变低
return 0;
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
void BH1750_SendByte(u8 data)
{
u8 i;
IIC_OUTPUT_MODE_SET();
IIC_SCL = 0;//拉低时钟线, 数据准备发送
delay_us(2);//延时
for (i=0;i<8;i++)//从高位开始一位一位地传送
{
if(data&0x80) IIC_SDA_OUT=1;//送数据口
else IIC_SDA_OUT=0;
data <<= 1;//移出数据的最高位
IIC_SCL = 1; //拉高时钟线,发送数据
delay_us(2);//延时
IIC_SCL = 0;//拉低时钟线,数据发送完毕
delay_us(2);//延时
}
}
/**************************************
从IIC总线接收一个字节数据
**************************************/
u8 BH1750_RecvByte()
{
u8 i;
u8 data = 0;
IIC_INPUT_MODE_SET();//使能内部上拉,准备读取数据,
for (i=0;i<8;i++)//8位计数器
{
IIC_SCL=0;//置时钟线为低,准备接收数据位
delay_us(2);//时钟低电平周期大于4.7μs
IIC_SCL=1;//置时钟线为高使数据线上数据有效,主机开始读数据,从机不能再改变数据了,即改变SDA的电平
data <<= 1;
IIC_SCL = 1;//拉高时钟线
if(IIC_SDA_IN) data|=0x01;//读数据
delay_us(1);//延时
}
IIC_SCL=0;
return data;
}
void Single_Write_BH1750(u8 REG_Address)
{
BH1750_Start();//起始信号
BH1750_SendByte(SlaveAddress);//发送设备地址+写信号
BH1750_RecvACK();
BH1750_SendByte(REG_Address);//内部寄存器地址,请参考中文pdf22页
BH1750_RecvACK();
BH1750_Stop();//发送停止信号
}
/*********************************************************
连续读出BH1750内部数据
*********************************************************/
void Multiple_Read_BH1750()
{
BH1750_Start();//起始信号
BH1750_SendByte(SlaveAddress+1);//发送设备地址+读信号
BH1750_RecvACK();
BUF[0] = BH1750_RecvByte();//BUF[0]存储0x32地址中的数据
BH1750_SendACK(0);
BUF[1] = BH1750_RecvByte();//BUF[0]存储0x32地址中的数据
BH1750_SendACK(1);
BH1750_Stop();//停止信号
delay_ms(5);
}
/*********************************************************
读出数据并合成实际光强值
*********************************************************/
float Get_Sunlight_Value()
{
int dis_data=0;
float temp;
u8 i=0;
Single_Write_BH1750(0x01);// power on
Single_Write_BH1750(0x10);// H- resolution mode
delay_ms(180);//延时180ms
Multiple_Read_BH1750();//连续读出数据,存储在BUF中
for(i=0;i<3;i++)
//printf("0X%X ",BUF[i]);
dis_data=BUF[0];
dis_data=(dis_data<<8)+BUF[1];//合成数据
temp=(float)dis_data/1.2;
UsartPrintf(USART_DEBUG,"Sunlight=%0.2f lx\n",temp);
return temp;
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍BH1750的使用,在使用BH1750前要学好C语言和32单片机。
下面是一些参考资料:链接:https://pan.baidu.com/s/130FgxdHM6iHjuuoQNk_GEQ?pwd=jk07
提取码:jk07(f103-mini原理图)
链接:https://pan.baidu.com/s/1bBw2-GxwMST1IQwkkUEQQg?pwd=0pko
提取码:0pko (野火- 零死角玩转stm32)