1.特别说明

​ 要是不想看原理和过程,直接下拉找代码吧,都是测试过的,很稳定,有硬件I2C驱动的,也有软件模拟I2C驱动的,基于STM32F103系列和STM32F4系列实现,基于标准库实现,条理清晰。

2.软硬件硬件准备

​ (1) Kile 5.27

​ (2) 串口助手

​ (3) STM32F103与STM32F4系列单片机

​ (4) CH340 串口转 TTL 工具

​ (5) BH1750-即-GY-302光照传感器

3.了解驱动原理

3.1.程序设计思路


这是官方数据手册给的驱动说明,这是基于标准I2C设计的传感器,也就是说它支持标准全速400KHz速率通信(实测确实没问题);这个流程图大概说的是程序设计:

1.上电初始化

2.掉电再上电(软指令,可省略步骤)

3.发送测量命令(单次测量或者连续测量)

4.读取测量数据

3.2.引脚接线说明

VCC 5V~3.3V
GND GND
SCL PB6
SDA PB7
ADDR VCC/GND

首先这个模块比较友好,支持3V3到5V供电,其次特别注意ADDR这个引脚的接线:

接高电平的硬件地址和接低电平的硬件地址是不一样的:

​ 接高电平硬件地址:0X5C (注意:这是高 7 位地址数据)

​ 接低电平硬件地址:0X23 (注意:这是高 7 位地址数据)

器件地址(7位-用左移1位-最后1位为读写位–1为读-0为写)

3.3驱动时序

写指令流程

1.发送起始信号 ————> 2.发送写指令地址(接收ACK信号)

3.发送操作指令(接收ACK信号) ————> 4.发送停止信号

读指令流程:

1.发送起始信号 ——> 2.发送读指令地址(接收ACK信号)

3.接收高 8 位数据(发送ACK信号) ——> 4.接收低 8 位数据(发送NACK)

5.发送结束信号

3.3.指令集说明

功能 寄存器地址指令 注释说明
断电 0000_0000 没有活动状态。
接通电源 0000_0001 正在等待测量命令。
重置 0000_0111 重置数据寄存器值。在关机模式下,不能接受重置命令。
连续H分辨率模式 0001_0000 以1lx的分辨率开始测量。测量时间通常为120ms。
连续h分辨率模式2 0001_0001 在0.5lx的分辨率下开始测量。测量时间通常为120ms。
连续L分辨率模式 0001_0011 以4lx的分辨率开始测量。测量时间通常为16ms。
一次H分辨率模式 0010_0000 以1lx的分辨率开始测量。测量时间通常为120ms。测量后自动设置为关机模式。
一次H分辨率模式2 0010_0001 在0.5lx的分辨率下开始测量。测量时间通常为120ms。测量后自动设置为关机模式。
一次性L分辨率模式 0010_0011 以4lx的分辨率开始测量。测量时间通常为16ms。测量后自动设置为关机模式。
更改测量时间(高位) 01000_MT[7,6,5] 改变测量时间。※请参考“调整测量结果对光学窗口的影响”。
更改测量时间(低位) 011_MT[4,3,2,1,0] 更改测量时间。※请参考“调整测量结果对光学窗口的影响”。

3.4数据转换

(uint16_t)Data_LX = (uint16_t)(H_data << 8) + (uint8_t)L_data

接收用无符号短 8 位整形接收,移位对齐数据再相加就好了;

4.上代码

4.1硬件IIC驱动

​ 特别说明,在刚开始硬件驱动的时候,出了个小问题:完全照着手册的时序写,就是会卡死在接收高 8 位数据的 EV7事件上;

​ 解决办法:在发送读指令并接收到回应后(EV6 事件),主机给光照模块发送一个 ACK 信号,相当于告诉它我们准备好接受数据了,然后等待光照模块发来数据(EV7事件),接着后面就没啥问题了。

4.1.1 适用STM32F103系列的硬件IIC驱动

BH1750.c

