1 分析i2c设备的识别过程
i2c_add_driver
    i2c_register_driver
        driver->driver.bus = &i2c_bus_type;
        driver_register(&driver->driver);
        
        list_for_each_entry(adapter, &adapters, list) {
            driver->attach_adapter(adapter);
                        i2c_probe(adapter, &addr_data, eeprom_detect);
                            i2c_probe_address // 发出S信号,发出设备地址(来自addr_data)
                                i2c_smbus_xfer
                                    i2c_smbus_xfer_emulated
                                        i2c_transfer
                                            adap->algo->master_xfer // s3c24xx_i2c_xfer
                                            
        
2 怎么写I2C设备驱动程序?
2.1 分配一个i2c_driver结构体
2.2 设置
      attach_adapter // 它直接调用 i2c_probe(adap, 设备地址, 发现这个设备后要调用的函数);
      detach_client  // 卸载这个驱动后,如果之前发现能够支持的设备,则调用它来清理
      
2.3 注册:i2c_add_driver

3 写代码

 #include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/fs.h>
#include <asm/uaccess.h> static unsigned short ignore[] = { I2C_CLIENT_END };
static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END }; /* 地址值是7位 */
/* 改为0x60的话, 由于不存在设备地址为0x60的设备, 所以at24cxx_detect不被调用 */ static unsigned short force_addr[] = {ANY_I2C_BUS, 0x60, I2C_CLIENT_END};
static unsigned short * forces[] = {force_addr, NULL}; static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr, /* 要发出S信号和设备地址并得到ACK信号,才能确定存在这个设备 */
.probe = ignore,
.ignore = ignore,
//.forces = forces, /* 强制认为存在这个设备 */
}; static struct i2c_driver at24cxx_driver; static int major;
static struct class *cls;
struct i2c_client *at24cxx_client; static ssize_t at24cxx_read(struct file *file, char __user *buf, size_t size, loff_t * offset)
{
unsigned char address;
unsigned char data;
struct i2c_msg msg[];
int ret; /* address = buf[0]
* data = buf[1]
*/
if (size != )
return -EINVAL; copy_from_user(&address, buf, ); /* 数据传输三要素: 源,目的,长度 */ /* 读AT24CXX时,要先把要读的存储空间的地址发给它 */
msg[].addr = at24cxx_client->addr; /* 目的 */
msg[].buf = &address; /* 源 */
msg[].len = ; /* 地址=1 byte */
msg[].flags = ; /* 表示写 */ /* 然后启动读操作 */
msg[].addr = at24cxx_client->addr; /* 源 */
msg[].buf = &data; /* 目的 */
msg[].len = ; /* 数据=1 byte */
msg[].flags = I2C_M_RD; /* 表示读 */ ret = i2c_transfer(at24cxx_client->adapter, msg, );
if (ret == )
{
copy_to_user(buf, &data, );
return ;
}
else
return -EIO;
} static ssize_t at24cxx_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
unsigned char val[];
struct i2c_msg msg[];
int ret; /* address = buf[0]
* data = buf[1]
*/
if (size != )
return -EINVAL; copy_from_user(val, buf, ); /* 数据传输三要素: 源,目的,长度 */
msg[].addr = at24cxx_client->addr; /* 目的 */
msg[].buf = val; /* 源 */
msg[].len = ; /* 地址+数据=2 byte */
msg[].flags = ; /* 表示写 */ ret = i2c_transfer(at24cxx_client->adapter, msg, );
if (ret == )
return ;
else
return -EIO;
} static struct file_operations at24cxx_fops = {
.owner = THIS_MODULE,
.read = at24cxx_read,
.write = at24cxx_write,
}; static int at24cxx_detect(struct i2c_adapter *adapter, int address, int kind)
{
printk("at24cxx_detect\n"); /* 构构一个i2c_client结构体: 以后收改数据时会用到它 */
at24cxx_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
at24cxx_client->addr = address;
at24cxx_client->adapter = adapter;
at24cxx_client->driver = &at24cxx_driver;
strcpy(at24cxx_client->name, "at24cxx");
i2c_attach_client(at24cxx_client); major = register_chrdev(, "at24cxx", &at24cxx_fops); cls = class_create(THIS_MODULE, "at24cxx");
class_device_create(cls, NULL, MKDEV(major, ), NULL, "at24cxx"); /* /dev/at24cxx */ return ;
} static int at24cxx_attach(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &addr_data, at24cxx_detect);
} static int at24cxx_detach(struct i2c_client *client)
{
printk("at24cxx_detach\n");
class_device_destroy(cls, MKDEV(major, ));
class_destroy(cls);
unregister_chrdev(major, "at24cxx"); i2c_detach_client(client);
kfree(i2c_get_clientdata(client)); return ;
} /* 1. 分配一个i2c_driver结构体 */
/* 2. 设置i2c_driver结构体 */
static struct i2c_driver at24cxx_driver = {
.driver = {
.name = "at24cxx",
},
.attach_adapter = at24cxx_attach,
.detach_client = at24cxx_detach,
}; static int at24cxx_init(void)
{
i2c_add_driver(&at24cxx_driver);
return ;
} static void at24cxx_exit(void)
{
i2c_del_driver(&at24cxx_driver);
} module_init(at24cxx_init);
module_exit(at24cxx_exit); MODULE_LICENSE("GPL");

