linux驱动 -- IIC&BH1750

1:linux下的IIC

linux中最重要的思想就是分层思想,一般开发者对接的是中间层也就是接口,linux不关注底层,这个底层一般是内核与厂家联合初始化的。

通过设备树提供IIC信息,然后再提供一些接口

在驱动结构体中:厂商提供IIC的信息,再匹配设备树提供的信息,会自动去匹配对应的设备文件。

2:linux下的IIC的中间层接口

         linux下的IIC接口是平台设备总线类型的,需要注册驱动信息,从而匹配设备信息

2.1 接口函数

头文件:

#include "linux/i2c.h"

IIC的驱动的信息注册函数:

int i2c_add_driver(struct i2c_driver *driver)
int i2c_register_driver(struct module *owner, struct i2c_driver
*driver);

函数功能:

        向内核注册IIC 驱动信息,主要是去匹配设备树的IIC信息。

函数参数:

        driver:

                注册内核I2C设备信息,主要对应的是入口、出口、匹配信息

struct i2c_driver
{
    //匹配函数
    int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
    int (*probe_new)(struct i2c_client *client);
    //注销函数
    int (*remove)(struct i2c_client *client);
    struct device_driver driver
    {
        const char *name;//一般填写
        const struct of_device_id *of_match_table;
        //匹配 compatible 
    }
    const struct i2c_device_id *id_table
    {
        char name[I2C_NAME_SIZE];
    }
}

返回值:

        成功返回 0

        失败返回 非0

匹配成功后的probe(struct i2c_client  * client)

其中的信息结构体:

struct i2c_client
{
    unsigned short addr;//设备树传递过来的从机地址!
    struct i2c_adapter *adapter;//他就是 IICx 的抽象的内核结构体
    //有了他 你就可以任意的操作内核 IIC 了!
    //有了它你就可以调用 i2c_transfer
    //做数据的读写收发了!
}

函数功能:用于内核层的IIC的读写

函数原型

int i2c_transfer(
    struct i2c_adapter *adap,
    struct i2c_msg *msgs,
    int num
);    

函数的参数

        adapt:IIC的抽象结构体

        msgs:

struct i2c_msg {
    __u16 addr; //从机地址
    __u16 flags;//标志 : 0/1 -> 写 / 读
    __u16 len; //读写的数据长度
    __u8 *buf;//读写缓冲区
}

num:有结果msg需要发送。

3:BH1750

3.1: BH1750 介绍

3.2 核心信息

从机地址:
        两种从机地址可以选择
        默认我们没有接 ADDR: 0100011 = 0x23

工作流程:
        设置 BH1750 的工作模式
        写入 BH1750 指令 0x11(高分辨率模式 2), 产生停止
        等待 180ms->BH1750 就开始以这个模式正常工作

        BH1750 不断采集外部光照数据给主机返回
        主机每隔 120ms 找从机要一次数据即可
        注意返回的数据是 16bit
工作模式:

4:IIC驱动BH1750设备代码示例

//bh1750光照传感器
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/of.h"
#include "linux/cdev.h"
#include "linux/fs.h"
#include "linux/gpio.h"
#include "linux/of_gpio.h"
#include "linux/device/class.h"
#include "linux/device.h"
#include "linux/platform_device.h"
#include "linux/miscdevice.h"
#include "asm/uaccess.h"
#include "linux/irq.h"
#include "linux/interrupt.h"
#include "linux/sched.h"
#include "linux/wait.h"
#include "linux/i2c.h"
#include "linux/delay.h"
struct i2c_client * bh1750_client;
struct miscdevice *misc;
struct file_operations *fops;
struct i2c_adapter *adap;
int bh1750_open (struct inode * ind, struct file *file)
{
    //初始化bh1750发送0X10
    // i2c_smbus_write_block_data();
    uint8_t cmd =0x10;
    struct i2c_msg  msgs;
    msgs.addr = bh1750_client->addr;//从机地址
    msgs.buf = &cmd;
    msgs.len =1;
    msgs.flags = 0;//代表写入数据
    int rem = i2c_transfer(bh1750_client->adapter,&msgs,1);
    mdelay(200);//延时200ms
    rem =rem;
    return 0;
}
int bh1750_close (struct inode * ind, struct file *file)
{
    return 0;
}
ssize_t bh1750_read (struct file * fil, char __user * buff, size_t size, loff_t * lof)
{
    //读取从机的数据
    //返回的数据是16bit的
    uint8_t readbuf[2] ={0};
    uint16_t value;
    struct i2c_msg msgs;
    msgs.addr = bh1750_client->addr;
    msgs.buf = readbuf;
    msgs.len = 2;
    msgs.flags = 1;
    int rem = i2c_transfer(bh1750_client->adapter,&msgs,1);
    value = readbuf[0]<<8 | readbuf[1];
    int ret = copy_to_user(buff,&value,2);
    ret =0;
    rem =rem;
    return 0;
}

int bh1750_probel(struct i2c_client *client)
{
    printk("检测到信息\r\n");
    bh1750_client = client;
    // node= dev->dev.of_node;//承接设备树信息
   //注册杂项设备
   misc = kzalloc(sizeof(struct miscdevice),GFP_KERNEL);
   fops = kzalloc(sizeof(struct file_operations),GFP_KERNEL);
   fops->open = bh1750_open;
   fops->owner = THIS_MODULE;
   fops->release = bh1750_close;
   fops->read = bh1750_read;

   misc->minor = 255;
   misc->name = "xyd_bh1750";
   misc->fops = fops;
   return misc_register(misc);
}


struct of_device_id id_tible={
    .compatible = "xydbh1750",//匹配名字
};

struct i2c_driver bh1750_driver = {
    .probe_new = bh1750_probel,
    .driver = {
        .name = "xyd_bh1750",
        .of_match_table = &id_tible,
    },
};
//加载函数
static int __init bh1750_init(void)
{
    //添加设备树
    i2c_add_driver(&bh1750_driver);
    // platform_driver_register(&bh1750);
    return 0;
}
static void __exit bh1750_exit(void)
{
    // platform_driver_unregister(&bh1750);
}
module_init(bh1750_init);
module_exit(bh1750_exit);
MODULE_LICENSE("GPL");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值