#include "BH1750.h"/****************************************************************************
**  函数名称:I2C_Configuration()
**  函数功能:显示用到的引脚初始化与 IIC初始化
**  参数说明:
**
**  返回值:无
**  IIC_InitTypeDef 说明:I2C_ClockSpeed;       //设置SCL时钟频率,此值最高 400 000I2C_Mode;                //指定工作模式,可选IIC模式及SMBUS模式I2C_DutyCycle;       //时钟占空比,可选low/high = 2:0或16:9I2C_OwnAddress1;        //自身的IIC设备地址I2C_Ack;                //使能或者关闭响应,一般是使能I2C_AcknowledgedAddress;//指定地址长度,可为7或10******************************************************************************STM32F103C8T6芯片的硬件:IIC_1: PB6 -- SCL; PB7 -- SDAIIC_1(重映射):PB8 -- SCL; PB9 -- SDAIIC_2:
*****************************************************************************/
void I2C_Configuration(void)
{GPIO_InitTypeDef  GPIO_InitStructure;/*    重映射开启AFIO时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE); //重映射 IIC/* 重映射引脚   使用IIC_1  PB8 -- SCL; PB9 -- SDA     */GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 | GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;    //I2C必须开漏输出GPIO_Init(GPIOB, &GPIO_InitStructure);I2C_InitTypeDef  I2C_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);I2C_DeInit(I2C1);    //使用I2C1I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;         //选择IIC模式I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;    //占空比 1/2I2C_InitStructure.I2C_OwnAddress1 = 0x30;         //主机的I2C地址I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;          //应答信号使能I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;  //IIC 7 位寻址I2C_InitStructure.I2C_ClockSpeed = 100000;          //设置最大400KI2C_Cmd(I2C1, ENABLE);                //使能IIC1I2C_Init(I2C1, &I2C_InitStructure); //初始化 IIC_1 相关}/****************************************************************************
**  函数名称:BH1750_WriteByte()
**  函数功能:BH1750 写数据
**  参数说明:
**          uint8_t addr: 寄存器地址
**
**  返回值:无
**  IIC函数说明:
**              I2C_GetFlagStatus(IIC_x, IIC_Flag_x)-- 检查标志位是否置 1
**
*****************************************************************************/
void BH1750_WriteByte(uint8_t addr)
{/* 先判断总线是否忙  */while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));/* 发送Start信号,切换到主模式(M/SL 位置 1) */I2C_GenerateSTART(I2C1, ENABLE);/* 等待EV5事件,IIC开始信号已经发出 */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/* 发送器件地址,发送方向: I2C_Direction_Transmitter */I2C_Send7bitAddress(I2C1, (BH1750_Addr_GND_REG<<1|0), I2C_Direction_Transmitter);/*  等待EV6事件:表示地址已经发送  */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));/*  发送操作的寄存器地址  */I2C_SendData(I2C1, addr);/*   等待EV8事件:数据寄存器DR为空,地址数据已经发送   */while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));/*  产生应答信号  */I2C_AcknowledgeConfig(I2C1, ENABLE);I2C_GenerateSTOP(I2C1, ENABLE);//产生停止信号,关闭I2C1总线
}/****************************************************************************
**  函数名称:BH1750_Read_Data()
**  函数功能:BH1750 读取数据
**  参数说明:
**          uint8_t addr :寄存器地址
**
**  返回值:RX_Data
**  IIC函数说明:
**              I2C_GetFlagStatus(IIC_x, IIC_Flag_x)-- 检查标志位是否置 1
**
*****************************************************************************/
uint16_t BH1750_Read_Data(void)
{uint8_t    H_Data;                         //高 8 位数据uint8_t    L_Data;                         //低 8 位 数据uint16_t  Rx_Data;                        //完整 16 位数据while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));                   /* 先判断总线是否忙 */I2C_GenerateSTART(I2C1, ENABLE);                              /* 发送Start信号,切换到主模式  */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));      /* 等待EV5事件,IIC开始信号已经发出 *//* 发送读地址指令,发送方向: I2C_Direction_Receiver */I2C_Send7bitAddress(I2C1, BH1750_Addr_GND_REG<<1|1, I2C_Direction_Receiver);/* 等待EV6事件:地址已发送 (接收类型)  */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));I2C_AcknowledgeConfig(I2C1, ENABLE);                           /*  产生应答信号  */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));     /* 等待EV7事件 */H_Data = I2C_ReceiveData(I2C1);                                   /* 读取高8位数据  */I2C_AcknowledgeConfig(I2C1, ENABLE);                          /* 产生应答信号 */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));   /*  等待EV7事件 *//* 与高8位合成16位完整数据 */L_Data = I2C_ReceiveData(I2C1);                                   /* 读取低8位 */I2C_AcknowledgeConfig(I2C1, DISABLE);                            /*  产生非应答信号 */I2C_GenerateSTOP(I2C1, ENABLE);                                   /** 发送停止信号  **/Rx_Data = ((uint16_t)H_Data << 8) + L_Data;                      /* 16位数据合成 */return RX_Data;
}/**    BH1750上电 **/
void BH1750_Power_ON(void)
{BH1750_WriteByte(BH1750_Power_ON_REG);
}/**    BH1750断电 **/
void BH1750_Power_OFF(void)
{BH1750_WriteByte(BH1750_Power_OFF_REG);
}/**    BH1750数据寄存器复位 **/
void BH1750_RESET(void)
{BH1750_WriteByte(BH1750_MODULE_RESET_REG);
}/**    BH1750初始化 **/
void BH1750_Init(void)
{I2C_Configuration();delay_ms(100);BH1750_Power_OFF();BH1750_Power_ON();BH1750_RESET();BH1750_WriteByte(BH1750_CONTINUE_H_MODE2);
}/**    获取光照强度 **/
/** 分辨率 光照强度(单位lx)=(High Byte + Low Byte)/ 1.2  **/
float Light_Intensity(void)
{return (float)(BH1750_Read_Data() / 1.2f );
}/*************************************END***********************************************/