i2c设备驱动程序

驱动13.i2c设备驱动程序的更多相关文章

  1. 驱动05.lcd设备驱动程序

    参考s3c2410fb.c总结出框架 1.代码分析 1.1 入口函数 int __devinit s3c2410fb_init(void) { return platform_driver_regis ...

  2. linux设备驱动程序-i2c(0)-i2c设备驱动源码实现

    (基于4.14内核版本) 为了梳理清楚linux内核中的i2c实现框架,从本文开始,博主将分几个章节分别解析i2c总线在linux内核中的形成过程.匹配过程.以及设备驱动程序源码实现. 在介绍linu ...

  3. linux设备驱动程序-i2c(1):i2c总线的添加与实现

    linux设备驱动程序-i2c(1):i2c总线的添加与实现 (基于4.14内核版本) 在上一章节linux设备驱动程序-i2c(0)-i2c设备驱动源码实现中,我们演示了i2c设备驱动程序的源码实现 ...

  4. linux设备驱动程序--串行通信驱动框架分析

    linux 串行通信接口驱动框架 在学习linux内核驱动时,不论是看linux相关的书籍,又或者是直接看linux的源码,总是能在linux中看到各种各样的框架,linux内核极其庞杂,linux各 ...

  5. Linux驱动之I2C总线设备以及驱动

    [ 导读] 本文通过阅读内核代码,来梳理一下I2C子系统的整体视图.在开发I2C设备驱动程序时,往往缺乏对于系统整体的认识,导致没有一个清晰的思路.所以从高层级来分析一下I2C系统的设计思路,将有助于 ...

  6. 乾坤合一~Linux设备驱动之I2C核心、总线以及设备驱动

    我思念的城市已是黄昏 为何我总对你一往情深 曾经给我快乐 也给我创伤 曾经给我希望 也给我绝望 我在遥远的城市 陌生的人群 感觉着你遥远的忧伤 我的幻想 你的忧伤,像我的的绝望,那样漫长,,,,,这是 ...

  7. Linux 驱动框架---i2c驱动框架

    i2c驱动在Linux通过一个周的学习后发现i2c总线的驱动框架还是和Linux整体的驱动框架是相同的,思想并不特殊比较复杂的内容如i2c核心的内容都是内核驱动框架实现完成的,今天我们暂时只分析驱动开 ...

  8. linux驱动之I2C

    include/linux/i2c.h struct i2c_msg;struct i2c_algorithm;struct i2c_adapter;struct i2c_client;struct ...

  9. Linux I2C设备驱动编写(二)

    在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_driver.i2c_client.三者的关系也在上一节进行了描述.应该已经算是对Linux I2C子系统有了初步 ...

随机推荐

  1. 【贪心 计数】bzoj2006: [NOI2010]超级钢琴

    这么经典的贪心我怎么现在才做啊…… Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐. 这架超级钢琴可以弹奏出n个 ...

  2. Unity基础-外部导入C# Dll(汇编集)

    外部导入C# Dll(汇编集) 使用创建一个dll工程 添加依赖的dll 导入Unity中,放入Assets的任意文件夹中 使用代码生成的dll汇编集只要"use dll的名字"引 ...

  3. Boostrap的自适应功能

    其实理解栅栏模式之后,自适应功能就简单很多了,根据浏览器的大小,Boostrap有四种栅栏类名提供使用,用法与Css样式表类名选择器样式调用是一样的: xs:col-xs-1 ~ col-xs-12, ...

  4. php 关于金额的几种计算方式

    php 关于金额的几种计算方式 平常开始开发过程中,多多少少都会遇到点关于金额的计算,比如设置返利.提现手续费.折扣啊等等诸如此类的比例,然后再计算出之后的实际的费用. 下面,以折扣为例,来实现这类计 ...

  5. MySQL_8.0.15_Windows10_X64 安装教程

    最近学习的内容涉及到MySQL的知识,所以安装一个MySQL非常有必要,参考别人的教程安装过程还算顺利,其中遇到了一些问题查了一些也解决了,这里把整个安装过程梳理一遍,给大家一个参考. 我手里的电脑是 ...

  6. 关于缺失值NaN

    在Pandas中处理NaN值  https://blog.csdn.net/Tyro_java/article/details/81396000

  7. ProC第三弹

    一.前言 我们上面已经了解Windows和Linux下的ProC开发环境,这里我们更进一步去简要介绍下ProC的预编译参数. 二.什么是预编译 预编译过程中,Pro*C/C++会自动生成C或者C++的 ...

  8. CodeForces - 899E Segments Removal (优先队列 + 链表)

    给定一个序列,每次从序列中找一个长度最大的元素相同的片段,删除它. 如果长度相同,删除最靠左边的那个片段. 问,需要删几次. 用链表处理删除片段.对于删除之后两边又能连成一个片段的那种情况,用set记 ...

  9. 线段树:CDOJ1597-An easy problem C(区间更新的线段树)

    An easy problem C Time Limit: 4000/2000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Pr ...

  10. poj 3050 地图5位数问题 dfs算法

    题意:一个5*5地图上面,从任意位置上下左右跳五次,组成一个数.问:不重复的数有多少个? 思路:dfs 从任意位置跳5次,说明每个位置都需要遍历. 组成一个数:number*10+map[dx][dy ...