STM32F103光照度测量GY-302 串口打印

  1. 硬件连接

用到的引脚宏定义

#define I2C_GPIO_CLK_ENABLE()           __HAL_RCC_GPIOG_CLK_ENABLE()//时钟
#define I2C_GPIO_PORT                   GPIOG   
#define I2C_SCL_PIN                     GPIO_PIN_15//时钟线引脚
#define I2C_SDA_PIN                     GPIO_PIN_14//双向数据线引脚

模块引脚号

名称

说明

1

VCC

供电电压源正极

2

SCL

IIC时钟线,时钟输入引脚,由MCU输出时钟

3

SDA

IIC数据线,双向IO口,用来传输数据

4

ADDR

IIC地址线,接GND时器件地址为0100011 ,接VCC时器件地址为1011100

5

GND

供电电压源负极

  1. BH1750的通讯过程

根据手册写出我流BH1750FVI通讯协议,步骤如下:

  • 在访问I2C设备前,先打开时钟配置GPIO开漏输出,调用 I2C_CheckDevice() 检测I2C设备是否正常or存在。

  • bh1750fvi初始化,过程包括发送上电+连续检测命令。

  • BH1750 读取数据,过程包括发送ST+0x47+等待模块ack信号+读取高位数据(8bit)+发送ack+读取低位数据(8bit)+发送nack+SP(注:因为我将IIC地址线接GND,所以器件地址为0100011 ,所以读数据发送0x47)

  • 最后调用函数并将结果打印出。

  • 补:写指令流程

1.发送起始信号AT

2.发送写指令地址+接收ACK信号

​ 3.发送操作指令+接收ACK信号

4.发送停止信号SP

  • 补:读指令流程:

​ 1.发送起始信号AT

2.发送读指令地址+接收ACK信号

​ 3.接收高 8 位数据+发送ACK信号)

4.接收低 8 位数据+发送NACK

​ 5.发送结束信号SP

  1. BH1750的命令

功能

寄存器地址指令

注释说明

断电

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]

更改测量时间。※请参考“调整测量结果对光学窗口的影响”。

  1. 驱动代码

IIC底层封装就不写了,用到了这些基础函数

/* 函数声明 ------------------------------------------------------------------*/
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);
void    I2C_InitGPIO(void);

BH1750封装函数bsp_bh1750fvi.c

/* 需要包含头文件 --------------------------------------------------------------*/
#include "BH1750FVI/bsp_bh1750fvi.h"
#include "IIC/bsp_iic.h"

/* 函数体 --------------------------------------------------------------------*/
uint8_t BUF[3]={0};

/**
  * @brief  I2C_CheckDevice,检测I2C设备是否正常
  * @param  无
  * @retval 无
  */
    uint8_t I2C_CheckDevice(void)
{
    uint8_t ucAck;
    I2C_Start();        /* 发送启动信号 */
    /* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7*/
    I2C_SendByte(0x46);
    ucAck = I2C_WaitAck();    /* 检测设备的ACK应答 */
 
    I2C_Stop();            /* 发送停止信号 */
 
    return ucAck;
}
 /**
  * @brief  bh1750fvi_Init,初始化向bh1750fvi发送上电+连续检测命令
  * @param  无
  * @retval 无
  */
    void bh1750fvi_Init(void)
    {
        BH1750_WriteCommand(BH1750_Power_ON_REG);         // 1.发送通电命令0x01
        BH1750_WriteCommand(BH1750_CONTINUE_H_MODE);        // 2.发送7位地址+读写位(0x10)
        HAL_Delay(120);
    }
    
    /**
  * @brief  BH1750_WriteByte,BH1750 写数据
  * @param  uint8_t addr: 寄存器地址
  * @retval 无
  */
    uint8_t BH1750_WriteCommand(uint8_t addr)
{    
    I2C_Start();                   // 1.发送起始信号
    
    I2C_SendByte(Lux_ADDR);        // 2.发送7位地址+读写位(0:写)
    if(I2C_WaitAck()==1)          //0表示正确应答,1表示无器件响应
     return 1;
    I2C_SendByte(addr);            // 3.发送8位操作指令
    if(I2C_WaitAck()==1)
     return 2;
    I2C_Stop();                    // 4.发送停止信号
     return 0;
}