BH1750.h

#ifndef __BH1750_H
#define __BH1750_H#include "stm32f10x.h"
#include "delay.h"/*  器件地址(7位-用左移1位-最后1位为读写位--1为读-0为写) */
#define             BH1750_Addr_GND_REG             0X23    //ADDR引脚接低电平
#define             BH1750_Addr_VCC_REG             0X5C    //ADDR引脚接高电平/****** 指令集宏定义*****/
#define             BH1750_Power_OFF_REG            0x00    //断电指令
#define             BH1750_Power_ON_REG             0x01    //通电,等待测量命令
#define             BH1750_MODULE_RESET_REG         0x07    //重置数据寄存器,关机模式下,不能接受重置命令/*************************************************   不同模式下分辨率不同(也即精度不同)高分辨率模式2:分辨率是0.5lx高分辨率模式:分辨率1lx低分辨率模式:分辨率4lx不同模式只是精度不一样,对于计算没有区别
***************************************************//** 工作模式指令集 **/
#define             BH1750_CONTINUE_H_MODE          0x10    //连续H分辨率模式
#define             BH1750_CONTINUE_H_MODE2         0x11    //连续H分辨率模式2
#define             BH1750_CONTINUE_L_MODE          0x13    //连续L分辨率模式
#define             BH1750_ONE_TIME_H_MODE          0x20    //一次H分辨率模式
#define             BH1750_ONE_TIME_H_MODE2         0x21    //一次H分辨率模式2
#define             BH1750_ONE_TIME_L_MODE          0x23    //一次性L分辨率模式/**      函数声明区   **/
void        I2C_Configuration               (void);
void        BH1750_WriteByte                (uint8_t addr);
uint16_t    BH1750_Read_Data                (void);
void        BH1750_Power_ON                 (void);
void        BH1750_Power_OFF                (void);
void        BH1750_RESET                    (void);
void        BH1750_Init                     (void);
float       Light_Intensity                 (void);#endif

4.1.2 适用STM32F103系列的软件IIC驱动 ( BH1750.h 头文件基本一样)

BH1750.c

