Linux I2C总线

Linux I2C总线(一)I2C驱动框架

Linux I2C总线(二)I2C设备驱动编写方法

Linux I2C总线(二)I2C设备驱动编写方法

文章目录

  • Linux I2C总线(二)I2C设备驱动编写方法
    • 一、I2C驱动的注册
    • 二、I2C设备的注册
      • 2.1 静态注册
      • 2.2 动态注册
      • 2.3 在用户空间注册
    • 三、I2C数据传输
    • 四、I2C驱动模板

一、I2C驱动的注册

1.设置I2C驱动

static const struct i2c_device_id my_i2c_dev_id[] = {{ "my_i2c_dev", 0},  /* 设备名字 */{ }
};static struct i2c_driver my_i2c_drv = {.driver = {.name = "no", /* 这个名字不重要 */.owner = THIS_MODULE,},.probe      = my_i2c_drv_probe, /* 当匹配到i2c设备时调用 */.remove      = my_i2c_drv_remove, /* 当卸载i2c设备或驱动时调用 */.id_table = my_i2c_dev_id, /* 这个结构体中的名字很重要 */
};

其中的my_i2c_dev_id非常重要,数组元素中的名称指明了支持的I2C设备

要定义号probe函数和remove函数,注册时发现有设备和驱动匹配,probe函数会被调用,在卸载匹配的驱动或者设备的时候,remove函数会被调用

2.注册I2C驱动

通过i2c_add_driver来注册一个I2C驱动

static int __init my_i2c_drv_init(void)
{i2c_add_driver(&my_i2c_drv_drv);return 0;
}

二、I2C设备的注册

注册I2C设备有多种方法,下面介绍三种

2.1 静态注册

静态注册表示只可以在内核启动时就讲i2c设备注册进内核

  • 定义一个i2c_board_info对象

    static struct i2c_board_info  my_i2c_dev_info = {I2C_BOARD_INFO("my_i2c_dev", 0x2d), //名字,设备地址
    };
    
  • 通过i2c_register_board_info注册

    /** busnum:哪一条总线,也就是选择哪一个i2c控制器* info:i2c设备信息数组* n:数组有几项*/
    i2c_register_board_info(int busnum, struct i2c_board_info const * info, unsigned n);
    

2.2 动态注册

动态注册可以在内核运行期间注册,也就是可以应用在加载驱动模块中

  • 定义一个i2c_board_info对象

    static struct i2c_board_info  my_i2c_dev_info = {I2C_BOARD_INFO("my_i2c_dev", 0x2d), //名字,设备地址
    };
    
  • 通过i2c_new_device来动态注册

    /** adap:指定i2c设备器,以后访问设备的时候,使用过哪一个设备器(i2c主机控制器)去访问* info:指定i2c设备信息*/
    struct i2c_client *
    i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
    

2.3 在用户空间注册

  • 注册设备

    # echo my_i2c_dev 0x55 > sys/devices/platform/s3c2440-i2c.0/i2c-0/new_device
    
  • 注销设备

    echo 0x55 > sys/devices/platform/s3c2440-i2c.0/i2c-0/delete_device
    

三、I2C数据传输

I2C数据传输通过i2c_transfer

/** adap:i2c适配器* msgs:消息数据* num:数组的个数*/
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)

i2c_msg的定义如下

struct i2c_msg {__u16 addr;  //从设备地址__u16 flags; //读或写__u16 len; //消息的长度__u8 *buf;   //消息
};

例如要发送下列的时序

