目录

本集陆续更新传感器外设,废话不多说,开整

资源获取

介绍

原理图

main.c

BH1750.h

BH1750.c


本集陆续更新传感器外设,废话不多说,开整

资源获取

欢迎关注微信公众号--星之援工作室 发送关键字(BH1750)

目录

本集陆续更新传感器外设,废话不多说,开整

main.c

BH1750.h

BH1750.c


介绍

BH1750是一款数字式环境光传感器,能够准确地测量环境光的亮度。BH1750采用数字式输出,具有高精度、快速响应、低功耗的特点,广泛应用于照明自动控制、智能设备、电子识别等领域。BH1750能简化光控设计,接口方便,采用I2C总线通信协议,支持多种测量模式,并可通过设置来调整测量灵敏度。BH1750工作温度范围广,适用于各种环境。除此之外,BH1750还有很多其他的特性,如可控制的精度、可选的地址引脚、多种输出范围等。在物联网、智能家居等领域,BH1750正在发挥越来越重要的作用。

原理图

main.c

/**
  * @brief  主函数
  * @param  无  
  * @retval 无
  */
int main(void)
{
	

	/* 初始化系统时钟*/
	SysTick_Init();
  delay_init();//初始化延时函数
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
	USART_Config();//初始化串口1
	printf("\r\n***  bh1750传感器实验***\r\n");
	bh1750_Init();//初始化bh1750
	
	while(1)
	{	
		light=getValue();
		UsartPrintf(DEBUG_USARTx,"光照:%d",light);	//打印串口数据	,再加一个光照强度%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方向设置
//#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操作函数	 
#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总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
                                     //ALT  ADDRESS引脚接地时地址为0x46,接电源时地址为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时钟
	   
	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单次写命令****/
void Single_Write_bh1750(unsigned char Reg_Address)
{
	bh1750_iic_start();
	bh1750_send_byte(0x46);  //发送器件地址0100 0110   最后一位0,表示写
	//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);	
}
 
//光照强度数据接收和处理
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("光照强度:%f   value:%d\r\n",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);  //发送器件地址0100 0110   最后一位0,表示写
	bh1750_recv_ack();
	bh1750_send_byte(0x20);   //发送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();        //主机应答
	//temp1=temp<<8;
	BUF[1]=bh1750_recv_byte(0);
	//IIC_NAck();        //主机不应答	
	bh1750_iic_stop();
	
	
// 	temp2=BUF[0];
// 	temp2=(temp2<<8)+BUF[1];
// 	lux=(float)temp2/1.2;    //lux是float型
	
	//return lux;
	//Delay_ms(200);
}
 
/****从BH1750连续读Lux****/
/****
模式选择:H-Resolution Mode,分辨率1lux
连续读Opecode:0001 0000
器件地址:0100011,ADDR接GND
****/
void  bh1750_ReadContinuous1(void)
{
//	u16 temp=0,temp1=0;
	bh1750_iic_start();
  bh1750_send_byte(0x46);  //发送器件地址0100 0110   最后一位0,表示写
	bh1750_recv_ack();
	bh1750_send_byte(0x10);  //发送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型
	
}
 
 
 
/**************************************
起始信号
**************************************/
void bh1750_iic_start(void)
{
		BH1750_SDA_OUT()       //设置SDA线为输出
	//在开始数据传输前,先让SDA和SCL都拉高
		BH1750_IIC_SDA=1;    //发送起始条件的数据信号,释放总线
	  delay_us(2);
		BH1750_IIC_SCL=1;    
 
		delay_us(5);   //Tsu;STA:起始条件的建立时间大于4.7us。
	
		BH1750_IIC_SDA=0;    //SDA由高变为低表示开始信号
		delay_us(4);   //起始条件的保持时间大于4us
		BH1750_IIC_SCL=0;    //钳住IIC总线,准备发送或者接收数据
		delay_us(2);
}
 
/**************************************
停止信号
**************************************/
void bh1750_iic_stop(void)
{
	BH1750_SDA_OUT()       //设置SDA线为输出
	
	//IIC_SCL=0;    //此句是调试BH1750时加,2018.03.03
	
	BH1750_IIC_SDA=0;   //发送停止信号的数据信号
	delay_us(2);
	BH1750_IIC_SCL=1;   //发送停止信号的时钟信号
	delay_us(5);  //停止信号的建立时间大于4us
	BH1750_IIC_SDA=1;   //发送停止信号
	delay_us(4);    //;
}
 
/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void bh1750_send_ack(char ack)
{
	BH1750_IIC_SCL=0;
	BH1750_SDA_OUT();
	BH1750_IIC_SDA=ack;   //主器件应答
	delay_us(2);
	BH1750_IIC_SCL=1;
	delay_us(4);        //SCL高电平周期大于4us
	BH1750_IIC_SCL=0;         //清时钟线,钳住IIC总线以便继续接收
	delay_us(2);
 
}
 
/**************************************
接收应答信号
**************************************/
char bh1750_recv_ack(void)
{
	u8 ucErrorTime=0;
	BH1750_SDA_IN();     //SDA设置成输入
	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总线发送一个字节数据
**************************************/
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;   //判断发送位
		else BH1750_IIC_SDA=0;
 
		delay_us(2);
		BH1750_IIC_SCL=1;     //拉高SCL,通知被控器开始接收数据位
		delay_us(4);   //保证SCL高电平周期大于4us
		BH1750_IIC_SCL=0;    //拉低SCL,允许SDA传输下一位数据。因为只有在SCL=0时才允许SDA的状态发生变化
	  delay_us(2);
   }
	 //以下四句是调试BH1750时添加的,2018.03.03
	 //特别注意;用方法三时,以下四句不可去掉,去掉后得到的数有问题
	 //用方法二时,以下四句需注释掉,否则也会有问题,至于原因暂时还不清楚。
// 	 IIC_SDA=0;
// 	 Delay_us(2);
// 	 IIC_SCL=1;
// 	 Delay_us(2);
	 
	 BH1750_IIC_SCL=0;      //拉低SCL,为下次数据传输做好准备
	 delay_us(2);
}
 
/**************************************
从IIC总线接收一个字节数据
用来接收从器件传来的数据,ack为1时,发送Ack(产生应答);ack为0时,发送NAck(不产生应答)
**************************************/
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为低,准备接收数据位
		delay_us(5);  //时钟低电平周期大于4.7us
		BH1750_IIC_SCL=1;   //置SCL为高,使SDA上数据有效
		delay_us(2);
		receive=receive<<1;
		if(BH1750_READ_SDA) receive=receive+1;    //读取SDA,把接收的数据位放入receve中,若此处写成IIC_SDA==1,会失败,思考原因?	
		delay_us(2);
  }
	if(!ack) 
		bh1750_send_ack(1);   //发送NAck
	else 
		bh1750_send_ack(0);    //发送Ack
	//IIC_SCL=0;      //在此处有何用处???(猜测:为下次数据传输做好准备, //钳住IIC总线,准备发送或者接收数据)
	//Delay_us(2);
	return receive;
}



/*************************************END OF FILE******************************/

参考

BH1750( GY-302 )光照传感器icon-default.png?t=N7T8https://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

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