#include "BH1750.h"/****************************************************************************
**  函数名称:BH1750_WriteByte()
**  函数功能:BH1750 写数据
**  参数说明:
**          uint8_t addr: 寄存器地址
**
**  返回值:无
**  IIC函数说明:
**              I2C_GetFlagStatus(IIC_x, IIC_Flag_x)-- 检查标志位是否置 1
**
*****************************************************************************/
void BH1750_WriteByte(uint8_t addr)
{   IIC_Start();                                // 1.发送起始信号IIC_Send_Byte(BH1750_Addr_GND_REG << 1|0); // 2.发送7位地址与读写位(0:写)while(!IIC_Wait_Ack());                        // 3.等待从机应答信号IIC_Send_Byte(addr);                       // 4.发送8位操作指令while(!IIC_Wait_Ack());                        // 5.等待从机应答信号IIC_Stop();                                    // 6.发送停止信号
}/****************************************************************************
**  函数名称:BH1750_Read_Data()
**  函数功能:BH1750 读取数据
**  参数说明:
**          uint8_t addr :寄存器地址
**
**  返回值:RX_Data
**  IIC函数说明:
**              I2C_GetFlagStatus(IIC_x, IIC_Flag_x)-- 检查标志位是否置 1
**
*****************************************************************************/
uint16_t BH1750_Read_Data(void)
{uint8_t    H_Data;                         //高 8 位数据uint8_t    L_Data;                         //低 8 位 数据uint16_t  Rx_Data;                        //完整 16 位数据IIC_Start();                             // 1.发送起始信号IIC_Send_Byte(BH1750_Addr_GND_REG << 1|1); // 2.发送7位地址与读写位(1:读)while(!IIC_Wait_Ack());                        // 3.等待从机应答信号H_Data = IIC_Read_Byte(1);                    // 4.读取高八位并发送ACKL_Data = IIC_Read_Byte(0);                 // 5.读取低八位并发送NACKIIC_Stop();                                    // 6.发送停止信号Rx_Data = ((uint16_t)H_Data << 8) + L_Data;  // 7.16位数据合成return Rx_Data;                             // 8.返回读取数据
}/**    BH1750上电 **/
void BH1750_Power_ON(void)
{BH1750_WriteByte(BH1750_Power_ON_REG);
}/**    BH1750断电 **/
void BH1750_Power_OFF(void)
{BH1750_WriteByte(BH1750_Power_OFF_REG);
}/**    BH1750数据寄存器复位 **/
void BH1750_RESET(void)
{BH1750_WriteByte(BH1750_MODULE_RESET_REG);
}/**    BH1750初始化 **/
void BH1750_Init(void)
{IIC_Init();delay_ms(100);BH1750_Power_OFF();BH1750_Power_ON();BH1750_RESET();BH1750_WriteByte(BH1750_CONTINUE_H_MODE2);
}/**
**  获取光照强度
**  分辨率 光照强度(单位lx)=(High Byte + Low Byte)/ 1.2
**/
float Light_Intensity(void)
{return (float)(BH1750_Read_Data() / 1.2f );
}/*************************************END***********************************************/