/* 定义 i2c_msg 结构体 */
struct i2c_msg msg[2]; char val[10]/* 填充msg */
msg[0].addr = my_i2c_client->addr; /* 这个client在probe函数中得到的 */
msg[0].flags = 0; /* 0表示写,1表示读 */
msg[0].buf = 0x80; /* 写:要发送的数据地址,读:读取到的数据存放的地址 */
msg[0].len = 1; /* 想要传输的字节数 *//* 填充msg */
msg[1].addr = my_i2c_client->addr; /* 这个client在probe函数中得到的 */
msg[1].flags = 1; /* 1表示读 */
msg[1].buf = val; /* 读到的数据存在这里 */
msg[1].len = 4; /* 想要读取的字节数 *//* 传输数据 */
i2c_transfer(my_i2c_client->adapter, msg, 2); /* 有两个msg */

四、I2C驱动模板

I2C设备

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/slab.h>static struct i2c_board_info my_i2c_dev_info = {I2C_BOARD_INFO("my_i2c_dev", 0x50), /* 这个名字和地址很重要 */
};static struct i2c_client *my_i2c_client;static int i2c_dev_init(void)
{struct i2c_adapter *i2c_adap;i2c_adap = i2c_get_adapter(0); /* 得到i2c设备器,i2c设备在哪条总线上 */my_i2c_client = i2c_new_device(i2c_adap, &my_i2c_dev_info);i2c_put_adapter(i2c_adap);return 0;
}static void i2c_dev_exit(void)
{ i2c_unregister_device(my_i2c_client);
}module_init(i2c_dev_init);
module_exit(i2c_dev_exit);
MODULE_LICENSE("GPL");

I2C驱动

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/earlysuspend.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/ioc4.h>
#include <linux/io.h>#include <linux/proc_fs.h>#include <mach/gpio.h>
#include <mach/hardware.h>
#include <plat/gpio-cfg.h>
#include <plat/irqs.h>static struct i2c_client *my_i2c_client;static const struct i2c_device_id my_i2c_dev_id[] = {{ "my_i2c_dev", 0 },{ }
};static int my_i2c_drv_probe(struct i2c_client *client,const struct i2c_device_id *id)
{/* 记录下i2c设备client */my_i2c_client = client;    /* 在这里注册字符设备,创建设备节点 *//* 这里为了简单,只是打印一句话而已 */printk("my_i2c_ddrv_probe\n");return 0;
}static int my_i2c_drv_remove(struct i2c_client *client)
{/* 在这里卸载字符设备 *//* 这里为了简单,只打印一句话 */printk("my_i2c_dev_remove\n")    return 0;
}static struct i2c_driver my_i2c_drv = {.driver = {.name  = "jt_ts",.owner = THIS_MODULE,},.probe     = my_i2c_drv_probe,.remove     = my_i2c_drv_remove,.id_table  = my_i2c_dev_id,
};static int __init my_i2c_drv_init(void)
{i2c_add_driver(&my_i2c_drv);return 0;
}static void __exit my_i2c_drv_exit(void)
{i2c_del_driver(&my_i2c_drv);return;
}module_init(my_i2c_drv_init);
module_exit(my_i2c_drv_exit);MODULE_LICENSE("GPL");

