以下作品由安信可社區(qū)用戶
WangChong制作
外設(shè)介紹
BH1750是一種基于光電二極管的數(shù)字光強(qiáng)傳感器,能夠測量環(huán)境中的光照強(qiáng)度,并將其轉(zhuǎn)換為數(shù)字信號。它采用 I2C 接口進(jìn)行通信,適合用于光強(qiáng)度檢測的各種應(yīng)用,如自動調(diào)節(jié)顯示屏亮度、光線感應(yīng)開關(guān)等。
外設(shè)規(guī)格參數(shù)
工作電壓: 2.4V 至 3.6V
測量范圍: 1 至 65535 lux
分辨率:
高分辨率模式(1 lx)
低分辨率模式(4 lx)
通信接口: I2C
I2C 地址: 0x23(默認(rèn)),0x5C(可選) 根據(jù) Address 是否接拉低或者拉高進(jìn)行選擇
測量時間:
高分辨率模式: 120ms - 180ms
低分辨率模式: 16ms - 24 ms
待機(jī)模式: 0.1 μA(典型值)
功耗:
測量模式: 0.12 mA(典型值)
移植過程
BH1750 數(shù)據(jù)手冊:https://www.mouser.com/datasheet/2/348/bh1750fvi-e-186247.pdf
根據(jù)數(shù)據(jù)手冊得知, BH1750 是使用的 I2C 通信,同時我們使用的是 WB2,因此我們需要根據(jù)原理圖確認(rèn) WB2 的 I2C 接口 PIN。
由于使用的是 WB2-12F 的開發(fā)板,所以可以在安信可社區(qū) WB2 專題下找到對應(yīng)的原理圖,同時根據(jù)博流官方 GPIO 的功能復(fù)用,可以找到哪些 PIN 支持 I2C。
https://dev.bouffalolab.com/media/doc/602/open/datasheet/zh/html/content/Pindefinition.html
在 SDK 下的 application/iot-solution/demo_bh1750 下已經(jīng)提供了一個完整的實現(xiàn)。我們來嘗試將 I2C 配置中的 PIN3(SDA)改成 PIN17 (SDA)。同時將 WB2-12F devkit 的 12 號 PIN 和 17 號 PIN 分別接到 BH1750 的 SCL 和 SDA 上進(jìn)行燒錄測試。
燒錄驗證
此時可以通過串口助手已經(jīng)可以正確的查看到 WB2-12F 正確的讀取了 BH1750 的光照強(qiáng)度。
代碼解讀
#include
#include
#include
#include
#include
#include
// BH1750 的默認(rèn) 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 // 開機(jī)命令
#define BH1750_RESET 0x07 // 重置命令
#define BH1750_CONTINUOUS_H_MODE 0x10 // 高分辨率模式,持續(xù)測量
#define BH1750_CONTINUOUS_H_MODE2 0x11 // 高分辨率模式2,持續(xù)測量
#define BH1750_CONTINUOUS_L_MODE 0x13 // 低分辨率模式,持續(xù)測量
#define BH1750_ONETIME_H_MODE 0x20 // 高分辨率模式,一次性測量
#define BH1750_ONETIME_H_MODE2 0x21 // 高分辨率模式2,一次性測量
#define BH1750_ONETIME_L_MODE 0x23 // 低分辨率模式,一次性測量
int main(void)
{
// 定義并初始化 I2C 設(shè)備 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 主機(jī)模式
.scl = 12, // 時鐘引腳 GPIO 12
.sda = 17, // 數(shù)據(jù)引腳 GPIO 17
},
.port = 0, // I2C 端口號
};
// 初始化 I2C 接口
hosal_i2c_init(&i2c0);
for (;;) {
uint8_t buffer[2]; // 用于接收光照強(qiáng)度數(shù)據(jù)的緩沖區(qū)
uint8_t cmd = BH1750_ONETIME_H_MODE; // 設(shè)置 BH1750 的測量模式為高分辨率一次性測量
hosal_i2c_master_send(&i2c0, BH1750_DEFAULT_ADDR, &cmd, 1, HOSAL_WAIT_FOREVER); // 發(fā)送測量命令到 BH1750
// 接收來自 BH1750 的測量結(jié)果(2字節(jié))
int ret = hosal_i2c_master_recv(&i2c0, BH1750_DEFAULT_ADDR, buffer, 2, 100);
if (ret) {
// 如果接收超時,重新發(fā)送上電命令并記錄錯誤日志
cmd = BH1750_POWER_ON;
hosal_i2c_master_send(&i2c0, BH1750_DEFAULT_ADDR, &cmd, 1, 100);
blog_error("i2c timeoutrn");
} else {
// 將接收到的兩個字節(jié)數(shù)據(jù)合并為一個16位整數(shù)
uint16_t result = buffer[0];
result <<= 8; // 左移8位,放置高8位
result |= buffer[1]; // 組合低8位
// 將測量值轉(zhuǎn)換為光照強(qiáng)度(lux)
float luxlevel = result;
result /= 1.2f;
// 輸出光照強(qiáng)度日志
blog_info("lux level: %.02frn", luxlevel);
}
// 任務(wù)延時 1000 毫秒,即每隔 1 秒執(zhí)行一次測量
vTaskDelay(portTICK_RATE_MS * 1000);
}
return 0;
}
庫函數(shù)
讓我們簡單的對上面的庫函數(shù)進(jìn)行一下整理
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)); // 使用宏將毫秒轉(zhuǎn)換為FreeRTOS時間單位
}
}
bh1750.h
#ifndef BH1750_H
#define BH1750_H
#include
// BH1750 的默認(rèn) 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 // 開機(jī)命令
#define BH1750_RESET 0x07 // 重置命令
#define BH1750_CONTINUOUS_H_MODE 0x10 // 高分辨率模式,持續(xù)測量
#define BH1750_CONTINUOUS_H_MODE2 0x11 // 高分辨率模式2,持續(xù)測量
#define BH1750_CONTINUOUS_L_MODE 0x13 // 低分辨率模式,持續(xù)測量
#define BH1750_ONETIME_H_MODE 0x20 // 高分辨率模式,一次性測量
#define BH1750_ONETIME_H_MODE2 0x21 // 高分辨率模式2,一次性測量
#define BH1750_ONETIME_L_MODE 0x23 // 低分辨率模式,一次性測量
// 函數(shù)聲明
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;
}
注意事項
切記,不要在主函數(shù)中開啟任務(wù)的調(diào)度器,主函數(shù)在其他地方使用 extern 引用了,相當(dāng)于一個中轉(zhuǎn)的中間方法,可以用于初始化 task。
附上后續(xù)的驗證過程:
驗證過程
1. 編譯代碼
上述帖子中已經(jīng)貼出來了完整的工程代碼。直接將其拷貝到 sdk 目錄,為了與 sdk 中的代碼沖突,將驗證工程目錄改名為 demo_bh17501。
進(jìn)入到目錄中進(jìn)行編譯:
很快就可以看到編譯成功。
2. 代碼燒錄
燒錄完成:
3. 測試驗證
打開串口工具:
可以看到傳感器的數(shù)據(jù)有輸出了。實際測試用不同強(qiáng)度的光線照射得到的 lux 是和預(yù)期相符的。
至此,驗證通過。
審核編輯 黃宇
-
傳感器
+關(guān)注
關(guān)注
2550文章
51035瀏覽量
753060
發(fā)布評論請先 登錄
相關(guān)推薦
評論