头文件基本一样,只需要导入软件模拟 IIC 的头文件就行,(#include "IIC.h"),工程导入模拟IIC.c文件

IIC.c

#include "IIC.h"/**
*   函数说明:软件模拟 IIC
*
*   函数功能:GPIO 初始化
*
*   注意事项:GPIO 可自行选择
*
*   记录:  GPIO 引脚初始化,相同的归
*           属GPIOX尽量放同一语句中;
**/
void IIC_Init(void)
{                        GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;    //SCL & SDAGPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ;       //推挽/开漏GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;       //速度 10 MHzGPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);                 //PB6,PB7 输出高
}/**
*   函数说明:产生IIC起始信号
*
*   原理说明:    当 SCL 是高电平状态时,
*               数据线 SDA 由高拉低;
**/
void IIC_Start(void)
{SDA_OUT();     /* SDA 线输出模式 */IIC_SDA = 1;    /* 先拉高 SDA 状态 */IIC_SCL = 1;   /* 再拉高 SCL 状态 */IIC_Delay();    /* 延时保持电平状态 */IIC_SDA = 0; /* 后拉低 SDA 状态 */IIC_Delay();    /* 延时保持电平状态 */IIC_SCL = 0; /* 钳住I2C,发送或接收 */
}/**
*   函数说明:产生IIC停止信号
*
*   原理说明:    SCL线为高电平状态时, SDA 线
*               由低电平向高电平跳变(上升沿)
**/
void IIC_Stop(void)
{SDA_OUT();     /* SDA 线输出模式 */IIC_SCL = 0;    /* 先拉低 SCL 状态 */IIC_SDA = 0;   /* 先拉低 SDA 状态 */IIC_Delay();    /* 延时保持电平状态 */IIC_SCL = 1; /* 后拉高 SCL 状态 */IIC_SDA = 1;   /* 后拉高 SDA 状态 */IIC_Delay();    /* 延时保持电平状态 */
}/**
*   函数说明:等待应答信号到来
*
*   原理说明:    先将数据线拉高,延时等待稳定,然后将时钟线拉高,
*               延时等待稳定,最后采样数据线电平状态,如果是高
*               电平,未应答,如果是低电平,应答;
*
*   返回值:0, 接收应答失败
*           1, 接收应答成功
**/
uint8_t IIC_Wait_Ack(void)
{uint16_t ErrorTime;SDA_IN();               /** SDA 线输入模式 **/IIC_SDA = 1;          /* 先拉高 SDA 状态 */IIC_Delay();            /* 延时保持电平状态 */IIC_SCL = 1;         /* 后拉高 SCL 状态 */IIC_Delay();            /* 延时保持电平状态 */while(Read_SDA)           /* 采样 SDA 电平状态 */{ErrorTime ++;if(ErrorTime > 250){IIC_Stop();     /* 非应答,结束通信 */return 0;}}IIC_SCL = 0;          /** 钳住,等待发或收 **/return 1;               /** 接收到应答信号 **/
}/**
*   函数说明:产生 ACK 应答
*
*   原理说明:SCL 在高电平期间 SDA 始终处于低电平
*            (SCL 保持时间 <= SDA 保持时间)
*             需要在传输完毕一个字节后发送
*
**/
void IIC_Ack(void)
{SDA_OUT();                 /** SDA 线输出模式 **/IIC_SCL = 0;              /* 时钟线 SCL 拉低 */IIC_SDA = 0;               /* 数据线 SDA 拉低 */IIC_Delay();                /* 延时保持电平状态 */IIC_SCL = 1;             /* 时钟线 SCL 拉高 */IIC_Delay();                /* 延时保持电平状态 */IIC_SCL = 0;             /* 时钟线 SCL 拉低 */
}/**
*   函数说明:产生 NACK 应答
*
*   原理说明:SCL在高电平期间SDA始终处于高电平
*            (SCL 保持时间 <= SDA 保持时间)
*             需要在传输完毕一个字节后发送
*
**/
void IIC_NAck(void)
{SDA_OUT();                 /** SDA 线输出模式 **/IIC_SCL = 0;              /* 数据线 SCL 拉低 */IIC_SDA = 1;               /* 数据线 SDA 拉高 */IIC_Delay();                /* 延时保持电平状态 */IIC_SCL = 1;             /* 时钟线 SCL 拉高 */IIC_Delay();                /* 延时保持电平状态 */IIC_SCL = 0;             /* 时钟线 SCL 拉低 */
}/**
*   函数功能:IIC发送一个字节
*   参数说明:Txd 无符号 8 位
*
*   返回值:1, 有应答
*           0, 无应答
**/
void IIC_Send_Byte(uint8_t Txd)
{uint8_t T;SDA_OUT();                       /** 数据线SDA输出态 **/IIC_SCL = 0;                  /** 时钟线 SCL 拉低 **/for(T = 0; T < 8; T++)          /** 由高到低发送数据 */{IIC_SDA = (Txd & 0x80) >> 7;/** 每次发送最高位 **/Txd <<= 1;                 /* 更新数据的最高位 */IIC_Delay();              /* 延时保持电平状态 */IIC_SCL = 1;             /* 时钟线 SCL 拉高 */IIC_Delay();                /* 延时保持电平状态 */IIC_SCL = 0;             /* 时钟线 SCL 拉低 */IIC_Delay();                /* 延时保持电平状态 */}
}/** 函数功能:IIC读字节* 参数说明:ack = 1, 发送ACK*            ack = 0, 发送NACK** 返回值:返回读取到的一个字节*/
uint8_t IIC_Read_Byte(uint8_t ACK)
{uint8_t    T;uint8_t   Receive;SDA_IN();               /** SDA 线设置为输入 **/for(T = 0; T < 8; T++ ) /** 由高到低接收数据**/{IIC_SCL = 0;       /* 时钟线拉低的时候,SDA才允许变化 */IIC_Delay();     /* 延时保持电平状态 */IIC_SCL = 1;     /* 拉高时钟线,不允许SDA变化,可以读取 SDA */Receive <<= 1;      /** 接收到数据位左移 **/if(Read_SDA){Receive++;       /** 高电平,则最低位为1 **/}IIC_Delay();     /* 延时保持电平状态 */}if (!ACK)    IIC_NAck();         /** 发送 NACK **/else     IIC_Ack();          /** 发送  ACK **/return Receive;
}

IIC.h

#ifndef __IIC_H
#define __IIC_H#include "stm32f10x.h"
#include "delay.h"
#include "sys.h" /*********************************
**  引脚选择:                    **
**          SCL ---> PXx     **
**          SDA ---> PXx     **
**********************************//*******************************保持时间***********************************/
#define  IIC_Delay()        {   delay_us(5);    }              /*************************** IO方向设置(GPIOx * 4) ****************************//**      PXx 上拉输入模式      **/
#define  SDA_IN()  {GPIOB -> CRL &= 0X0FFFFFFF; GPIOB -> CRL |= (u32)8 << 28;}/**     PXx 推挽输出模式      **/
#define  SDA_OUT() {GPIOB -> CRL &= 0X0FFFFFFF; GPIOB -> CRL |= (u32)3 << 28;}/*************************** IO操作函数 *************************/
#define         IIC_SCL         PBout(6)    //SCL 输出
#define         IIC_SDA         PBout(7)    //SDA 输出
#define         Read_SDA        PBin (7)    //SDA 输入/***************************** IIC所有操作函数 **********************************/void                IIC_Init                (void);             //初始化IIC的IO口
void                IIC_Start               (void);             //发送IIC开始信号
void                IIC_Stop                (void);             //发送IIC停止信号
void                IIC_Send_Byte           (uint8_t Txd);      //IIC发送一个字节
uint8_t             IIC_Read_Byte           (uint8_t ACK);      //IIC读取一个字节
uint8_t             IIC_Wait_Ack            (void);             //IIC等待ACK信号
void                IIC_Ack                 (void);             //IIC发送ACK信号
void                IIC_NAck                (void);             //IIC不发送ACK信号#endif

4.2 STM32F4系列的大同小异,只是硬件IO驱动函数不太一样而已

需要改动的就只有两个函数:I2C_Configuration() 和 IIC_Init() ;头文件也需要改的一点;

/********************************** BH1750.c 改动 ***************************************/void I2C_Configuration(void)
{GPIO_InitTypeDef  GPIO_InitStructure;I2C_InitTypeDef  I2C_InitStructure;RCC_AHB1PeriphClockCmd(BH1750_GPIO_CLOCK, ENABLE);     /*使能 GPIOB 时钟*/RCC_APB1PeriphClockCmd(BH1750_IIC_CLOCK, ENABLE);        /*使能 IIC_x 时钟*//* STM32F401CCU6芯片的硬件I2C1: I2C1:PB6 -- SCL  PB7 -- SDAI2C1:PB8 -- SCL     PB9 -- SDA I2C2:PB10 --SCL  PB3 -- SDA I2C3:PA8 ---SCL  PB4 -- SDA**/GPIO_InitStructure.GPIO_Pin =  BH1750_SCL | BH1750_SDA;  //IIC引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //高速模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;         //复用模式GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;           //开漏输出GPIO_Init(BH1750_GPIOx, &GPIO_InitStructure);/**  连接 AFx,这里必须要开启引脚重映射 **///GPIO_PinAFConfig(BH1750_GPIOx, GPIO_PinSource8, GPIO_AF_I2C1);//GPIO_PinAFConfig(BH1750_GPIOx, GPIO_PinSource9, GPIO_AF_I2C1);GPIO_PinAFConfig(BH1750_GPIOx, GPIO_PinSource6, GPIO_AF_I2C1);GPIO_PinAFConfig(BH1750_GPIOx, GPIO_PinSource7, GPIO_AF_I2C1);I2C_DeInit(BH1750_IIC);                              //使用I2CxI2C_InitStructure.I2C_Mode = I2C_Mode_I2C;         //选择IIC模式I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;    //占空比 1/2I2C_InitStructure.I2C_OwnAddress1 = 0x30;         //主机的I2C地址,随便写的I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;         //应答信号使能I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;  //IIC 7 位寻址I2C_InitStructure.I2C_ClockSpeed = 10000;           //设置最大400KI2C_Cmd(BH1750_IIC, ENABLE);                      //使能IICI2C_Init(BH1750_IIC, &I2C_InitStructure);            //初始化 IIC 相关}

头文件(.h文件)改动

/********************************** BH1750.h 改动 ***************************************/
/************************************硬件使用到的相关************************************/
#define             BH1750_GPIOx                    GPIOB                   // GPIOx
#define             BH1750_GPIO_CLOCK               RCC_AHB1Periph_GPIOB    //GPIOx_CLOCK
#define             BH1750_IIC_CLOCK                RCC_APB1Periph_I2C1     // IIC_CLOCK
#define             BH1750_SCL                      GPIO_Pin_6              // GPIO_SCL
#define             BH1750_SDA                      GPIO_Pin_7              // GPIO_SDA
#define             BH1750_IIC                      I2C1                    // IIC_X

软件IIC模拟改动

/************************************ IIC.c 改动 ****************************************/
void IIC_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);/**  自定义 GPIO 初始化**/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;    //SCL&&SDAGPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                //普通输出GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;               //开漏输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;         //设置2MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;               //引脚上拉GPIO_Init(GPIOB, &GPIO_InitStructure);                        //初始化IOIIC_SCL = 1;                                                //上拉 SCL IIC_SDA = 1;                                              //上拉 SDA
}
/************************************ IIC.h 改动 ****************************************/
/*********************************
**  引脚选择:                    **
**          SCL ---> PXx     **
**          SDA ---> PXx     **
**********************************//************************* IO方向设置(GPIOx * 2) ****************************//**        PXx输入模式     **/
#define SDA_IN()  {GPIOB -> MODER &=~(3 << (13*2));GPIOB -> MODER |= 0 << 13*2;}
/**     PXx输出模式     **/
#define SDA_OUT() {GPIOB -> MODER &=~(3 << (13*2));GPIOB -> MODER |= 1 << 13*2;}/*************************** IO操作函数 *************************/
#define     IIC_SCL             PBout(12)           //SCL 输出
#define     IIC_SDA             PBout(13)           //SDA 输出
#define     Read_SDA            PBin (13)           //SDA 输入

