stm32f1 Series SCM drives BH1750/GY302 module

STM32f1 series single chip microcomputer drives BH1750

Forward this article, please mark it out!

  • First of all, the next * * GY302 module is actually a BH1750 chip * *, and then an external driver circuit is added, which is essentially the same.

  • In a word, BH1750 is a light intensity sensor. The input voltage VCC is between 3.0v-3.6v. We usually use 3.3v power supply. The standard IIC protocol is used for communication. There are two options for our IIC address. Please see the back for how to choose. It has a spectral effect close to vision. To put it bluntly, it is the light wave range that your eyes can feel, and it also happens to be the range, so this module is the best for the light intensity sensing products for consumers; its input light range is 1-65535lx

  • At the beginning, I used STM32's hardware IIC to write this program, but I found that no matter how the whole program is 0x80, and the STM32's hardware IIC is a bit of a problem. Later, I just changed to software IIC without getting it out, and the following program is also written with software IIC. Friends who are successful in hardware iic can share it. I also left the code of hardware IIC I wrote in Now, I hope there are enthusiastic partners to study why the hardware IIC is not successful. When writing the hardware IIC, we must pay attention to two points. First, the address of the IIC slave is 7 bits forward, and the eighth bit is the read-write bit. Second, the EV6 events in the STM32 read-write sequence are named EV6, but the codes are different. They are i2c_event_master_receiver_umode_ Attention must be paid to selected and I2C event master transmission mode selected!

  • Here are some problems to be noticed when writing the driver of BH1750:

  • Selection of chip IIC address: by changing the level of ADDR pin

    • When connected to low level, it is "0100011"
    • "1011100" when connected to high level
    • Note that the address is 7 digits! 7! 7!!! So if you use hardware IIC, remember to move the address to the front by 1 bit, and then the read address is at least 1, and the write address is at least 0. For example, when the ADDR is connected low, the IIC address is 0x46, and the read address is 0x46+1, and the write address is 0x46
  • Calculation method of light intensity: light intensity (unit: lx) = (high byte + low byte) / 1.2 * measurement accuracy

  • There are six working modes of the chip. It should be noted that the higher the accuracy is, the longer the measurement time is. The longest one is 120ms, so you have to delay once you test and play, and then pay attention to the difference between continuous measurement and single measurement. After you send and power on the continuous measurement, configure the measurement mode, and then read it continuously. When you measure once alone, you need to send it first Electrical - Measurement Mode - Reread measurement results

  • The others are very simple. If you know IIC, if you don't, you can find information on the Internet to learn

