【i.MX6ULL】linux驱动bh1750模块

I2C-BH1750

1、设备地址

  • 引脚说明
VCC5V
GNDGND
SCLPB6
SDAPB7
ADDRVCC/GND

bh1750设备的地址由引脚 ADDR 来决定

  • ADDR接GND

    当ADDR引脚接地时设备bh1750的地址为:0x23(7bit)

  • ADDR接VCC

    当ADDR引脚接地时设备bh1750的地址为:0x5c(7bit)

2、工作模式

BH1750FVI模块共有六种工作模式:连续H-分辨率模式、连续H-分辨率模式2、连续L-分辨率模式、一次H分辨率模式、一次H分辨率模式2、一次性L分辨率模式

在这里插入图片描述
手册中建议使用 连续H-分辨率模式
在这里插入图片描述

连续H-分辨率模式 每次转换时间为120ms
在这里插入图片描述

3、读取数据流程

每个芯片都有固有的读取数据流程,下面我们来看一下bh1750模块的读取流程,以连续H-分辨率模式为例大致流程为:通电指令 -> 工作模式指令 -> 获取数据
在这里插入图片描述

4、ROM指令

在这里插入图片描述

5、读写时序

连续H-分辨率模式并且ADDR与GND相连的读写时序如下:
在这里插入图片描述
总上,读取数据全过程为:
第一步:通过I2C总线,主机给bh1750设备发送数据:0x01 ——> (Power on)
第二步:通过I2C总线,主机给bh1750设备发送数据:0x10 ——> (Continuously H-resolution mode)
第三步:通过I2C总线,主机读取设备bh1750采集到的数据

6、添加设备信息

找到开发板对应的设备树文件dts,i2c1的节点下面添加bh1750设备信息(我这里将bh1750连接到了i2c1控制器下):