5.搭配主函数与串口函数打印,结果如下:

int main(void)
{SystemInit();              //系统初始化delay_init();                //延时初始USART1_init(115200);      //初始化串口波特率为115200BH1750_Init();             // BH1750初始化printf("Test\r\n");while (1){printf("光照强度:%f\r\n",Light_Intensity());delay_ms(500);}
}


结果不稳定是因为为了演示效果,我一直在晃动模块,调整角度。

有问题的可以私信或者留言评论区,想要工程代码可以留联系邮箱,我发一份就好了

STM32 驱动 GY-302 光照传感器 BH1750 模块(软件IIC与硬件IIC驱动)相关推荐

  1. 联盛德 HLK-W806 (十一): 软件SPI和硬件SPI驱动ST7567液晶LCD

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

  2. 联盛德 HLK-W806 (九): 软件SPI和硬件SPI驱动ST7789V液晶LCD

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

  3. BH1750 光照传感器文档详解 及 驱动设计

    前言 最近接触到一个应用,需要在低功耗的产品上加上光照度采集,正好最近有接触到一款光照传感器 BH1750 ,性能价格都合适,那么今天就抽空来好好测试一下. 那么要写一篇测试文章,我会尽量以新手的角度 ...

  4. STM32使用IIC总线通讯协议在OLED屏幕上显示字符串、汉字、图像(硬件IIC)

    参考:基于STM32-Oled(IIC)的使用 作者:奋斗的小殷 发布时间: 2021-05-07 13:09:26 网址:https://blog.csdn.net/boybs/article/de ...

  5. ubuntu下在软件和更新的附加驱动处安装NVIDIA显卡驱动无法安装,应用更改不了,没反应

    一.卸载已经安装的驱动 sudo apt-get remove nvidia-* 然后重新在软件和更新的附加驱动处安装nvidia驱动

  6. STM32驱动BH1750模块

    模块描述 BH1750FVI是一款用于I2C总线接口的数字环境光传感器IC.该集成电路最适合获取环境光数据,用于调整手机的 LCD和键盘背光功率.可以在高分辨率下检测宽范围(1-65535 lx) 引 ...

  7. 树莓派光照传感器java_树莓派上使用光照强度检测(BH1750)传感器

    BH1750FVI 是一款 IIC 接口的数字型光强度传感器集成电路.下面介绍一下其在树莓派下的用法. 一.前期准备 1.环境要求 GY30模块(BH1750FVI传感器) 树莓派 Raspbian ...

  8. BH1750( GY-302 )光照传感器

    文章目录 一.产品简介 二.IIC通信 三.BH1750的使用 四.程序源码 这里我先简单的介绍一下BH1750光照传感器模块的基本信息(不多废话),我将着重讲解它的使用部分,相信对于屏幕前的你也是更 ...

  9. STM32驱动ADXL345三轴传感器

    简介:STM32F103C8T6驱动ADXL345三轴倾斜度传感器源码介绍. 开发平台:KEIL ARM MCU型号:STM32F103C8T6 传感器型号:ADXL345 特别提示:驱动内可能使用了 ...

