STM32F103C8T6驱动BH1750光照传感器,从接线到数据读取的保姆级教程
2026/6/2 22:52:56 网站建设 项目流程

STM32F103C8T6驱动BH1750光照传感器实战指南

刚拿到STM32开发板和BH1750传感器时,很多初学者会面临这样的困惑:如何正确连接硬件?为什么我的代码读取不到数据?光照强度的单位lx到底代表什么?本文将用最直接的方式,带你从零开始完成整个项目。

1. 硬件连接与准备工作

1.1 认识你的硬件设备

BH1750传感器模块通常有4个引脚:

  • VCC:3.3V-5V供电
  • GND:接地
  • SCL:I2C时钟线
  • SDA:I2C数据线
  • ADDR:地址选择引脚(可选)

STM32F103C8T6最小系统板(蓝板)的GPIO资源:

  • 推荐使用PB6(SCL)和PB7(SDA),这是STM32的硬件I2C1接口
  • 也可用任意GPIO模拟I2C,本文以PC5(SCL)和PD2(SDA)为例

1.2 接线示意图

BH1750引脚STM32连接方式
VCC3.3V
GNDGND
SCLPC5
SDAPD2
ADDR悬空或接地

注意:ADDR引脚悬空时器件地址为0x23,接VCC时为0x5C。建议初次使用时保持悬空。

1.3 所需工具清单

  • STM32F103C8T6开发板 ×1
  • BH1750传感器模块 ×1
  • 杜邦线若干
  • USB转TTL模块(用于串口调试)
  • Keil MDK或STM32CubeIDE开发环境

2. 软件环境搭建

2.1 工程创建基础

使用STM32CubeMX快速配置工程:

  1. 选择STM32F103C8系列
  2. 开启GPIO:
    • PC5推挽输出(SCL)
    • PD2推挽输出(SDA)
  3. 配置USART1用于调试输出(115200波特率)
  4. 生成Keil或IAR工程

关键配置参数:

// GPIO初始化代码示例 GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); // SCL配置 (PC5) GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // SDA配置 (PD2) GPIO_InitStruct.Pin = GPIO_PIN_2; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

2.2 驱动代码移植

创建bh1750.c和bh1750.h文件,核心函数包括:

  • I2C起始/停止信号生成
  • 字节读写函数
  • 传感器初始化
  • 数据读取函数

典型错误排查:

  1. 确保所有GPIO时钟已开启
  2. 检查接线是否正确,特别是电源
  3. 用逻辑分析仪抓取I2C波形(可选)

3. 传感器驱动实现细节

3.1 I2C时序精准控制

软件模拟I2C的关键时序:

void I2C_Start(void) { SDA_HIGH(); SCL_HIGH(); Delay_us(5); SDA_LOW(); Delay_us(5); SCL_LOW(); } void I2C_Stop(void) { SDA_LOW(); SCL_HIGH(); Delay_us(5); SDA_HIGH(); Delay_us(5); }

时序参数建议:

操作延时时间
起始条件5μs
停止条件5μs
数据建立2μs
时钟高电平4μs

3.2 BH1750工作模式选择

传感器支持多种测量模式:

  • 高分辨率模式1 (0x10): 1lx精度,120ms
  • 高分辨率模式2 (0x11): 0.5lx精度,120ms
  • 低分辨率模式 (0x13): 4lx精度,16ms

模式设置代码示例:

void BH1750_SetMode(uint8_t mode) { I2C_Start(); I2C_WriteByte(0x23 << 1); // 器件地址+写 I2C_WaitAck(); I2C_WriteByte(mode); I2C_WaitAck(); I2C_Stop(); }

3.3 数据读取与处理

光照强度计算公式:

实际光照(lx) = 原始数据 / 1.2

数据读取流程:

  1. 发送启动测量命令
  2. 等待足够测量时间(根据模式不同)
  3. 读取两个字节数据
  4. 合并为16位数值
  5. 转换为实际光照强度
float BH1750_ReadLight(void) { uint8_t buf[2]; uint16_t val = 0; // 启动测量 BH1750_SetMode(BH1750_MODE_HR1); Delay_ms(180); // 等待测量完成 // 读取数据 I2C_Start(); I2C_WriteByte(0x23 << 1 | 0x01); // 器件地址+读 I2C_WaitAck(); buf[0] = I2C_ReadByte(1); // 读高字节 buf[1] = I2C_ReadByte(0); // 读低字节 I2C_Stop(); val = (buf[0] << 8) | buf[1]; return val / 1.2f; }

4. 数据可视化与优化

4.1 串口输出调试

通过printf输出光照数据:

printf("当前光照强度: %.2f lx\r\n", BH1750_ReadLight());

串口输出示例:

[BH1750] 初始化完成 [BH1750] 当前模式: 高分辨率模式1 [BH1750] 光照强度: 358.42 lx [BH1750] 光照强度: 362.15 lx

4.2 OLED显示实现

SSD1306 OLED显示代码片段:

void OLED_ShowLight(float lux) { char str[20]; sprintf(str, "Light:%.1flx", lux); OLED_ShowString(0, 2, str, 16); }

显示效果优化建议:

  • 添加光照等级提示(如"太暗/舒适/太亮")
  • 实现历史数据曲线显示
  • 添加单位自动转换(lx/fc)

4.3 实际应用场景扩展

基于光照数据的应用示例:

  1. 自动调光LED灯
  2. 智能窗帘控制系统
  3. 植物生长监测
  4. 室内环境质量评估

典型光照参考值:

环境场景典型光照范围(lx)
晴天室外10,000-100,000
阴天室外1,000-10,000
明亮办公室300-500
家庭起居室100-300
月光下的环境0.1-0.3

在完成基础功能后,可以尝试将采样间隔设置为30秒,连续记录24小时的光照变化,观察不同时段的光照规律。实际测试中发现,传感器在快速变化的光照环境下需要3-4次采样才能稳定到新值,这在设计实时系统时需要特别注意。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询