stm32读取BH1750光照传感器

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: stm32读取BH1750光照传感器

一.序言

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


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
6月前
|
传感器
【STM32】I2C练习,SHT3X温度传感器的数据读取
【STM32】I2C练习,SHT3X温度传感器的数据读取
105 0
|
4月前
|
传感器 数据安全/隐私保护 数据格式
STM32CubeMX DHT11温湿度传感器
STM32CubeMX DHT11温湿度传感器
253 11
|
5月前
|
传感器 数据格式
【STM32】DHT11温湿度模块传感器详解&代码
【STM32】DHT11温湿度模块传感器详解&代码
|
6月前
|
传感器 数据采集 物联网
基于STM32的光敏传感器数据采集系统-嵌入式系统与设计课程设计2
基于STM32的光敏传感器数据采集系统-嵌入式系统与设计课程设计
701 0
|
存储 传感器 编解码
STM32外设系列—BH1750
本文详细介绍了BH1750的特点,原理图,IIC通信协议。给出了BH1750程序设计,能够实时获取周围环境光照强度。最后,给出了两种拓展应用,并说明了实现思路。
1260 0
STM32外设系列—BH1750
|
6月前
|
传感器 数据采集 物联网
基于STM32的光敏传感器数据采集系统-嵌入式系统与设计课程设计1
基于STM32的光敏传感器数据采集系统-嵌入式系统与设计课程设计
535 0
|
传感器 安全
嵌入式 STM32 SHT31温湿度传感器
嵌入式 STM32 SHT31温湿度传感器
|
传感器 数据采集 SDN
STM32(HAL库)驱动AD8232心率传感器
STM32(HAL库)驱动AD8232心率传感器
|
5月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
440 2
|
4月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
711 0