Linux I2C总线(二)I2C设备驱动编写方法相关推荐

  1. 【基于Linux系统设备树的SPI驱动编写方法】

    文章目录 前言 一.SPI驱动编写 1.修改设备树  a.设备树文件是什么?  b.设备树怎么改? 2.编写驱动 二.完善和测试 1.编译和应用程序  a.编译 && 拷贝到开发板命令 ...

  2. Linux i2c总线(2) - I2C核心层

    1. I2C 核心层初始化 这一部分向系统注册了一个名为i2c的总线类型. static int __init i2c_init(void) {int retval;retval = bus_regi ...

  3. linux设备驱动编写基础

    Linux设备驱动编写基础 一.linux中的驱动是以模块的形式存在的,这样就大大提高了驱动的灵活性,linux内核模块的程序结构如下: l  模块加载函数(必须):module_init() l  ...

  4. IIC(I2C)总线上的设备其地址如何定义?通俗易懂

    IIC(I2C)总线上的设备其地址如何定义? IIC总线 一般串行数据通讯都有时钟和数据之分,有异步和同步之别. 有单线,双线和三线等. I2C肯定是2线的(不算地线). I2C协议确实很科学,比3/ ...

  5. Linux内核学习-字符设备驱动学习(二)

    在Linux内核学习-字符设备驱动学习(一)中编写字符设备驱动的一种方法,但是需要手动创建设备节点. 有没有能够自动的创建设备节点的呢? 有!使用class_create()和device_creat ...

  6. 深入学习Linux摄像头(二)v4l2驱动框架

    深入学习Linux摄像头系列 深入学习Linux摄像头(一)v4l2应用编程 深入学习Linux摄像头(二)v4l2驱动框架 深入学习Linux摄像头(三)虚拟摄像头驱动分析 深入学习Linux摄像头 ...

  7. [linux]platform总线机制与wtd驱动开发

    Linux之platform总线机制与wtd驱动开发 1.概述: 通常在Linux中,把SoC系统中集成的独立外设单元(如:I2C.IIS.RTC.看门狗等)都被当作平台设备来处理. 从Linux2. ...

  8. 标准linux4.4--驱动开发(二)GPIO驱动编写

    标准linux4.4--驱动开发(二)GPIO驱动编写 简介 介绍GPIO DTS配置 在驱动文件中关联DTS的配置 驱动说明 中断 复用 FAQs 简介 1.什么是linux内核模块 在linux中 ...

  9. 一起分析Linux系统设计思想——05字符设备驱动框架剖析(四)

    在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习.我的使命就是过滤掉大量的垃圾信息,将知识体系化,以短平快的方式直 ...

最新文章

  1. 高通:全球NB-IoT/eMTC最新现状
  2. python分类算法_python数据挖掘中的分类算法有哪些?
  3. C# SQLite 数据库操作语句与文件视图管理器
  4. 如何定义一个只能在堆上(栈上)生成对象的类?
  5. win8信息服务器不可用怎么办,win8系统下开机提示OneDrive选项此服务现在不可用请稍后再试怎么办...
  6. SQL 2005 字段备注获取
  7. 数仓系列 | Flink 窗口的应用与实现
  8. html表格上下居中 w3c,DIV+CSS实现表格功能(不支垂直居中)
  9. Netty学习(三)高性能之ByteBuf源码解析(篇幅较长)
  10. 项目管理 计算机仿真,刘宝林老师【项目管理】《挑战埃及》沙盘课程内容分享...
  11. 大数据项目实战二之电信大数据项目
  12. 优秀课程案例:使用Scratch制作俄罗斯方块哈利·波特魔法消除版!
  13. 开机netmeeting已删除_NetMeeting
  14. Excel如何快速生成二维码图片?
  15. 华为HG8120C光猫换天邑TEWA-600AGM(百兆换千兆)的过程记录
  16. 海伯利安发布首个区块链红包RP
  17. 用好这 43 款 Chrome 插件,让你开发学习一下子好轻松!
  18. 王春亮推拿学堂:如何成为一名高级调理师
  19. 知识存储之Apache Jena
  20. 《JavaSE-第七章》之抽象的类-实例的对象-合理的封装

热门文章

  1. POJ 1417 True Liars(带权并查集+DP)
  2. 【加水印】如何批量加文字水印和图片水印,如何批量添加文件名水印到图片里?图片的名称批量写到图片上面?
  3. ARM GICv3 GIC代码分析
  4. 人工智能课后作业_python实现广度优先遍历搜索(BFS)(附源码)
  5. CFD网格你应该了解的常识
  6. Java中继承和实现的区别【单继承,多实现】
  7. Linux常用命令及演示
  8. ChatGPT使用案例之自然语言处理
  9. MoviePy - 中文文档4-MoviePy实战案例-给MoviePy Logo做一个闪动的阴影效果
  10. 阿ken的HTML、CSS的学习笔记_浮动与定位(笔记六)