/**
  * @brief  BH1750_ReadData, 一次完整的数据传输为16bit,BH1750 读取数据
  * @param  *BH1750_Data1: BH1750结构体
  * @retval ERROR:  读取出错
  *         SUCCESS:读取成功
  */
uint16_t BH1750_ReadData(BH1750_Data_TypeDef *BH1750_Data1)
{

    
     I2C_Start();                     // 1.发送起始信号
     I2C_SendByte(Read_ADDR);         // 2.发送7位地址与读写位(0x47)
     if(I2C_WaitAck()==1)            // 3.等待从机应答信号
         return 0;
     
     BUF[0] = I2C_ReadByte();        //读取高八位数据
     I2C_Ack();                      //回应ACK
     BUF[1] = I2C_ReadByte();        //读取低八位数据
     I2C_NAck();                     //最后一个数据需要回NOACK
     I2C_Stop();                     // 6.发送停止信号

     BH1750_Data1->lux_high8bit = BUF[0];
     BH1750_Data1->lux_low8bit = BUF[1];
     BH1750_Data1->AllData = BH1750_Data1->lux_high8bit*256 + BH1750_Data1->lux_low8bit;
     BH1750_Data1->illumination = (float)(BH1750_Data1->AllData/1.2);//计算实际光照值
    
     if(BH1750_Data1->illumination != 0)
    { 
      return SUCCESS;
    }
     else 
      return ERROR;

}

对应头文件bsp_bh1750fvi.h

#ifndef __BSP_BH1750FVI_H__
#define __BSP_BH1750FVI_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

/* 类型定义 ------------------------------------------------------------------*/
/************************ BH1750 数据类型定义******************************/
typedef struct
{
    uint8_t   lux_high8bit;          //原始数据:光照高8位
    uint8_t   lux_low8bit;           //原始数据:光照低8位
    uint16_t  AllData;                  //完整 16 位数据
    float     illumination;     //实际光照 
}BH1750_Data_TypeDef;

/* 宏定义 --------------------------------------------------------------------*/
#define       Lux_ADDR                        0x46  //接GND的写操作从地址
#define       Read_ADDR                       0x47  //接GND的读操作从地址
#define       BH1750_Power_OFF_REG            0x00    //断电指令
#define       BH1750_Power_ON_REG             0x01    //通电,等待测量命令

/*************************************************    
    不同模式下分辨率不同(也即精度不同)
    高分辨率模式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 bh1750fvi_Init(void);
uint8_t BH1750_WriteCommand(uint8_t addr);
uint16_t BH1750_ReadData(BH1750_Data_TypeDef *BH1750_Data1);
uint8_t I2C_CheckDevice(void);

#endif

bsp_iic.h

#ifndef    __BSP_IIC_H__// 防止bsp_iic.h被重复引用 
#define    __BSP_IIC_H__
/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

/* 类型定义 ------------------------------------------------------------------*/
/* 宏定义 --------------------------------------------------------------------*/

#define I2C_GPIO_CLK_ENABLE()               __HAL_RCC_GPIOG_CLK_ENABLE()
#define I2C_GPIO_PORT                       GPIOG                                                                                                
#define I2C_SCL_PIN                         GPIO_PIN_15
#define I2C_SDA_PIN                         GPIO_PIN_14

#define I2C_SCL_HIGH()                      HAL_GPIO_WritePin(I2C_GPIO_PORT,I2C_SCL_PIN,GPIO_PIN_SET)    // 输出高电平
#define I2C_SCL_LOW()                       HAL_GPIO_WritePin(I2C_GPIO_PORT,I2C_SCL_PIN,GPIO_PIN_RESET)  // 输出低电平
#define I2C_SDA_HIGH()                      HAL_GPIO_WritePin(I2C_GPIO_PORT,I2C_SDA_PIN,GPIO_PIN_SET)    // 输出高电平
#define I2C_SDA_LOW()                       HAL_GPIO_WritePin(I2C_GPIO_PORT,I2C_SDA_PIN,GPIO_PIN_RESET)  // 输出低电平
#define I2C_SDA_READ()                      HAL_GPIO_ReadPin(I2C_GPIO_PORT,I2C_SDA_PIN)