&i2c1 {
      clock-frequency = <100000>;
      pinctrl-names = "default";
      pinctrl-0 = <&pinctrl_i2c1>;
      status = "okay";
 
      bh1750@23 {
          compatible = "gy302,bh1750";
          reg = <0x23>;
      };

7、驱动代码

#include <asm-generic/errno-base.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/i2c.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include "acpi/acoutput.h"
#include "asm-generic/int-ll64.h"
#include "linux/export.h"
#include "linux/printk.h"
#include "uapi/linux/i2c.h"
#include <linux/delay.h>

//Rom指令
#define POWER_ON           0x01
#define H_RESOLUTION_MODE  0x10

struct bh1750_device {
    void *private_data;
};

static struct bh1750_device bh1750_dev;

static int bh1750_read_regs(struct bh1750_device *dev, void *val, int len)
{
    int ret = 0;
    struct i2c_client *client = (struct i2c_client *)dev->private_data; 

     struct i2c_msg msgs[1] = {
        [0] = {  //寄存器的值
            .addr = client->addr,
            .flags = I2C_M_RD,
            .buf = val,
            .len = len,
        }
    };

    ret = i2c_transfer(client->adapter, msgs, 1);

    if (ret != 1) {
        printk("i2c rd failed=%d len=%d\n",ret, len);
        ret = -EINVAL;
    } else {
        ret = 0;
    }

    return ret;
}

/* bh1750写数据 */
static int bh1750_write_regs(struct bh1750_device *dev, u8 *buf, u8 len)
{
    struct i2c_client *client = (struct i2c_client *)dev->private_data;
    u8 data[256];

    struct i2c_msg msgs;

    memcpy(data, buf, len);

    msgs.addr = client->addr;
    msgs.flags = 0;
    msgs.buf = data;
    msgs.len = len;

    return i2c_transfer(client->adapter, &msgs, 1);
}

static void bh1750_write_reg(struct bh1750_device *dev, u8 data)
{
    int ret;

    ret = bh1750_write_regs(dev, &data, 1);
    if (ret != 1) {
        printk("i2c write fail: %d\n", ret);
    }
}

/* bh1750字符集 */
int bh1750_open(struct inode *inode, struct file *file)
{
    bh1750_write_reg(&bh1750_dev, POWER_ON);
    bh1750_write_reg(&bh1750_dev, H_RESOLUTION_MODE);
    mdelay(200);
    return 0;
}

ssize_t bh1750_read(struct file* filp, char __user* buf, size_t count, loff_t* ppos)
{
    u8 data[2];
    int err;

    bh1750_read_regs(&bh1750_dev, data, 2);


	err = copy_to_user(buf, data, sizeof(data));

    return 0;
}

int bh1750_close(struct inode *inode, struct file *file)
{
    return 0;
}

struct file_operations bh1750_fops = {
    .open = bh1750_open,
    .release = bh1750_close,
    .read = bh1750_read,
};

struct miscdevice bh1750_misc = {
    .name = "bh1750",
    .fops = &bh1750_fops,
    .minor = 255,
};

static const struct of_device_id bh1750_of_device_id[] = {
    { .compatible = "gy302,bh1750" },
    { /* END OF LIST */ }
};

struct i2c_device_id bh1750_device_id[] = {
    {.name = "gy302,bh1750", },
    { /* END OF LIST */ }
};

int bh1750_probe(struct i2c_client *client, const struct i2c_device_id *dev)
{
    int ret;
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

    ret = misc_register(&bh1750_misc);
    if (ret < 0) {
        printk(KERN_WARNING "ac.o: Unable to register misc device\n");
        goto MISC_REGISTER_FAIL;
    }

    /* 获得iic_client */
    bh1750_dev.private_data = client;

    printk("bh1750 addr: %#x\r\n", client->addr);

    return 0;

MISC_REGISTER_FAIL:
    return ret;
}

int bh1750_remove(struct i2c_client *client)
{
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

    misc_deregister(&bh1750_misc);
    
    return 0;
}

struct i2c_driver bh1750_driver = {
    .id_table = bh1750_device_id,
    .driver = {
        .owner = THIS_MODULE,
        .name = "bh1750",
        .of_match_table = bh1750_of_device_id,
    },
    .probe = bh1750_probe,
    .remove = bh1750_remove,
};

/* 入口 */
static int __init bh1750_driver_init(void)
{
    return i2c_add_driver(&bh1750_driver);
}

static void __exit bh1750_driver_exit(void)
{
    i2c_del_driver(&bh1750_driver);
}

module_init(bh1750_driver_init);
module_exit(bh1750_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lighting master");

应用层代码就你们自己写吧~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/223721.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【S32K3环境搭建】-0.3-S32DS安装实时驱动RTD(Real-Time Driver)

目录 1 什么是“实时驱动RTD(Real-Time Driver)” 2 安装“实时驱动RTD(Real-Time Driver)” 2.1 方法一&#xff1a;通过S32DS Extensions and Updates安装“实时驱动RTD(Real-Time Driver)” 2.2 方法二&#xff1a;通过Install New Software…安装“实时驱动RTD(Real-Ti…

基于KSZ9897VLAN 虚拟WAN网络接口

目录 1:先看看高通的8327是如何虚拟网络接口 2: Linux 内核中选上802.1Q 3: 实际效果展示 4&#xff1a;配置使用 1:先看看高通的8327是如何虚拟网络接口 rootOpenWrt:~# cat /etc/config/wirelessconfig wifi-device wifi0option type qcawifioption macaddr 68:89:75:04:…

一篇文章带你详细了解C++智能指针

一篇文章带你详细了解C智能指针 为什么要有智能指针内存泄漏1.什么是内存泄漏&#xff0c;它的危害是什么2.内存泄漏的分类3.如何避免内存泄漏 智能指针的使用及原理1.RAII2.智能指针的原理3.auto_ptr4.unique_ptr5.shared_ptr6.weak_ptr 为什么要有智能指针 C引入智能指针的主…

flink源码分析之功能组件(四)-slot管理组件I

简介 本系列是flink源码分析的第二个系列&#xff0c;上一个《flink源码分析之集群与资源》分析集群与资源&#xff0c;本系列分析功能组件&#xff0c;kubeclient&#xff0c;rpc&#xff0c;心跳&#xff0c;高可用&#xff0c;slotpool&#xff0c;rest&#xff0c;metrics&…

从零开发短视频电商 Jmeter压测示例模板详解(无认证场景)

文章目录 添加线程组添加定时器添加HTTP请求默认值添加HTTP头管理添加HTTP请求添加结果断言响应断言 Response AssertionJSON断言 JSON Assertion持续时间断言 Duration Assertion 添加察看结果树添加聚合报告添加表格察看结果参考 以压测百度搜索为例 https://www.baidu.com/s…

[NAND Flash 2.2] NAND闪存及控制器的市场趋势 [2023]

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《深入理解NAND Flash》 <<<< 返回总目录 <<<< 一、NAND闪存市场分析 据欧洲知名半导体分析机构Yole发布的报告显示&#xff0c;2020年起&#xff0c;NAND闪存市场发展趋势保持稳定…

【Angular开发】Angular中的高级组件

在这个博客中&#xff0c;我将解释Angular中的几个高级组件和机制&#xff0c;它们增强了灵活性、可重用性和性能。 通过熟悉这些高级组件和机制&#xff0c;您可以提高您的Angular开发技能&#xff0c;并在应用程序中利用灵活性、可重用性和性能优化的能力。让我们开始吧&…

使用dockerfile 构建自己的nacos-mysql

前言 在部署nacos的时候触发的脑袋灵光一闪&#xff0c;每次部署nacos都要部署下mysql服务器&#xff0c;然后导入sql语句&#xff0c;配置nacos配置文件&#xff0c;那有没有简单的方法实现一键部署nacos和nacos-mysql 呢? 答案是肯定&#xff01;如下目录图&#xff1a; …

ctfhub技能树_web_信息泄露

目录 二、信息泄露 2.1、目录遍历 2.2、Phpinfo 2.3、备份文件下载 2.3.1、网站源码 2.3.2、bak文件 2.3.3、vim缓存 2.3.4、.DS_Store 2.4、Git泄露 2.4.1、log 2.4.2、stash 2.4.3、index 2.5、SVN泄露 2.6、HG泄露 二、信息泄露 2.1、目录遍历 注&#xff1…

寻找峰值00

题目链接 寻找峰值 题目描述 注意点 数组可能包含多个峰值&#xff0c;在这种情况下&#xff0c;返回 任何一个峰值 所在位置即可对于所有有效的 i 都有 nums[i] ! nums[i 1]可以假设 nums[-1] nums[n] -∞ 解答思路 可以根据二分查找保证在O(log n)的时间复杂度找到峰…

数据中心的操作系统——kubernets

操作系统的功能和模块与 Kubernetes 的功能和模块做了一个对比&#xff1a; Kubernetes 作为数据中心的操作系统还是主要管理数据中心里面的四种硬件资源&#xff1a;CPU、内存、存储、网络。 对于 CPU 和内存这两种计算资源的管理&#xff0c;我们可以通过 Docker 技术完成。…

【数据分享】11个城市的出租车(网约车)数据(免费获取)

出租车&#xff08;网约车&#xff09;GPS数据是我们最常使用的交通大数据之一&#xff0c;但是出租车&#xff08;网约车&#xff09;GPS数据没有公开的获取渠道&#xff0c;有些学者可能能通过与相关机构合作拿到数据&#xff0c;但是对于绝大多数普通人是没有这个机会的&…

跳水比赛(C++)

系列文章目录 进阶的卡莎C++_睡觉觉觉得的博客-CSDN博客数1的个数_睡觉觉觉得的博客-CSDN博客双精度浮点数的输入输出_睡觉觉觉得的博客-CSDN博客足球联赛积分_睡觉觉觉得的博客-CSDN博客大减价(一级)_睡觉觉觉得的博客-CSDN博客小写字母的判断_睡觉觉觉得的博客-CSDN博客纸币(…

navicate16 2059 plugin http could not be loaded

plugin http could not be loaded 乱码 library path http.dll 今天新装一台机子的navicate遇到这个问题。 查了半天都是说 caching_sha2_password’的解决办法。 然后是咋解决的呢&#xff0c;真是丢脸 由于我是直接从浏览器复制下来的ip&#xff0c;所以虽然我只复制了ip地…

Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in modules。Android studio纯java代码报错

我使用java代码 构建项目&#xff0c;初始代码运行就会报错。我使用的是Android Studio Giraffe&#xff08;Adroid-studio-2022.3.1.18-windows&#xff09;。我在网上找的解决办法是删除重复的类&#xff0c;但这操作起来真的太麻烦了。 这是全部报错代码&#xff1a; Dupli…

QGraphicsView实现简易地图7『异步加载-多瓦片-无底图』

前文链接&#xff1a;QGraphicsView实现简易地图6『异步加载-单瓦片-无底图』 前一篇文章提到的异步单瓦片加载&#xff0c;是指线程每准备好一个瓦片数据后&#xff0c;立刻抛出信号让主线程加载。而本篇异步多瓦片加载是指线程准备好所有瓦片数据后&#xff0c;一起抛出信号让…

迅软DSE:为企业描绘安全蓝图,构建无忧网络办公天地

企业员工的不规范上网行为已成为管理人员面临的挑战&#xff0c;而利用上网行为管理软件则成为解决问题的最佳途径。 上网行为管理软件具备全面监控功能&#xff0c;可监控QQ、微信、电脑邮件、文件外发等行为&#xff0c;保证监控过程隐蔽而安全。通过实时屏幕监控功能&#…

[NAND Flash 2.3] 闪存芯片国产进程

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《深入理解NAND Flash》 <<<< 返回总目录 <<<< 目录 前言1 闪存介质1.1 NOR 闪存国产技术发展1.2 NAND 闪存国产技术 2 闪存国产厂商与产品2.1 NOR FLASH 国产厂商与产品2.2 NAND FA…

【Redis】redis 高性能--线程模型以及epoll网络框架

目录 一.前言 二.多线程的弊端 2.1 锁的开销问题 2.2 多线程上下文切换带来的额外开销 2.3 多线程占用内存成本增高 三.基本IO模型与epoll 模式 3.1 基本IO模型 3.2 单线程处理机制 四.总结 一.前言 我们经常讨论到&#xff0c;redis 是单线程&#xff0c;那为什么单线…

玩弄GPTs:人人都会的Prompt模板

角色定义 分享一个自用的Prompt模板&#xff0c;只要学会了这个模板&#xff0c;当遇到新场景时&#xff0c;直接套用就行。 简单总结&#xff1a; 角色定义(Master)背景(Background)规则(rule)技能(skill)限制(constaints)工作流(workflow) 经过实际测试发现&#xff0c;这…