以下作品由安信可社区用户
WangChong制作
外设介绍
BH1750是一种基于光电二极管的数字光强传感器,能够测量环境中的光照强度,并将其转换为数字信号。它采用 I2C 接口进行通信,适合用于光强度检测的各种应用,如自动调节显示屏亮度、光线感应开关等。
外设规格参数
工作电压: 2.4V 至 3.6V
测量范围: 1 至 65535 lux
分辨率:
高分辨率模式(1 lx)
低分辨率模式(4 lx)
通信接口: I2C
I2C 地址: 0x23(默认),0x5C(可选) 根据 Address 是否接拉低或者拉高进行选择
测量时间:
高分辨率模式: 120ms - 180ms
低分辨率模式: 16ms - 24 ms
待机模式: 0.1 µA(典型值)
功耗:
测量模式: 0.12 mA(典型值)
移植过程
BH1750 数据手册:https://www.mouser.com/datasheet/2/348/bh1750fvi-e-186247.pdf
根据数据手册得知, BH1750 是使用的 I2C 通信,同时我们使用的是 WB2,因此我们需要根据原理图确认 WB2 的 I2C 接口 PIN。
由于使用的是 WB2-12F 的开发板,所以可以在安信可社区 WB2 专题下找到对应的原理图,同时根据博流官方 GPIO 的功能复用,可以找到哪些 PIN 支持 I2C。
https://dev.bouffalolab.com/media/doc/602/open/datasheet/zh/html/content/Pindefinition.html
在 SDK 下的 application/iot-solution/demo_bh1750 下已经提供了一个完整的实现。我们来尝试将 I2C 配置中的 PIN3(SDA)改成 PIN17 (SDA)。同时将 WB2-12F devkit 的 12 号 PIN 和 17 号 PIN 分别接到 BH1750 的 SCL 和 SDA 上进行烧录测试。
烧录验证
此时可以通过串口助手已经可以正确的查看到 WB2-12F 正确的读取了 BH1750 的光照强度。
代码解读
#include
#include
#include
#include
#include
#include
// BH1750 的默认 I2C 地址
#define BH1750_DEFAULT_ADDR BH1750_ADDR_L
#define BH1750_ADDR_H 0x5c // BH1750 高地址
#define BH1750_ADDR_L 0x23 // BH1750 低地址
// BH1750 的各种操作命令
#define BH1750_POWER_DOWN 0x00 // 断电命令
#define BH1750_POWER_ON 0x01 // 开机命令
#define BH1750_RESET 0x07 // 重置命令
#define BH1750_CONTINUOUS_H_MODE 0x10 // 高分辨率模式,持续测量
#define BH1750_CONTINUOUS_H_MODE2 0x11 // 高分辨率模式2,持续测量
#define BH1750_CONTINUOUS_L_MODE 0x13 // 低分辨率模式,持续测量
#define BH1750_ONETIME_H_MODE 0x20 // 高分辨率模式,一次性测量
#define BH1750_ONETIME_H_MODE2 0x21 // 高分辨率模式2,一次性测量
#define BH1750_ONETIME_L_MODE 0x23 // 低分辨率模式,一次性测量
int main(void)
{
// 定义并初始化 I2C 设备 i2c0
static hosal_i2c_dev_t i2c0 = {
.config = {
.address_width = HOSAL_I2C_ADDRESS_WIDTH_7BIT, // 7位地址模式
.freq = 100000, // I2C 通信频率为 100kHz
.mode = HOSAL_I2C_MODE_MASTER, // I2C 主机模式
.scl = 12, // 时钟引脚 GPIO 12
.sda = 17, // 数据引脚 GPIO 17
},
.port = 0, // I2C 端口号
};
// 初始化 I2C 接口
hosal_i2c_init(&i2c0);
for (;;) {
uint8_t buffer[2]; // 用于接收光照强度数据的缓冲区
uint8_t cmd = BH1750_ONETIME_H_MODE; // 设置 BH1750 的测量模式为高分辨率一次性测量
hosal_i2c_master_send(&i2c0, BH1750_DEFAULT_ADDR, &cmd, 1, HOSAL_WAIT_FOREVER); // 发送测量命令到 BH1750
// 接收来自 BH1750 的测量结果(2字节)
int ret = hosal_i2c_master_recv(&i2c0, BH1750_DEFAULT_ADDR, buffer, 2, 100);
if (ret) {
// 如果接收超时,重新发送上电命令并记录错误日志
cmd = BH1750_POWER_ON;
hosal_i2c_master_send(&i2c0, BH1750_DEFAULT_ADDR, &cmd, 1, 100);
blog_error("i2c timeoutrn");
} else {
// 将接收到的两个字节数据合并为一个16位整数
uint16_t result = buffer[0];
result <<= 8; // 左移8位,放置高8位
result |= buffer[1]; // 组合低8位
// 将测量值转换为光照强度(lux)
float luxlevel = result;
result /= 1.2f;
// 输出光照强度日志
blog_info("lux level: %.02frn", luxlevel);
}
// 任务延时 1000 毫秒,即每隔 1 秒执行一次测量
vTaskDelay(portTICK_RATE_MS * 1000);
}
return 0;
}
库函数
让我们简单的对上面的库函数进行一下整理
bh1750.c
#include "bh1750.h"
#include
#include
#include
static hosal_i2c_dev_t i2c0 = {
.config = {
.address_width = HOSAL_I2C_ADDRESS_WIDTH_7BIT,
.freq = 100000,
.mode = HOSAL_I2C_MODE_MASTER,
.scl = 12,
.sda = 17,
},
.port = 0,
};
void bh1750_init()
{
blog_info("Initializing I2C...n");
hosal_i2c_init(&i2c0);
}
void read_bh1750(void *args)
{
for (;;)
{
uint8_t buffer[2];
uint8_t cmd = BH1750_ONETIME_H_MODE;
int ret;
blog_info("Sending command to BH1750...n");
ret = hosal_i2c_master_send(&i2c0, BH1750_DEFAULT_ADDR, &cmd, 1, HOSAL_WAIT_FOREVER);
if (ret != 0)
{
blog_error("I2C send failed with error: %dn", ret);
continue;
}
blog_info("Receiving data from BH1750...n");
ret = hosal_i2c_master_recv(&i2c0, BH1750_DEFAULT_ADDR, buffer, 2, 100);
if (ret != 0)
{
cmd = BH1750_POWER_ON;
hosal_i2c_master_send(&i2c0, BH1750_DEFAULT_ADDR, &cmd, 1, 100);
blog_error("I2C receive failed with error: %dn", ret);
}
else
{
uint16_t result = (buffer[0] << 8) | buffer[1];
float luxlevel = result / 1.2f;
blog_info("Lux level: %.02fn", luxlevel);
}
vTaskDelay(pdMS_TO_TICKS(1000)); // 使用宏将毫秒转换为FreeRTOS时间单位
}
}
bh1750.h
#ifndef BH1750_H
#define BH1750_H
#include
// BH1750 的默认 I2C 地址
#define BH1750_DEFAULT_ADDR BH1750_ADDR_L
#define BH1750_ADDR_H 0x5c // BH1750 高地址
#define BH1750_ADDR_L 0x23 // BH1750 低地址
// BH1750 的各种操作命令
#define BH1750_POWER_DOWN 0x00 // 断电命令
#define BH1750_POWER_ON 0x01 // 开机命令
#define BH1750_RESET 0x07 // 重置命令
#define BH1750_CONTINUOUS_H_MODE 0x10 // 高分辨率模式,持续测量
#define BH1750_CONTINUOUS_H_MODE2 0x11 // 高分辨率模式2,持续测量
#define BH1750_CONTINUOUS_L_MODE 0x13 // 低分辨率模式,持续测量
#define BH1750_ONETIME_H_MODE 0x20 // 高分辨率模式,一次性测量
#define BH1750_ONETIME_H_MODE2 0x21 // 高分辨率模式2,一次性测量
#define BH1750_ONETIME_L_MODE 0x23 // 低分辨率模式,一次性测量
// 函数声明
void bh1750_init();
void read_bh1750(void *args);
#endif // BH1750_H
main.c
#include
#include
#include
#include
#include
#include
#include "bh1750.h"
int main(void)
{
bh1750_init();
xTaskCreate(read_bh1750, "BH1750 Task", 4096, NULL, 10, NULL);
return 0;
}
注意事项
切记,不要在主函数中开启任务的调度器,主函数在其他地方使用 extern 引用了,相当于一个中转的中间方法,可以用于初始化 task。
附上后续的验证过程:
验证过程
1. 编译代码
上述帖子中已经贴出来了完整的工程代码。直接将其拷贝到 sdk 目录,为了与 sdk 中的代码冲突,将验证工程目录改名为 demo_bh17501。
进入到目录中进行编译:
很快就可以看到编译成功。
2. 代码烧录
烧录完成:
3. 测试验证
打开串口工具:
可以看到传感器的数据有输出了。实际测试用不同强度的光线照射得到的 lux 是和预期相符的。
至此,验证通过。
审核编辑 黄宇
-
传感器
+关注
关注
2550文章
51035浏览量
753052
发布评论请先 登录
相关推荐
评论