介紹
BH1750是一款數(shù)字式環(huán)境光傳感器,能夠準(zhǔn)確地測(cè)量環(huán)境光的亮度。BH1750采用數(shù)字式輸出,具有高精度、快速響應(yīng)、低功耗的特點(diǎn),廣泛應(yīng)用于照明自動(dòng)控制、智能設(shè)備、電子識(shí)別等領(lǐng)域。BH1750能簡(jiǎn)化光控設(shè)計(jì),接口方便,采用I2C總線通信協(xié)議,支持多種測(cè)量模式,并可通過(guò)設(shè)置來(lái)調(diào)整測(cè)量靈敏度。BH1750工作溫度范圍廣,適用于各種環(huán)境。除此之外,BH1750還有很多其他的特性,如可控制的精度、可選的地址引腳、多種輸出范圍等。在物聯(lián)網(wǎng)、智能家居等領(lǐng)域,BH1750正在發(fā)揮越來(lái)越重要的作用。
原理圖
資源獲取
歡迎關(guān)注微信公眾號(hào)--星之援工作室 發(fā)送關(guān)鍵字(BH1750)
main.c
/**
* @brief 主函數(shù)
* @param 無(wú)
* @retval 無(wú)
*/
int main(void)
{
/* 初始化系統(tǒng)時(shí)鐘*/
SysTick_Init();
delay_init();//初始化延時(shí)函數(shù)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
USART_Config();//初始化串口1
printf("rn*** bh1750傳感器實(shí)驗(yàn)***rn");
bh1750_Init();//初始化bh1750
while(1)
{
light=getValue();
UsartPrintf(DEBUG_USARTx,"光照:%d",light); //打印串口數(shù)據(jù) ,再加一個(gè)光照強(qiáng)度%d light
Delay_ms(2000);
}
}
BH1750.h
#ifndef __BH1750_I2C_H
#define __BH1750_I2C_H
#include "stm32f10x.h"
/************************************
* 連接 VCC-->3.3V GND-->GND
* ADDR----->GND
* SCL ----->pb6
* sda ----->pb5
*************************************/
//IO方向設(shè)置
//#include "SysTick.h"
#include "time.h"
#include "./usart/bsp_usart.h"
#define BH1750_SDA_IN() {GPIOB->CRL&=0XFF0FFFFF;GPIOB->CRL|=(u32)8<<20;}
#define BH1750_SDA_OUT() {GPIOB->CRL&=0XFF0FFFFF;GPIOB->CRL|=(u32)3<<20;}
//IO操作函數(shù)
#define BH1750_IIC_SCL PBout(6) //SCL
#define BH1750_IIC_SDA PBout(5) //SDA
#define BH1750_READ_SDA PBin(5) //輸入SDA
#define BH1750_SlaveAddress 0x46 //定義器件在IIC總線中的從地址,根據(jù)ALT ADDRESS地址引腳不同修改
//ALT ADDRESS引腳接地時(shí)地址為0x46,接電源時(shí)地址為0xB8
extern float lux;
void bh1750_iic_init(void);
void bh1750_iic_start(void);
void bh1750_iic_stop(void);
void bh1750_send_ack(char ack);
char bh1750_recv_ack(void);
void bh1750_send_byte(char dat);
char bh1750_recv_byte(unsigned char ack);
void bh1750_iic_init(void);
void Single_Write_bh1750(unsigned char Reg_Address);
void bh1750_Init(void);
void bh1750_ReadOneTime(void);
void bh1750_ReadContinuous1(void);
u8 getValue(void);
#endif /* __BH1750_I2C_H */
BH1750.c
#include "BH1750.h"
#include "sys.h"
#include "delay.h"
u8 BUF[8];
u16 temp2=0;
float lux=0;
void bh1750_iic_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_5|GPIO_Pin_6); //PB6,PB7 輸出高
}
/****向BH1750單次寫(xiě)命令****/
void Single_Write_bh1750(unsigned char Reg_Address)
{
bh1750_iic_start();
bh1750_send_byte(0x46); //發(fā)送器件地址0100 0110 最后一位0,表示寫(xiě)
//IIC_Wait_Ack();
bh1750_send_byte(Reg_Address);
//IIC_Wait_Ack();
bh1750_iic_stop();
}
/****BH1750初始化****/
void bh1750_Init(void)
{
// TIM4_PWM_Init(899,0);
bh1750_iic_init();
TIM_SetCompare3(TIM3,0);
}
//光照強(qiáng)度數(shù)據(jù)接收和處理
u8 getValue(void)
{
unsigned char value=0;
Single_Write_bh1750(0x01);
Single_Write_bh1750(0x10);
delay_ms(200);
bh1750_ReadContinuous1();
temp2=BUF[0];
temp2=(temp2<<8)+BUF[1];
lux=(float)temp2/1.2; //lux是float型
if((lux>0)&&(lux<50))
value=10;
else if(lux<75)
value=20;
else if(lux<100)
value=40;
else if(lux<125)
value=50;
else if(lux<150)
value=60;
else if(lux<175)
value=70;
else if(lux<200)
value=80;
else if(lux<250)
value=90;
else if(lux<280)
value=110;
else if(lux<300)
value=120;
else if(lux<320)
value=130;
else if(lux<340)
value=140;
else if(lux<360)
value=150;
else if(lux<380)
value=160;
else if(lux<400)
value=170;
else if(lux<410)
value=180;
else if(lux<450)
value=190;
else if(lux<800)
value=240;
//printf("光照強(qiáng)度:%f value:%drn",lux,value);
TIM_SetCompare3(TIM3,value);
return value;
//Delay_ms(1000);
}
/****從BH1750單次讀Lux****/
/****
模式選擇:H-Resolution Mode,分辨率1lux
單次讀Opecode:0010 0000 ,即0x20
器件地址:0100011,ADDR接GND
****/
void bh1750_ReadOneTime(void)
{
bh1750_iic_start();
bh1750_send_byte(0x46); //發(fā)送器件地址0100 0110 最后一位0,表示寫(xiě)
bh1750_recv_ack();
bh1750_send_byte(0x20); //發(fā)送One time H-Resolution Mode的Opecode 0010 0000,分辨率為1lux
bh1750_recv_ack();
bh1750_iic_stop();
delay_ms(200);
bh1750_iic_start();
bh1750_send_byte(0x47); //
bh1750_recv_ack();
BUF[0]=bh1750_recv_byte(1);
//IIC_Ack(); //主機(jī)應(yīng)答
//temp1=temp<<8;
BUF[1]=bh1750_recv_byte(0);
//IIC_NAck(); //主機(jī)不應(yīng)答
bh1750_iic_stop();
// temp2=BUF[0];
// temp2=(temp2<<8)+BUF[1];
// lux=(float)temp2/1.2; //lux是float型
//return lux;
//Delay_ms(200);
}
/****從BH1750連續(xù)讀Lux****/
/****
模式選擇:H-Resolution Mode,分辨率1lux
連續(xù)讀Opecode:0001 0000
器件地址:0100011,ADDR接GND
****/
void bh1750_ReadContinuous1(void)
{
// u16 temp=0,temp1=0;
bh1750_iic_start();
bh1750_send_byte(0x46); //發(fā)送器件地址0100 0110 最后一位0,表示寫(xiě)
bh1750_recv_ack();
bh1750_send_byte(0x10); //發(fā)送Continuous H-Resolution Mode的Opecode 0001 0000,分辨率為1lux
bh1750_recv_ack();
bh1750_iic_stop();
delay_ms(200);
bh1750_iic_start();
bh1750_send_byte(0x47);
bh1750_recv_ack();
BUF[0]=bh1750_recv_byte(1);
BUF[1]=bh1750_recv_byte(0);
//temp=bh1750_recv_byte(1);
//temp1=bh1750_recv_byte(0);
bh1750_iic_stop();
//temp2=temp1+(temp<<8);
//lux=(float)temp2/1.2; //lux是float型
}
void Conversion(void)
{
temp2=BUF[0];
temp2=(temp2<<8)+BUF[1];
lux=(float)temp2/1.2; //lux是float型
}
/**************************************
起始信號(hào)
**************************************/
void bh1750_iic_start(void)
{
BH1750_SDA_OUT() //設(shè)置SDA線為輸出
//在開(kāi)始數(shù)據(jù)傳輸前,先讓SDA和SCL都拉高
BH1750_IIC_SDA=1; //發(fā)送起始條件的數(shù)據(jù)信號(hào),釋放總線
delay_us(2);
BH1750_IIC_SCL=1;
delay_us(5); //Tsu;STA:起始條件的建立時(shí)間大于4.7us。
BH1750_IIC_SDA=0; //SDA由高變?yōu)榈捅硎鹃_(kāi)始信號(hào)
delay_us(4); //起始條件的保持時(shí)間大于4us
BH1750_IIC_SCL=0; //鉗住IIC總線,準(zhǔn)備發(fā)送或者接收數(shù)據(jù)
delay_us(2);
}
/**************************************
停止信號(hào)
**************************************/
void bh1750_iic_stop(void)
{
BH1750_SDA_OUT() //設(shè)置SDA線為輸出
//IIC_SCL=0; //此句是調(diào)試BH1750時(shí)加,2018.03.03
BH1750_IIC_SDA=0; //發(fā)送停止信號(hào)的數(shù)據(jù)信號(hào)
delay_us(2);
BH1750_IIC_SCL=1; //發(fā)送停止信號(hào)的時(shí)鐘信號(hào)
delay_us(5); //停止信號(hào)的建立時(shí)間大于4us
BH1750_IIC_SDA=1; //發(fā)送停止信號(hào)
delay_us(4); //;
}
/**************************************
發(fā)送應(yīng)答信號(hào)
入口參數(shù):ack (0:ACK 1:NAK)
**************************************/
void bh1750_send_ack(char ack)
{
BH1750_IIC_SCL=0;
BH1750_SDA_OUT();
BH1750_IIC_SDA=ack; //主器件應(yīng)答
delay_us(2);
BH1750_IIC_SCL=1;
delay_us(4); //SCL高電平周期大于4us
BH1750_IIC_SCL=0; //清時(shí)鐘線,鉗住IIC總線以便繼續(xù)接收
delay_us(2);
}
/**************************************
接收應(yīng)答信號(hào)
**************************************/
char bh1750_recv_ack(void)
{
u8 ucErrorTime=0;
BH1750_SDA_IN(); //SDA設(shè)置成輸入
BH1750_IIC_SDA=1;
delay_us(2);
BH1750_IIC_SCL=1;
delay_us(2);
while(BH1750_READ_SDA)
{
ucErrorTime++;
if(ucErrorTime>=250)
{
bh1750_iic_stop();
return 1;
}
}
BH1750_IIC_SCL=0;
return 0;
}
/**************************************
向IIC總線發(fā)送一個(gè)字節(jié)數(shù)據(jù)
**************************************/
void bh1750_send_byte(char dat)
{
u8 i;
BH1750_SDA_OUT();
for(i=0;i<8;i++)
{
if((dat<<i)&0x80) BH1750_IIC_SDA=1; //判斷發(fā)送位
else BH1750_IIC_SDA=0;
delay_us(2);
BH1750_IIC_SCL=1; //拉高SCL,通知被控器開(kāi)始接收數(shù)據(jù)位
delay_us(4); //保證SCL高電平周期大于4us
BH1750_IIC_SCL=0; //拉低SCL,允許SDA傳輸下一位數(shù)據(jù)。因?yàn)橹挥性赟CL=0時(shí)才允許SDA的狀態(tài)發(fā)生變化
delay_us(2);
}
//以下四句是調(diào)試BH1750時(shí)添加的,2018.03.03
//特別注意;用方法三時(shí),以下四句不可去掉,去掉后得到的數(shù)有問(wèn)題
//用方法二時(shí),以下四句需注釋掉,否則也會(huì)有問(wèn)題,至于原因暫時(shí)還不清楚。
// IIC_SDA=0;
// Delay_us(2);
// IIC_SCL=1;
// Delay_us(2);
BH1750_IIC_SCL=0; //拉低SCL,為下次數(shù)據(jù)傳輸做好準(zhǔn)備
delay_us(2);
}
/**************************************
從IIC總線接收一個(gè)字節(jié)數(shù)據(jù)
用來(lái)接收從器件傳來(lái)的數(shù)據(jù),ack為1時(shí),發(fā)送Ack(產(chǎn)生應(yīng)答);ack為0時(shí),發(fā)送NAck(不產(chǎn)生應(yīng)答)
**************************************/
char bh1750_recv_byte(unsigned char ack)
{
unsigned char i,receive=0;
BH1750_SDA_IN();
for(i=0;i<8;i++)
{
BH1750_IIC_SCL=0; //置SCL為低,準(zhǔn)備接收數(shù)據(jù)位
delay_us(5); //時(shí)鐘低電平周期大于4.7us
BH1750_IIC_SCL=1; //置SCL為高,使SDA上數(shù)據(jù)有效
delay_us(2);
receive=receive<<1;
if(BH1750_READ_SDA) receive=receive+1; //讀取SDA,把接收的數(shù)據(jù)位放入receve中,若此處寫(xiě)成IIC_SDA==1,會(huì)失敗,思考原因?
delay_us(2);
}
if(!ack)
bh1750_send_ack(1); //發(fā)送NAck
else
bh1750_send_ack(0); //發(fā)送Ack
//IIC_SCL=0; //在此處有何用處???(猜測(cè):為下次數(shù)據(jù)傳輸做好準(zhǔn)備, //鉗住IIC總線,準(zhǔn)備發(fā)送或者接收數(shù)據(jù))
//Delay_us(2);
return receive;
}
/*************************************END OF FILE******************************/
參考
BH1750( GY-302 )光照傳感器https://blog.csdn.net/Dustinthewine/article/details/127540711?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170212703316800186517198%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170212703316800186517198&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-127540711-null-null.142^v96^pc_search_result_base7&utm_term=bh1750&spm=1018.2226.3001.4187
聯(lián)系方式 微信號(hào):13648103287