使用STM32读取BH1750光照传感器的方法详解

stm32读取BH1750光照传感器

  • 一.序言
  • 二.BH1750指令
  • 三.IIC协议
  • 四.代码实例
  • 4.1 bh1750.c源文件
  • 4.2 bh1750.h头文件
  • 一.序言

    BH1750是用IIC协议进行数据传输的。有SCL,SDA,VCC,GND四根线。下图是原理图

    二.BH1750指令

    我们先看芯片手册的操作指令(下图)含有掉电,上电,连续转化,一次转化以及转化的分辨率等。具体可以看下面的表格写的很详细。写代码时候需要用到(非常关键)。

    这里我也整理出来了一个指令表格,方便阅读,和后序的操作。

    指令 操作值
    POWER_OFF 0x00
    POWER_OFF 0x01
    MODULE_RESET 0x07
    CONTINUE_H_MODE 0x10
    CONTINUE_H_MODE2 0x11
    CONTINUE_L_MODE 0x13
    ONE_TIME_H_MODE 0x20
    ONE_TIME_H_MODE2 0x21
    ONE_TIME_L_MODE 0x23

    三.IIC协议

    IIC协议是在嵌入式中比较常用通信协议的,也是非常重要的。所以我们务必需要掌握IIC协议。
    这里可以参考我的上一篇博文 一文教你彻底学会IIC协议

    四.代码实例

    4.1 bh1750.c源文件

    
    #include "bh1750.h"
    
     
    /*
    	应用说明:
    	在访问I2C设备前,请先调用 i2c_CheckDevice() 检测I2C设备是否正常,该函数会配置GPIO
    */
     
     
    static void I2C_BH1750_GPIOConfig(void);
     
     
    /*
    *********************************************************************************************************
    *	函 数 名: i2c_Delay
    *	功能说明: I2C总线位延迟,最快400KHz
    *	形    参:无
    *	返 回 值: 无
    *********************************************************************************************************
    */
    static void i2c_Delay(void)
    {
    	uint8_t i;
    	/* 
    	 	下面的时间是通过逻辑分析仪测试得到的。
        工作条件:CPU主频72MHz ,MDK编译环境,1级优化
      
    		循环次数为10时,SCL频率 = 205KHz  
    		循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 
    	 	循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us 
    	*/
    	for (i = 0; i < 10; i++);
    }
    /*
    *********************************************************************************************************
    *	函 数 名: i2c_Start
    *	功能说明: CPU发起I2C总线启动信号
    *	形    参:无
    *	返 回 值: 无
    *********************************************************************************************************
    */
    void i2c_Start(void)
    {
    	/* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
    	BH1750_I2C_SDA_1();
    	BH1750_I2C_SCL_1();
    	i2c_Delay();
    	BH1750_I2C_SDA_0();
    	i2c_Delay();
    	BH1750_I2C_SCL_0();
    	i2c_Delay();
    }
    /*
    *********************************************************************************************************
    *	函 数 名: i2c_Start
    *	功能说明: CPU发起I2C总线停止信号
    *	形    参:无
    *	返 回 值: 无
    *********************************************************************************************************
    */
    void i2c_Stop(void)
    {
    	/* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
    	BH1750_I2C_SDA_0();
    	BH1750_I2C_SCL_1();
    	i2c_Delay();
    	BH1750_I2C_SDA_1();
    }
    /*
    *********************************************************************************************************
    *	函 数 名: i2c_SendByte
    *	功能说明: CPU向I2C总线设备发送8bit数据
    *	形    参:_ucByte : 等待发送的字节
    *	返 回 值: 无
    *********************************************************************************************************
    */
    void i2c_SendByte(uint8_t _ucByte)
    {
    	uint8_t i;
     
    	/* 先发送字节的高位bit7 */
    	for (i = 0; i < 8; i++)
    	{		
    		if (_ucByte & 0x80)
    		{
    			BH1750_I2C_SDA_1();
    		}
    		else
    		{
    			BH1750_I2C_SDA_0();
    		}
    		i2c_Delay();
    		BH1750_I2C_SCL_1();
    		i2c_Delay();	
    		BH1750_I2C_SCL_0();
    		if (i == 7)
    		{
    			 BH1750_I2C_SDA_1(); // 释放总线
    		}
    		_ucByte <<= 1;	/* 左移一个bit */
    		i2c_Delay();
    	}
    }
    /*
    *********************************************************************************************************
    *	函 数 名: i2c_ReadByte
    *	功能说明: CPU从I2C总线设备读取8bit数据
    *	形    参:无
    *	返 回 值: 读到的数据
    *********************************************************************************************************
    */
    uint8_t i2c_ReadByte(void)
    {
    	uint8_t i;
    	uint8_t value;
    	/* 读到第1个bit为数据的bit7 */
    	value = 0;
    	for (i = 0; i < 8; i++)
    	{
    		value <<= 1;
    		BH1750_I2C_SCL_1();
    		i2c_Delay();
    		if (BH1750_I2C_SDA_READ())
    		{
    			value++;
    		}
    		BH1750_I2C_SCL_0();
    		i2c_Delay();
    	}
    	return value;
    }
    /*
    *********************************************************************************************************
    *	函 数 名: i2c_WaitAck
    *	功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
    *	形    参:无
    *	返 回 值: 返回0表示正确应答,1表示无器件响应
    *********************************************************************************************************
    */
    uint8_t i2c_WaitAck(void)
    {
    	uint8_t re;
     
    	BH1750_I2C_SDA_1();	/* CPU释放SDA总线 */
    	i2c_Delay();
    	BH1750_I2C_SCL_1();	/* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
    	i2c_Delay();
    	if (BH1750_I2C_SDA_READ())	/* CPU读取SDA口线状态 */
    		re = 1;
    	else
    		re = 0;
    	BH1750_I2C_SCL_0();
    	i2c_Delay();
    	return re;
    }
    /*
    *********************************************************************************************************
    *	函 数 名: i2c_Ack
    *	功能说明: CPU产生一个ACK信号
    *	形    参:无
    *	返 回 值: 无
    *********************************************************************************************************
    */
    void i2c_Ack(void)
    {
    	BH1750_I2C_SDA_0();	/* CPU驱动SDA = 0 */
    	i2c_Delay();
    	BH1750_I2C_SCL_1();	/* CPU产生1个时钟 */
    	i2c_Delay();
    	BH1750_I2C_SCL_0();
    	i2c_Delay();
    	BH1750_I2C_SDA_1();	/* CPU释放SDA总线 */
    }
    /*
    *********************************************************************************************************
    *	函 数 名: i2c_NAck
    *	功能说明: CPU产生1个NACK信号
    *	形    参:无
    *	返 回 值: 无
    *********************************************************************************************************
    */
    void i2c_NAck(void)
    {
    	BH1750_I2C_SDA_1();	/* CPU驱动SDA = 1 */
    	i2c_Delay();
    	BH1750_I2C_SCL_1();	/* CPU产生1个时钟 */
    	i2c_Delay();
    	BH1750_I2C_SCL_0();
    	i2c_Delay();	
    }
    /*
    *********************************************************************************************************
    *	函 数 名: I2C_BH1750_GPIOConfig
    *	功能说明: 配置I2C总线的GPIO,采用模拟IO的方式实现
    *	形    参:无
    *	返 回 值: 无
    *********************************************************************************************************
    */
    static void I2C_BH1750_GPIOConfig(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	RCC_APB2PeriphClockCmd(BH1750_RCC_I2C_PORT, ENABLE);	/* 打开GPIO时钟 */
    	GPIO_InitStructure.GPIO_Pin = BH1750_I2C_SCL_PIN | BH1750_I2C_SDA_PIN;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  	/* 开漏输出 */
    	GPIO_Init(BH1750_GPIO_PORT_I2C, &GPIO_InitStructure);
    	/* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
    	i2c_Stop();
    }
    /*
    *********************************************************************************************************
    *	函 数 名: i2c_CheckDevice
    *	功能说明: 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在
    *	形    参:_Address:设备的I2C总线地址
    *	返 回 值: 返回值 0 表示正确, 返回1表示未探测到
    *********************************************************************************************************
    */
    uint8_t i2c_CheckDevice(uint8_t _Address)
    {
    	uint8_t ucAck;
    	i2c_Start();		/* 发送启动信号 */
    	/* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */
    	i2c_SendByte(_Address | BH1750_I2C_WR);
    	ucAck = i2c_WaitAck();	/* 检测设备的ACK应答 */
    	i2c_Stop();			/* 发送停止信号 */
    	return ucAck;
    }
    //BH1750写一个字节
    //返回值	成功:0		失败:非0 
    uint8_t BH1750_Byte_Write(uint8_t data)
    {
    	i2c_Start();
    	//发送写地址
    	i2c_SendByte(BH1750_Addr|0);
    	if(i2c_WaitAck()==1)
    		return 1;
    	//发送控制命令
    	i2c_SendByte(data);
    	if(i2c_WaitAck()==1)
    		return 2;
    	i2c_Stop();
    	return 0;
    }
    //BH1750读取测量数据
    //返回值 成功:返回光照强度 	失败:返回0
    uint16_t BH1750_Read_Measure(void)
    {
    	uint16_t receive_data=0; 
    	i2c_Start();
    	//发送读地址
    	i2c_SendByte(BH1750_Addr|1);
    	if(i2c_WaitAck()==1)
    		return 0;
    	//读取高八位
    	receive_data=i2c_ReadByte();
    	i2c_Ack();
    	//读取低八位
    	receive_data=(receive_data<<8)+i2c_ReadByte();
    	i2c_NAck();
    	i2c_Stop();
    	return receive_data;	//返回读取到的数据
    }
     
    //BH1750s上电
    void BH1750_Power_ON(void)
    {
    	BH1750_Byte_Write(POWER_ON);
    }
    //BH1750s断电
    void BH1750_Power_OFF(void)
    {
    	BH1750_Byte_Write(POWER_OFF);
    }
    //BH1750复位	仅在上电时有效
    void BH1750_RESET(void)
    {
    	BH1750_Byte_Write(MODULE_RESET);
    }
     
    //BH1750初始化
    uint8_t BH1750_Init(void)
    {
    	I2C_BH1750_GPIOConfig();		/* 配置GPIO */
    	
    	BH1750_Power_ON();	//BH1750s上电
    	//BH1750_RESET();			//BH1750复位
    	return BH1750_Byte_Write(Measure_Mode);
    	//SysTick_Delay_ms(120);
    }
    //获取光照强度
    int LIght_Intensity(void)
    {
    	float v;
    	v = (float)(BH1750_Read_Measure()/1.1f*Resolurtion);
    	return (int) v;
    }
    
    

    4.2 bh1750.h头文件

    #ifndef __BH1750_H
    #define __BH1750_H	 
    #include "stm32f10x.h"
    //BH1750的地址
    #define BH1750_Addr				0x46//0x46
     
    //BH1750指令码
    #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
     
    //测量模式
    #define Measure_Mode			CONTINUE_H_MODE
     
    //分辨率	光照强度(单位lx)=(High Byte  + Low Byte)/ 1.2 * 测量精度
    #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
     
    #define BH1750_I2C_WR	0		/* 写控制bit */
    #define BH1750_I2C_RD	1		/* 读控制bit */
     
     
    /* 定义I2C总线连接的GPIO端口, 只需要修改下面4行代码即可任意改变SCL和SDA的引脚 */
    #define BH1750_GPIO_PORT_I2C	GPIOB			/* GPIO端口 */
    #define BH1750_RCC_I2C_PORT 	RCC_APB2Periph_GPIOB		/* GPIO端口时钟 */
    #define BH1750_I2C_SCL_PIN		GPIO_Pin_6			/* 连接到SCL时钟线的GPIO */
    #define BH1750_I2C_SDA_PIN		GPIO_Pin_7			/* 连接到SDA数据线的GPIO */
     
     
    /* 定义读写SCL和SDA的宏,已增加代码的可移植性和可阅读性 */
    
    	#define BH1750_I2C_SCL_1()  GPIO_SetBits(BH1750_GPIO_PORT_I2C, BH1750_I2C_SCL_PIN)		/* SCL = 1 */
    	#define BH1750_I2C_SCL_0()  GPIO_ResetBits(BH1750_GPIO_PORT_I2C, BH1750_I2C_SCL_PIN)		/* SCL = 0 */
    	
    	#define BH1750_I2C_SDA_1()  GPIO_SetBits(BH1750_GPIO_PORT_I2C, BH1750_I2C_SDA_PIN)		/* SDA = 1 */
    	#define BH1750_I2C_SDA_0()  GPIO_ResetBits(BH1750_GPIO_PORT_I2C, BH1750_I2C_SDA_PIN)		/* SDA = 0 */
    	
    	#define BH1750_I2C_SDA_READ()  GPIO_ReadInputDataBit(BH1750_GPIO_PORT_I2C, BH1750_I2C_SDA_PIN)	/* 读SDA口线状态 */
    
     
     
    void i2c_Start(void);
    void i2c_Stop(void);
    void i2c_SendByte(uint8_t _ucByte);
    uint8_t i2c_ReadByte(void);
    uint8_t i2c_WaitAck(void);
    void i2c_Ack(void);
    void i2c_NAck(void);
    uint8_t i2c_CheckDevice(uint8_t _Address);
     
    uint8_t BH1750_Init(void);			//未包含IIC初始化
    int LIght_Intensity(void);	//读取光照强度的值
    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
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用STM32读取BH1750光照传感器的方法详解

    发表评论