This is the Chinese Reference Manual of BH1750. Please refer to [https://wenku.baidu.com/view/57203d05856a5611252d36ff6. HTML]

  • Next, let's put the code
  • The main function is very simple. First, check whether the module is available, and then initialize the BH1750 module. In fact, send the power on command, send the measurement mode, and then read the data continuously
int main(void)
{
	LED_GPIO_Config();
	USART_Config();
	//I2C_BH1750_Config();
	if(i2c_CheckDevice(BH1750_Addr)==0)
		printf("BH1750 Device test successful\r\n");
	else printf("BH1750 Device detection failed\r\n");
	
	BH1750_Init();
	
	printf("Light intensity sensor experiment\r\n");
	
	while(1)
	{
		printf("Light intensity:%f lx\r\n",LIght_Intensity());
		SysTick_Delay_ms(500);
	}
}

Next is its driver function. First look at the header file, which contains a lot of definitions

#ifndef __BH1750_I2C_H
#define __BH1750_I2C_H

#include "stm32f10x.h"
#include "./I2C_BH1750/i2c_bh1750_gpio.h"
#include "./SYSTICK/systick.h"

//Address of BH1750
#define BH1750_Addr				0x46

//BH1750 command code
#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

//Measurement mode
#define Measure_Mode			CONTINUE_H_MODE

//Resolution light intensity (unit: lx) = (high byte + low byte) / 1.2 * measurement accuracy
#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

void BH1750_Init(void);			//IIC initialization not included
float LIght_Intensity(void);	//Reading the value of light intensity
uint8_t BH1750_Byte_Write(uint8_t data);
uint16_t BH1750_Read_Measure(void);
void BH1750_Power_ON(void);
void BH1750_Power_OFF(void);
void BH1750_RESET(void);

#endif /* __BH1750_I2C_H */


C file is as follows: as long as you understand IIC and C, you can understand what you are doing

#include "./I2C_BH1750/i2c_bh1750.h"

//BH1750 write a byte
//Return value success: 0 failure: not 0 
uint8_t BH1750_Byte_Write(uint8_t data)
{
	i2c_Start();
	//Send write address
	i2c_SendByte(BH1750_Addr|0);
	if(i2c_WaitAck()==1)
		return 1;
	//Send control command
	i2c_SendByte(data);
	if(i2c_WaitAck()==1)
		return 2;
	i2c_Stop();
	return 0;
}

//BH1750 reading measurement data
//Return value successful: return light intensity failed: return 0
uint16_t BH1750_Read_Measure(void)
{
	uint16_t receive_data=0; 
	i2c_Start();
	//Send read address
	i2c_SendByte(BH1750_Addr|1);
	if(i2c_WaitAck()==1)
		return 0;
	//Read high octet
	receive_data=i2c_ReadByte();
	i2c_Ack();
	//Read low octet
	receive_data=(receive_data<<8)+i2c_ReadByte();
	i2c_NAck();
	i2c_Stop();
	return receive_data;	//Return read data
}


//BH1750s power on
void BH1750_Power_ON(void)
{
	BH1750_Byte_Write(POWER_ON);
}

//BH1750s power off
void BH1750_Power_OFF(void)
{
	BH1750_Byte_Write(POWER_OFF);
}

//BH1750 reset only valid when powered on
void BH1750_RESET(void)
{
	BH1750_Byte_Write(MODULE_RESET);
}

//BH1750 initialization
void BH1750_Init(void)
{
	BH1750_Power_ON();	//BH1750s power on
	//BH1750? Reset(); / / BH1750 reset
	BH1750_Byte_Write(Measure_Mode);
	SysTick_Delay_ms(120);
}

//Obtaining light intensity
float LIght_Intensity(void)
{
	return (float)(BH1750_Read_Measure()/1.2f*Resolurtion);
}

Isn't it very simple, but I don't know why I can't use the hardware IIC. Maybe I hit the problem of STM32 hardware IIC. It's said on the Internet that the time to receive the response signal is too short. If I miss it, GG will be the only one. Friends with successful hardware iic can share it. I also post the code of the hardware IIC I wrote, as follows:
This is the header file

#ifndef _I2C_H_
#define _I2C_H_

#include "stm32f10x.h"

#define 	stm32_I2C_OWN_Addr				0x5f	//The self address of stm32 in IIC communication note that the address is 7 bits

#define		BH1750_SCL_GPIO_PORT			GPIOB
#define		BH1750_SCL_GPIO_PIN				GPIO_Pin_6
#define 	BH1750_SCL_APBxClkCmd			RCC_APB2PeriphClockCmd
#define		BH1750_SCL_GPIO_CLK				RCC_APB2Periph_GPIOB

#define		BH1750_SDA_GPIO_PORT			GPIOB
#define		BH1750_SDA_GPIO_PIN				GPIO_Pin_7
#define 	BH1750_SDA_APBxClkCmd			RCC_APB2PeriphClockCmd
#define		BH1750_SDA_GPIO_CLK				RCC_APB2Periph_GPIOB

#define 	BH1750_I2Cx								I2C1
#define 	I2Cx_BH1750_ClockSpeek		400000
#define 	I2Cx_BH1750_APBxClkCmd		RCC_APB1PeriphClockCmd
#define 	I2Cx_BH1750_CLK						RCC_APB1Periph_I2C1
#define 	BH1750_Addr								0x46


//BH1750 command code
#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

//Measurement mode
#define Measure_Mode			ONE_TIME_H_MODE

//Resolution light intensity (unit: lx) = (high byte + low byte) / 1.2 * measurement accuracy
#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

/*Wait timeout*/
#define I2CT_FLAG_TIMEOUT         ((uint32_t)0x1000)
#define I2CT_LONG_TIMEOUT         ((uint32_t)(10 * I2CT_FLAG_TIMEOUT))


void I2C_BH1750_Config(void);
void BH1750_Init(void);			//IIC initialization not included
float LIght_Intensity(void);	//Reading the value of light intensity
uint8_t BH1750_Byte_Write(uint8_t data);
uint16_t BH1750_Read_Measure(void);
void BH1750_Power_ON(void);
void BH1750_Power_OFF(void);
void BH1750_RESET(void);

#endif /* _I2C_H_ */

This is a C file

#include "./I2C_BH1750/i2c_bh1750.h"			//". /" refers to the current directory

static __IO uint32_t  I2CTimeout = I2CT_LONG_TIMEOUT;   

void I2C_BH1750_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	I2C_InitTypeDef	I2C_InitStruct;
	
	//Turn on IIC clock
	I2Cx_BH1750_APBxClkCmd(I2Cx_BH1750_CLK, ENABLE);
	
	//Turn on GPIO clock
	BH1750_SCL_APBxClkCmd(BH1750_SCL_GPIO_CLK, ENABLE);
	BH1750_SDA_APBxClkCmd(BH1750_SDA_GPIO_CLK, ENABLE);
	
	//Configure SCL pin
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStruct.GPIO_Pin = BH1750_SCL_GPIO_PIN;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(BH1750_SCL_GPIO_PORT, &GPIO_InitStruct);
	
	//Configure SDA pin
	GPIO_InitStruct.GPIO_Pin = BH1750_SDA_GPIO_PIN;
	GPIO_Init(BH1750_SDA_GPIO_PORT, &GPIO_InitStruct);
	
	//Configure IIC
	I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_InitStruct.I2C_ClockSpeed = I2Cx_BH1750_ClockSpeek;
	I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStruct.I2C_OwnAddress1 = stm32_I2C_OWN_Addr;
	I2C_Init(BH1750_I2Cx, &I2C_InitStruct);
	
	I2C_Cmd(BH1750_I2Cx, ENABLE);
}