最新文章

  1. 单价数量和总价的公式_人教版四年级数学上册单价、数量和总价之间的关系微课...
  2. java 接口初始化_Java类的初始化 | 学步园
  3. 在RH6.5上安装sublime3 build3103步骤
  4. mysql数据库d导出数据_mysql数据库导入导出文件
  5. easyui下datagrid列单独赋值
  6. WCF BasicHttpBinding 安全解析(3)默认安全设置(IIS宿主)
  7. django-celery beat报错 error pid
  8. 一步一步使用标c编写跨平台图像处理库_让一个图像变成反向图像
  9. 数据库事务(Transaction)详解
  10. 95%的人都会答错的类加载的问题
  11. 基线_读心术基础(四) 什么是基线
  12. Deepin-TIM或Deepin-QQ调整界面DPI字体大小的方法
  13. amazing,盗走女友微信后,竟在微信号里看见了……
  14. 创建数据表与修改数据表
  15. 富文本编辑器实现导入word
  16. 姓莫的女孩子叫什么名字好听
  17. C#嵌入IronPython脚本示例(hello world)
  18. 如何构建一个成功的期权交易系统?
  19. CH340晶体不起振
  20. 传世服务器上怎么修改升级经验,传世各级升级需要的经验

热门文章

  1. OOM和JVM最详细介绍
  2. MySQL:偏移量为 0x000000000ae000 的位置执行 读取 期间,操作系统已经向 SQL Server 返回了错误 21(设备未就绪。)。
  3. 《linux基础》实验2:基本概念及操作
  4. 频谱、能谱、功率谱、倍频程谱、1/3 倍频程谱
  5. [svn] TortoisSVN的Blam功能
  6. 安徽省太和一中2021高考成绩查询分数,2021届安徽省太和一中高三物理高考二模试题 Word版含答案...
  7. windows系统服务器巡检仪哪个工具,机械振动巡检仪功能概述
  8. MATLAB 郭彦甫 第十四课练习答案
  9. 计算机基础知识填空题和选择题,计算机基础知识题库选择题(参考).doc
  10. HTML5 body设置全屏背景图片 如何让body的背景图片自适应整个屏----实战经验 1