STM32硬件接口I2C应用(基于BH1750)

目录

概述

[1 STM32Cube控制配置I2C](#1 STM32Cube控制配置I2C)

[1.1 I2C参数配置](#1.1 I2C参数配置)

[1.2 使用STM32Cube产生工程](#1.2 使用STM32Cube产生工程)

[2 HAL库函数介绍](#2 HAL库函数介绍)

[2.1 初始化函数](#2.1 初始化函数)

[2.2 写数据函数](#2.2 写数据函数)

[2.3 读数据函数](#2.3 读数据函数)

[3 光照传感器BH1750](#3 光照传感器BH1750)

[3.1 认识BH1750](#3.1 认识BH1750)

[3.2 BH1750寄存器](#3.2 BH1750寄存器)

[3.3 采集数据流程](#3.3 采集数据流程)

[4 BH1750驱动实现](#4 BH1750驱动实现)

[4.1 接口函数实现](#4.1 接口函数实现)

[4.2 完整驱动代码](#4.2 完整驱动代码)

[5 测试](#5 测试)

[6 逻辑分析仪捕捉波形](#6 逻辑分析仪捕捉波形)


测试代码下载地址:

bash 复制代码
https://gitee.com/mftang/stm32_open_test_proj/tree/master/stm32_f407_proj

概述

本文主要介绍STM32F4的内部I2C接口的使用方法,包括使用STM32Cube配置i2c接口函数,还介绍了STM32 HAL库中的接口函数,为了验证接口函数的是否能够正常工作,还使用bh1750作为device,以I2C接口作为通信接口,以实现该芯片数据的读写操作。

1 STM32Cube控制配置I2C

STM32CubeMX 版本: 6.11

HAL库版本: STM32Cube_FW_F4_V1.27.1

1.1 I2C参数配置

STM32F407 的标准I2C接口最大支持100K工作频率,笔者选择最大工作频100k,以配置I2C的参数。

I2C使用的GPIO接口如下:

使用MCU类型和HAL库的版本

1.2 使用STM32Cube产生工程

在配置完成项目后,点击GENERATE生成项目,打开项目后项目目录如下,和I2C相关的代码如下:

代码第40行:选择I2C2作为硬件接口

代码第41行:I2C通信速率为100K

代码第44行:定义地址位7bit

2 HAL库函数介绍

STM32 HAL库函数数量很多,本文仅介绍笔者使用的一些函数接口。其他函数在使用的时候在具体研究,而不许把每个函数搞清楚才去应用。

2.1 初始化函数

函数原型:

cpp 复制代码
HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);

参数介绍

hi2c: 指向I2C_HandleTypeDef结构体的指针,该结构体包含指定I2C的配置信息。

一个使用案例: 如果已经初始化完成hi2c结构,初始化时,直接调用该结构体即可。

2.2 写数据函数

函数原型:

cpp 复制代码
HAL_StatusTypeDef HAL_I2C_Master_Transmit(  I2C_HandleTypeDef *hi2c, 
                                            uint16_t DevAddress, 
                                            uint8_t *pData, 
                                            uint16_t Size, 
                                            uint32_t Timeout)

参数介绍:

hi2c: 指向I2C_HandleTypeDef结构体的指针,该结构体包含指定I2C的配置信息。

DevAddress: 目标设备地址:设备的7位地址值在调用接口之前,必须将数据表向左移动

pData: 写数据指针

Size: 写数据大小

Timeout: 写数据超时时间

2.3 读数据函数

函数原型:

cpp 复制代码
HAL_StatusTypeDef HAL_I2C_Master_Receive( I2C_HandleTypeDef *hi2c, 
                                          uint16_t DevAddress, 
                                          uint8_t *pData, 
                                          uint16_t Size, 
                                          uint32_t Timeout)

参数介绍:

hi2c: 指向I2C_HandleTypeDef结构体的指针,该结构体包含指定I2C的配置信息。

DevAddress: 目标设备地址:设备的7位地址值在调用接口之前,必须将数据表向左移动

pData: 读数据指针

Size: 读数据大小

Timeout: 读数据超时时间

3 光照传感器BH1750

3.1 认识BH1750

光照传感器BH1750是一种高性能数字光照传感器。它采用I2C总线通信接口,可测量环境中的光照强度,并输出数字信号。BH1750传感器具有高分辨率、高灵敏度和宽动态范围的特点,能够适应不同亮度条件下的测量需求。

BH1750传感器具有两种工作模式:连续测量模式和单次测量模式。在连续测量模式下,传感器会以设定的时间间隔进行光照强度的测量,并将结果输出。而在单次测量模式下,传感器进行一次测量后便停止,并将结果输出。用户可以根据实际需求选择适合的工作模式。

BH1750传感器还具有灵敏度调节功能,可以根据环境的亮度调整传感器的灵敏度,以确保测量结果的准确性。

光照传感器BH1750广泛应用于室内照明控制、户外光照强度监测、智能电子设备的自适应亮度调节等领域。它能够帮助节能减排、提升用户体验、增加设备智能化程度。

3.2 BH1750寄存器

3.3 采集数据流程

4 BH1750驱动实现

4.1 接口函数实现

1)写寄存器函数

代码第26行: 调用master发送数据至slave函数

2)读寄存器函数

代码第37行: 调用master读数据函数

3)修改模式函数

4)设置精度函数

4.2 完整驱动代码

1)创建bh1750.c文件,编写如下代码:

cpp 复制代码
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name            : bh1750.c
* Description          : I2C drive based on STM32F4
* STM32 HAL library ver: STM32Cube_FW_F4_V1.27.1
* 
******************************************************************************
* @attention
*
* Copyright (c) 2024~2029 mingfei.tang
* All rights reserved.
*
*************************************************************************
*/
/* USER CODE END Header */
#include "bh1750.h"

static uint8_t s_MTReg;    /* 灵敏度倍率 */
static uint8_t s_Mode;     /* 测量模式 */

static uint8_t bh1750_WeReg(  uint8_t *pData, uint16_t Size )
{
    HAL_StatusTypeDef status;
    
    status = HAL_I2C_Master_Transmit( &hi2c2, BH1750_SLAVE_ADDRESS, pData, Size, 1000);
    if( status == HAL_OK)
        return BH1750_OK;
    else
        return BH1750_ERROR; 
}

static uint8_t bh1750_RdReg( uint8_t *pData, uint16_t Size )
{
    HAL_StatusTypeDef status;
    
    status = HAL_I2C_Master_Receive( &hi2c2, BH1750_SLAVE_ADDRESS, pData, Size, 1000);
    if( status == HAL_OK)
        return BH1750_OK;
    else
        return BH1750_ERROR; 
}

void BH1750_ChageMode(uint8_t _ucMode)
{
    uint8_t cmd;
    
    if (_ucMode == 1)           /* 连续高分测量模式1 */
    {
        cmd = BHOP_CON_H_RES;
        bh1750_WeReg(&cmd, 1);    
        s_Mode = 1;             /* 测量模式1,分辨率 1 lux*/
    }
    else if (_ucMode == 2)      /* 连续高分测量模式2 */
    {
        cmd = BHOP_CON_H_RES2;
        bh1750_WeReg(&cmd, 1);  
        s_Mode = 2;             /* 测量模式2, 分辨率 0.5 lux */        
    }
    else if (_ucMode == 3)     /* 连续低分测量模式 */
    {
        cmd = BHOP_CON_L_RES;
        bh1750_WeReg(&cmd, 1);
        s_Mode = 3;            /* 测量模式3,低分辨率 4 lux*/        
    }
}

void BH1750_AdjustSensitivity(uint8_t _ucMTReg)
{
    uint8_t cmd;
    
    if (_ucMTReg <= 31)
    {
        _ucMTReg = 31;
    }
    else if (_ucMTReg >= 254)
    {
        _ucMTReg = 254;
    }
    
    s_MTReg = _ucMTReg;
    
    cmd = 0x40 + (s_MTReg >> 5);
    bh1750_WeReg(&cmd,1);            /* 更改高3bit */
    
    cmd = 0x60 + (s_MTReg & 0x1F);
    bh1750_WeReg(&cmd,1);            /* 更改低5bit */
    
    /* 更改量程范围后,需要重新发送命令设置测量模式 */
    BH1750_ChageMode(s_Mode);
}

uint16_t BH1750_ReadData(void)
{
    uint8_t buff[2];

    bh1750_RdReg( buff, 2);
    return (buff[0] << 8) + buff[1];
}

float BH1750_GetLux(void)
{
    uint16_t usLight;
    float lux;
    
    usLight = BH1750_ReadData();
    
    /* 
       计算光强度 = 16位寄存器值 / 1.2  * (69 / X) 
    */
    lux = (float)(usLight * 5 * 69) / (6 * s_MTReg);
    
    if (s_Mode == 2)    /* 高分辨率测量模式2 */
    {
        lux = lux / 2;
    }
    
    return lux;
}

void bh1750_test( void )
{
    uint8_t cmd;
    float fLux;
    
    cmd = BHOP_POWER_ON;            /* 芯片上电 */
    bh1750_WeReg(&cmd, 1); 
    
    BH1750_ChageMode(2);             /* 高分辨率连续测量 */

    BH1750_AdjustSensitivity(69);    /* 芯片缺省灵敏度倍率 = 69 */

    while(1)
    {
        fLux = BH1750_GetLux();
        printf("Ambient Light = %6.2f lux  \r",fLux);
        HAL_Delay(100);
    }
}



/* End of this file */

2)创建bh1750.h文件,编写如下代码:

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : bh1750.h
  * Description        : I2C drive based on STM32F4
  * 
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024~2029 mingfei.tang
  * All rights reserved.
  *
  *************************************************************************
  */
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __BH1750_H
#define __BH1750_H

#ifdef __cplusplus
 extern "C" {
#endif

#include "stdio.h"
#include "main.h"

#define BH1750_OK                1
#define BH1750_ERROR             0


#define bsp_DelayMS             HAL_Delay
#define BH1750_SLAVE_ADDRESS    0x46        /* I2C从机地址 */

/* 操作码 Opercode 定义 */
enum
{
    BHOP_POWER_DOWN = 0x00,        /* 进入掉电模式。芯片上电后缺省就是PowerDown模式 */
    BHOP_POWER_ON   = 0x01,        /* 上电,等待测量命令 */
    BHOP_RESET      = 0x07,        /* 清零数据寄存器 (Power Down 模式无效) */
    BHOP_CON_H_RES  = 0x10,        /* 连续高分辨率测量模式  (测量时间 120ms) (最大 180ms)*/
    BHOP_CON_H_RES2 = 0x11,        /* 连续高分辨率测量模式2 (测量时间 120ms)*/
    BHOP_CON_L_RES  = 0x13,        /* 连续低分辨率测量模式 (测量时间 16ms)*/

    BHOP_ONE_H_RES  = 0x20,        /* 单次高分辨率测量模式 , 之后自动进入Power Down */
    BHOP_ONE_H_RES2 = 0x21,        /* 单次高分辨率测量模式2 , 之后自动进入Power Down  */
    BHOP_ONE_L_RES  = 0x23,        /* 单次低分辨率测量模式 , 之后自动进入Power Down  */
};

void bh1750_test( void );

#ifdef __cplusplus
}
#endif

#endif /*__BH1750_H */

5 测试

1)编写测试代码

cpp 复制代码
void bh1750_test( void )
{
    uint8_t cmd;
    float fLux;
    
    cmd = BHOP_POWER_ON;            /* 芯片上电 */
    bh1750_WeReg(&cmd, 1); 
    
    BH1750_ChageMode(2);             /* 高分辨率连续测量 */

    BH1750_AdjustSensitivity(69);    /* 芯片缺省灵敏度倍率 = 69 */

    while(1)
    {
        fLux = BH1750_GetLux();
        printf("Ambient Light = %6.2f lux  \r",fLux);
        HAL_Delay(100);
    }
}

2)编译代码,下载到板卡中,运行代码得到结果如下:

6 逻辑分析仪捕捉波形

1)读取lux值

2) 配置参数函数

相关推荐
网易独家音乐人Mike Zhou3 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
zy张起灵4 小时前
48v72v-100v转12v 10A大功率转换电源方案CSM3100SK
经验分享·嵌入式硬件·硬件工程
PegasusYu6 小时前
STM32CUBEIDE FreeRTOS操作教程(九):eventgroup事件标志组
stm32·教程·rtos·stm32cubeide·free-rtos·eventgroup·时间标志组
lantiandianzi11 小时前
基于单片机的多功能跑步机控制系统
单片机·嵌入式硬件
文弱书生65611 小时前
输出比较简介
stm32
哔哥哔特商务网11 小时前
高集成的MCU方案已成电机应用趋势?
单片机·嵌入式硬件
跟着杰哥学嵌入式11 小时前
单片机进阶硬件部分_day2_项目实践
单片机·嵌入式硬件
电子科技圈11 小时前
IAR与鸿轩科技共同推进汽车未来
科技·嵌入式硬件·mcu·汽车
东芝、铠侠总代1361006839312 小时前
浅谈TLP184小型平面光耦
单片机·嵌入式硬件·物联网·平面
lantiandianzi12 小时前
基于单片机中医药柜管理系统的设计
单片机·嵌入式硬件