目录
概述
1 STM32Cube控制配置I2C
1.1 I2C参数配置
1.2 使用STM32Cube产生工程
2 HAL库函数介绍
2.1 初始化函数
2.2 写数据函数
2.3 读数据函数
3 光照传感器BH1750
3.1 认识BH1750
3.2 BH1750寄存器
3.3 采集数据流程
4 BH1750驱动实现
4.1 接口函数实现
4.2 完整驱动代码
5 测试
6 逻辑分析仪捕捉波形
测试代码下载地址:
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 初始化函数
函数原型:
HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);
参数介绍
hi2c: 指向I2C_HandleTypeDef结构体的指针,该结构体包含指定I2C的配置信息。
一个使用案例: 如果已经初始化完成hi2c结构,初始化时,直接调用该结构体即可。
2.2 写数据函数
函数原型:
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 读数据函数
函数原型:
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文件,编写如下代码:
/* 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文件,编写如下代码:
/* 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)编写测试代码
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) 配置参数函数