RT-Thread Studio 使用笔记(六)| 获取光传感器数据(I2C设备驱动+BH1750手写驱动代码分享)

Roselani ·
更新时间:2024-09-20
· 604 次阅读

1. 介绍 2. 添加I2C设备 2.1. 打开I2C设备驱动框架

双击左侧 RT-Thread Setting 文件,即可打开RT-Thread图形化配置工具,软件模拟I2C这一项是灰色的,表示没有打开,单击一下即可打开软件 I2C 的驱动框架,图标变为彩色表示打开:

右击该选项可以打开更多配置,比如查看该驱动设备的依赖、查看该驱动设备的详细配置,查看该驱动设备的API文档,查看在线文档等操作:

Ctrl+S保存,配置生效,软件会自动添加I2C设备驱动框架到工程中:

2.2. 添加软件 I2C 源码

打开了软件 I2C 的驱动框架之后,还要添加软件I2C的驱动底层实现,具体芯片的软件 I2C 驱动源码不同,本例中下载添加 STM32 系列的软件 I2C 驱动:Gitee 下载地址。

git clone https://gitee.com/tyustli/tyustli.git

下载之后源码只有两个文件:

将这两个文件添加到项目中的drivers文件夹中:

回到RT-Thread Studio IDE,在项目名称上右击,选择刷新,即可在目录中看到添加的文件:

2.3. 注册 I2C 设备

软件 I2C 添加到工程中之后就可以调用软件 I2C 注册函数 rt_hw_i2c_init 来注册软件 I2C 设备了,该函数的原型如下:

int rt_hw_i2c_init(char *name, rt_uint8_t scl, rt_uint8_t sda) name:设备名称 scl:软件模拟I2C的SCL引脚 sda:软件模拟I2C的SDA引脚

在小熊派IoT开发板上,温湿度传感器SHT30连接在PB6(SCL)和PB7(SDA) ,所以在main.c文件中先添加头文件:

#include

然后在文件最后添加如下注册软件 I2C到系统中的代码:

int register_i2c(void) { rt_hw_i2c_init("i2c1", GET_PIN(B,6), GET_PIN(B,7)); return RT_EOK; } //注册到系统中,自动初始化设备 INIT_BOARD_EXPORT(register_i2c);

添加完成之后点击编译,下载到开发板中运行,即可在串口终端中看到日志信息(绿色),提示I2C总线设备已注册成功:

因为main线程中循环打印对使用控制台有影响,所以将打印函数注释:

重新编译下载,在串口终端中输入命令list_device查看系统中注册的设备吗,再次确认I2C总线设备注册成功:

3. BH1750驱动代码 #include #include #define BH1750_I2C_BUS_NAME "i2c1" /* 传感器连接的I2C总线设备名称 */ #define BH1750_ADDR 0x23 /* 从机地址 */ typedef enum { POWER_OFF_CMD = 0x00, //断电:无激活状态 POWER_ON_CMD = 0x01, //通电:等待测量指令 RESET_REGISTER = 0x07, //重置数字寄存器(在断电状态下不起作用) CONT_H_MODE = 0x10, //连续H分辨率模式:在11x分辨率下开始测量,测量时间120ms CONT_H_MODE2 = 0x11, //连续H分辨率模式2:在0.51x分辨率下开始测量,测量时间120ms CONT_L_MODE = 0x13, //连续L分辨率模式:在411分辨率下开始测量,测量时间16ms ONCE_H_MODE = 0x20, //一次高分辨率模式:在11x分辨率下开始测量,测量时间120ms,测量后自动设置为断电模式 ONCE_H_MODE2 = 0x21, //一次高分辨率模式2:在0.51x分辨率下开始测量,测量时间120ms,测量后自动设置为断电模式 ONCE_L_MODE = 0x23 //一次低分辨率模式:在411x分辨率下开始测量,测量时间16ms,测量后自动设置为断电模式 } BH1750_MODE; static struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄 */ /** * @brief 向BH1750发送一条指令 * @param cmd —— BH1750工作模式指令(在BH1750_MODE中枚举定义) * @retval 成功返回RT_EOK */ rt_err_t BH1750_Send_Cmd(BH1750_MODE cmd) { struct rt_i2c_msg msgs; msgs.addr = BH1750_ADDR; msgs.flags = RT_I2C_WR; msgs.len = 1; msgs.buf = (rt_uint8_t*)&cmd; /* 调用I2C设备接口传输数据 */ if (rt_i2c_transfer(i2c_bus, &msgs, 1) == 1) { return RT_EOK; } else { return -RT_ERROR; } } /** * @brief 从BH1750接收一次光强数据 * @param dat —— 存储光照强度的地址(两个字节数组) * @retval 成功 —— 返回RT_EOK */ rt_err_t BH1750_Read_Dat(rt_uint8_t* dat) { struct rt_i2c_msg msgs; msgs.addr = BH1750_ADDR; msgs.flags = RT_I2C_RD; msgs.len = 2; msgs.buf = dat; /* 调用I2C设备接口传输数据 */ if (rt_i2c_transfer(i2c_bus, &msgs, 2) == 2) { return RT_EOK; } else { return -RT_ERROR; } } /** * @brief 将BH1750的两个字节数据转换为光照强度值(0-65535) * @param dat —— 存储光照强度的地址(两个字节数组) * @retval 成功 —— 返回光照强度值 */ rt_uint16_t BH1750_Dat_To_Lux(rt_uint8_t* dat) { rt_uint16_t lux = 0; lux = dat[0]; lux <<= 8; lux += dat[1]; lux = (int)(lux / 1.2); return lux; } void i2c_bh1750_example_entry(void *parameter) { rt_uint8_t dat[2] = {0}; //dat[0]是高字节,dat[1]是低字节 /* 查找I2C总线设备,获取I2C总线设备句柄 */ i2c_bus = (struct rt_i2c_bus_device*)rt_device_find(BH1750_I2C_BUS_NAME); if(i2c_bus == RT_NULL) { rt_kprintf("can't find %s device!\n", BH1750_I2C_BUS_NAME); } while(1) { /* 发送命令设置模式 */ BH1750_Send_Cmd(ONCE_H_MODE); /* 等待数据转换完成 */ rt_thread_mdelay(150); /* 读取数据 */ BH1750_Read_Dat(dat); /* 转换数据并打印 */ rt_kprintf("current: %5d lux\n", BH1750_Dat_To_Lux(dat)); rt_thread_mdelay(1000); } } int i2c_bh1750_example(void) { rt_thread_t tid; //线程句柄 tid = rt_thread_create("bh1750_thread", i2c_bh1750_example_entry, RT_NULL, 512, 9, 10); if(tid != RT_NULL) { //线程创建成功,启动线程 rt_thread_startup(tid); } return 0; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(i2c_bh1750_example, i2c bh1750 example);

执行该线程:

接收更多精彩文章及资源推送,欢迎订阅我的微信公众号:『mculover666』。


作者:Mculover666



i2c studio rt-thread 数据 传感器

需要 登录 后方可回复, 如果你还没有账号请 注册新账号