/* 扩展变量 ------------------------------------------------------------------*/
/* 函数声明 ------------------------------------------------------------------*/
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);
void    I2C_InitGPIO(void);

#endif /* __BSP_IIC_H__ */

main函数加入

#include "BH1750FVI/bsp_bh1750fvi.h"
#include "IIC/bsp_iic.h"
//光照传感器的结构体
BH1750_Data_TypeDef BH1750_Data1;
/* 模块初始化 */
    I2C_InitGPIO();
    if(I2C_CheckDevice()==0)
        printf("BH1750设备检测成功\r\n");
    else 
        printf("BH1750设备检测失败\r\n");
  bh1750fvi_Init();    
int main(void)
{
  /* 初始化外设 */
  InitPeri();                   //所有外设初始化
  while (1)
  {
        if(timecount==1000)     //每秒打印一次
        {
            if(BH1750_ReadData(&BH1750_Data1)==SUCCESS)
            {  
                printf("读取BH1750 %7.2f Lux \r\n",BH1750_Data1.illumination);//调试串口       
            }
            else
            {
                printf("读取BH1750信息失败\n");  
            }
            timecount=0;        
        }  
  }
}
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个简单的程序示例: ```c #include "stm32f10x.h" #include "i2c.h" #include "delay.h" #include "GY-30.h" int main(void) { uint16_t lux; // 初始化I2C总线 I2C_Configuration(); // 初始化延时函数 delay_init(); // 初始化GY-30模块 GY30_Init(); while(1) { // 读取光照强度值 lux = GY30_ReadLux(); // 延时一段时间 delay_ms(500); } } ``` 其中,`i2c.h` 和 `delay.h` 是 I2C 和延时函数的头文件,`GY-30.h` 是GY-30模块的头文件。 下面是 `GY-30.h` 的内容: ```c #ifndef __GY30_H #define __GY30_H #include "stm32f10x.h" #define GY30_ADDR 0x46 // GY-30模块的I2C地址 void GY30_Init(void); uint16_t GY30_ReadLux(void); #endif /* __GY30_H */ ``` 下面是 `GY-30.c` 的内容: ```c #include "GY-30.h" static void GY30_WriteReg(uint8_t reg, uint8_t value) { I2C_Start(); I2C_SendByte(GY30_ADDR << 1); I2C_WaitAck(); I2C_SendByte(reg); I2C_WaitAck(); I2C_SendByte(value); I2C_WaitAck(); I2C_Stop(); } static uint8_t GY30_ReadReg(uint8_t reg) { uint8_t value; I2C_Start(); I2C_SendByte(GY30_ADDR << 1); I2C_WaitAck(); I2C_SendByte(reg); I2C_WaitAck(); I2C_Start(); I2C_SendByte((GY30_ADDR << 1) | 0x01); I2C_WaitAck(); value = I2C_ReadByte(); I2C_Stop(); return value; } void GY30_Init(void) { GY30_WriteReg(0x01, 0x01); // 打开光照强度测量 GY30_WriteReg(0x10, 0x20); // 分辨率设置为1 Lux } uint16_t GY30_ReadLux(void) { uint16_t lux; uint8_t val1, val2; val1 = GY30_ReadReg(0x00); // 读取光照强度值的高八位 val2 = GY30_ReadReg(0x01); // 读取光照强度值的低八位 lux = (val1 << 8) | val2; // 合并高低八位数据 return lux; } ``` 其中,`GY30_WriteReg` 和 `GY30_ReadReg` 函数用于向GY-30模块写入和读取寄存器值,`GY30_Init` 函数用于初始化GY-30模块,`GY30_ReadLux` 函数用于读取光照强度值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值