/*
 * Write a byte of data to BH1750
 * Success will return 0, unsuccessful will return non-zero positive integer
 */
uint8_t BH1750_Byte_Write(uint8_t data)
{
	I2CTimeout = I2CT_LONG_TIMEOUT;
	//Send start signal
	I2C_GenerateSTART(BH1750_I2Cx, ENABLE);
	
	//Detect EV5 events
	while(I2C_CheckEvent(BH1750_I2Cx, I2C_EVENT_MASTER_MODE_SELECT) == ERROR)
	{
		if((I2CTimeout--) == 0) return 1;
	}
	I2CTimeout = I2CT_FLAG_TIMEOUT;
	
	//Send address write
	I2C_Send7bitAddress(BH1750_I2Cx, BH1750_Addr, I2C_Direction_Transmitter);
	
	//Detect EV6 events. Note that EV6 is divided into sending and receiving
	while(I2C_CheckEvent(BH1750_I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == ERROR)
	{
		if((I2CTimeout--) == 0) 
			return 2;
	}
	I2CTimeout = I2CT_FLAG_TIMEOUT;
	
	//Send storage unit address for operation
	I2C_SendData(BH1750_I2Cx, data);
	
	//Detect ev8 ﹣ 2 events
	while(I2C_CheckEvent(BH1750_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR)
	{
		if((I2CTimeout--) == 0) return 4;
	}
	
	//Send stop signal
	I2C_GenerateSTOP(BH1750_I2Cx, ENABLE);
	
	return 0;
}

//Read out the measured value of the light intensity sensor
//Success return: illuminance sensor register value Failure Return: 0
uint16_t BH1750_Read_Measure(void)
{
	uint16_t receive_data;
	I2CTimeout = I2CT_LONG_TIMEOUT;
	//Send start signal
	I2C_GenerateSTART(BH1750_I2Cx, ENABLE);
	
	//Detect EV5 events
	while(I2C_CheckEvent(BH1750_I2Cx, I2C_EVENT_MASTER_MODE_SELECT) == ERROR)
	{
		if((I2CTimeout--) == 0) return 0;
	}
	I2CTimeout = I2CT_FLAG_TIMEOUT;
	
	//Send address read
	I2C_Send7bitAddress(BH1750_I2Cx, BH1750_Addr, I2C_Direction_Receiver);
	
	//Detect EV6 events. Note that EV6 is divided into sending and receiving
	while(I2C_CheckEvent(BH1750_I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == ERROR)
	{
		if((I2CTimeout--) == 0) return 0;
	}
	I2CTimeout = I2CT_FLAG_TIMEOUT;
	
	//Reading high octet data of light intensity
	receive_data=I2C_ReceiveData(BH1750_I2Cx);
	//Generate response signal
	I2C_AcknowledgeConfig(BH1750_I2Cx, ENABLE);
	
	//Detect EV7 events
	while(I2C_CheckEvent(BH1750_I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) == ERROR)
	{
		if((I2CTimeout--) == 0) return 0;
	}
	
	//Reading low octet data of light intensity
	receive_data=(receive_data<<8)+I2C_ReceiveData(BH1750_I2Cx);
	//Generate non response signal
	I2C_AcknowledgeConfig(BH1750_I2Cx, DISABLE);
	//Send stop signal
	I2C_GenerateSTOP(BH1750_I2Cx, ENABLE);
	
	//Returns the value of the light intensity
	return receive_data;
}

//BH1750s power on
void BH1750_Power_ON(void)
{
	BH1750_Byte_Write(POWER_ON);
}

//BH1750s power off
void BH1750_Power_OFF(void)
{
	BH1750_Byte_Write(POWER_OFF);
}

//BH1750 reset
void BH1750_RESET(void)
{
	BH1750_Byte_Write(MODULE_RESET);
}

//BH1750 initialization
void BH1750_Init(void)
{
	BH1750_Power_ON();
	BH1750_RESET();
	BH1750_Byte_Write(Measure_Mode);
}

//Obtaining light intensity
float LIght_Intensity(void)
{
	return (float)(BH1750_Read_Measure()/1.2f*Resolurtion);
}

Who can comment on the problem

The whole project I also hung on my blog, need friends can pay attention to me, in my personal center upload file should be able to find!

**

Forward this article, please mark it out!

**

Published 1 original article, praised 0, visited 7
Private letter follow

Posted on Fri, 07 Feb 2020 08:41:39 -0500 by webster08