Linux用户空间无需寄存器地址读取BH1750 2字节I2C数据的实现方法
Linux用户空间无寄存器地址I2C多字节读取方案
实现思路
Linux内核提供了i2c-dev字符设备驱动,允许用户空间直接发起自定义I2C传输序列,无需编写内核驱动即可实现你需要的S Adr Rd (A) Data A Data NA P读取时序。核心使用I2C_RDWR类型的ioctl调用,该调用支持完全自定义传输结构,不需要强制附带寄存器地址前缀。
操作步骤
- 首先确认BeagleBone上BH1750挂载的I2C总线编号,执行
i2cdetect -l可以列出所有可用I2C总线,常用编号为i2c-1 - 加载i2c-dev内核模块:
modprobe i2c-dev,加载成功后会生成/dev/i2c-X(X为总线编号)设备节点 - 编写C代码调用ioctl完成读取,示例代码如下:
#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <stdint.h> #include <sys/ioctl.h> #include <linux/i2c.h> #include <linux/i2c-dev.h> // 根据BH1750的ADDR引脚电平调整地址,接GND为0x23,接VCC为0x5C #define BH1750_ADDR 0x23 int main() { int fd = open("/dev/i2c-1", O_RDWR); if (fd < 0) { perror("打开I2C设备失败"); return 1; } uint8_t recv_buf[2]; struct i2c_msg msgs[] = { { .addr = BH1750_ADDR, .flags = I2C_M_RD, // 标记为I2C读操作 .len = 2, // 连续读取2字节 .buf = recv_buf, } }; struct i2c_rdwr_ioctl_data ioctl_data = { .msgs = msgs, .nmsgs = 1, }; if (ioctl(fd, I2C_RDWR, &ioctl_data) < 0) { perror("I2C读取失败"); close(fd); return 1; } // 换算光照强度,单位lux float lux = ((recv_buf[0] << 8) | recv_buf[1]) / 1.2; printf("当前光照强度:%.2f lux\n", lux); close(fd); return 0; }
注意事项
- 运行程序需要root权限,或者通过udev规则配置普通用户对
/dev/i2c-X节点的访问权限 - 如果需要先发送测量启动指令,只需要在msgs数组中新增一个写类型的i2c_msg放在读消息之前,ioctl会自动按顺序完成连续传输
- 编译时不需要额外链接第三方库,直接用gcc编译即可:
gcc bh1750_read.c -o bh1750_read
内容的提问来源于stack exchange,提问作者0xEBD
相关产品推荐
相关产品推荐

