当前位置:文档之家› Linux下I2C驱动架构全面分析概要

Linux下I2C驱动架构全面分析概要

Linux下I2C驱动架构全面分析概要
Linux下I2C驱动架构全面分析概要

Linux下I2C驱动架构全面分析

I2C概述

I2C是philips提岀的外设总线.

I2C只有两条线,一条串行数据线:SDA, —条是时钟线SCL,使用SCL , SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线。

因此,I2C总线被非常广泛地应用在EEPROM,实时钟,小型LCD等设备与CPU的接口中。

linux下的驱动思路

在linux系统下编写I2C驱动,目前主要有两种方法,一种是把I2C设备当作一个普通的字符设备来处理,另一种是利用linux下I2C驱动体系结构来完成。下面比较下这两种方法:

第一种方法:

优点:思路比较直接,不需要花很多时间去了解linux中复杂的I2C子系统的操作方法。

缺点:

要求工程师不仅要对I2C设备的操作熟悉,而且要熟悉I2C的适配器(I2C控制器)操作。要求工程师对I2C的设备器及I2C的设备操作方法都比较熟悉,最重要的是写岀的程序可以移植性差。

对内核的资源无法直接使用,因为内核提供的所有I2C设备器以及设备驱动都是基于I2C

子系统的格式。

第一种方法的优点就是第二种方法的缺点,

第一种方法的缺点就是第二种方法的优点。

I2C架构概述

Linux的I2C体系结构分为3个组成部分:

I2C核心:I2C核心提供了I2C总线驱动和设备驱动的注册,注销方法,I2C通信方法

(” algorithm 上层的,与具体适配器无关的代码以及探测设备,检测设备地址的上层代码等。

I2C总线驱动:I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至可以直接集成在CPU内部。

I2C设备驱动:I2C设备驱动(也称为客户驱动)是对I2C硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。

linux 驱动中i2c 驱动架构

Algorithm

12匚_Achpte 「 ]

-- ------ ifi 问抽軀

上图完整的描述了 linux i2c 驱动架构,虽然I2C 硬件体系结构比较简单,但是i2c 体系结构在 linux 中的实现却相当复杂。

那么我们如何编写特定i2c 接口器件的驱动程序?就是说上述架构中的那些部分需要我们完成, 而哪些是linux 内核已经完善的或者是芯片提供商已经提供的?

架构层次分类

第一层:提供i2c adapter 的硬件驱动,探测、初始化i2c adapter (如申请i2c 的io 地址和 中断号),驱动soc 控制的i2c adapter 在硬件上产生信号(start 、stop 、ack )以及处理i2c 中 断。覆盖图中的硬件实现层

Appl

用户 访问

driver

驱动层

与待走的阴匚愉2保件相关的代码 < --------- 厠4实规控制层

12C AdaptorZ

SOC 芯片内部

的)2G 模块

121? Device 1

IK I J L -vice 2

J2C Device3,-挂lldZC 总线上的貝休番件

diiv^r

L licm

d m Ji

i2c 核心层

hdidwaTe

第二层:提供i2c adapter 的algorithm ,用具体适配器的xxx_xferf() 函数来填充

i2c_algorithm 的master_xfer 函数指针,并把赋值后的i2c_algorithm 再赋值给i2c_adapter

的algo指针。覆盖图中的访问抽象层、i2c核心层

第三层:实现i2c设备驱动中的i2c_driver 接口,用具体的i2c device 设备的attach_adapter() 、

detach_adapter() 方法赋值给i2c_driver 的成员函数指针。实现设备device

与总线(或者叫adapter )的挂接。覆盖图中的driver驱动层

第四层:实现i2c设备所对应的具体device的驱动,i2c_driver 只是实现设备与总线的挂接,

而挂接在总线上的设备则是千差万别的,所以要实现具体设备device的write()、read()、ioctl()

等方法,赋值给file_operations ,然后注册字符设备(多数是字符设备)。覆盖图中的driver驱动

第一层和第二层又叫i2c总线驱动(bus),第三第四属于i2c设备驱动(device driver)。

在linux驱动架构中,几乎不需要驱动开发人员再添加bus,因为linux内核几乎集成所有总线

bus,如usb、pci、i2c等等。并且总线bus中的(与特定硬件相关的代码)已由芯片提供商编写完成,例如三星的s3c-2440 平台i2c 总线bus 为/drivers/i2c/buses/i2c-s3c2410.c

第三第四层与特定device相干的就需要驱动工程师来实现了。

Linux下I2C体系文件构架

在Linux内核源代码中的driver目录下包含一个i2c目录

.built-

in.o.cmci

slq

i2e-

smbu^it 「]

J2c-

dev.OnCmd

n-fig

Makefili

J2c-

二广弓i广;亡.c上

i

rore r o,cmcl

i2c- bcardinfc^o ;

2c-

F2c- bo

jrdinfo.c

i2c-core.c 这个文件实现了I2C核心的功能以及/proc/bus/i2c* 接口。

i2c-dev.c 实现了I2C适配器设备文件的功能,每一个I2C适配器都被分配一个设备。通过适配器访设备时的主设备号都为89,次设备号为0-255。I2c-dev.c 并没有针对特定的设备而设计,

只是提供了通用的read(),write(), 和ioctl()等接口,应用层可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄存器,并控制I2C设备的工作方式。

busses文件夹这个文件中包含了一些I2C总线的驱动,如针对S3C2410 ,S3C2440 ,S3C6410等处理器的I2C控制器驱动为i2c-s3c2410.c.

algos文件夹实现了一些I2C总线适配器的algorithm.

重要的结构体

i2c_driver

[cpp] view pla in copy

1. struct i2c_driver {

2. unsigned int class ;

3. int (*attach_adapter)( struct i2c_adapter *); // 依附i2c_adapter 函数指

4. int (*detach_adapter)( struct i2c_adapter *); // 脱离i2c_adapter 函数指

5. int (*probe)( struct i2c_client *, const struct i2c_device_id *);

6. int (*remove)( struct i2c_client *);

7. void (*shutdown)( struct i2c_client *);

8. int (*suspend)( struct i2c_client *, pm_message_t mesg);

9. int (*resume)( struct i2c_client *);

10. void (*alert)( struct i2c_client *, unsigned int data);

11. int (*command)( struct i2c_client *client, unsigned int cmd, void *arg); // 命令列表

12. struct device_driver driver;

13. const struct i2c_device_id *id_table; // 该驱动所支持的设备ID 表

14. int (*detect)( struct i2c_client *, struct i2c_board_info *);

15. const unsigned short *address_list;

16. struct list_head clients;

17. };

i2c_clie nt

[cpp] view pla in copy

1. struct i2c_client {

unsigned short flags ;// 标志

2.

3. unsigned short addr; //低7位为芯片地址

4. char name[I2C_NAME_SIZE]; //设备名称

5. struct i2c_adapter *adapter; // 依附的i2c_adapter

6. struct i2c_driver *driver; // 依附的i2c_driver

7. struct device dev; // 设备结构体 8. int irq; //设备所使用的结构体 9. struct list_head detected; // 链表头 10.

};

i2c_adapter

[cpp] view pla in copy

1. struct i2c_adapter {

2. struct module *owner; // 所属模块

3. unsigned int id; //algorithm 的类型,定义于 i2c-id.h,

4. unsigned int class ;

5. const struct i2c_algorithm *algo; // 总线通信方法结构体指针

6. void *algo_data; //algorithm 数据

7. struct rt_mutex bus_lock; //控制并发访问的自旋锁

8. int timeout; 9. int retries;

// 重试次数

10. struct device dev; // 适配器设备 11. int nr; 12. char name[48];

// 适配器名称

13. struct completion dev_released; // 用于同步 14. struct list_head userspace_clients; //client 链表头

15.

};

i2c_algorithm

[cpp] view pla in copy

1. struct i2c_algorithm {

各结构体的作用与它们之间的关系

i2c_adapter 与 i2c_algorithm

2.

int (*master_xfer)( struct i2c_adapter *adap,

struct i2c_msg *msgs, int num);

3.

传输函数指针 int (*smbus_xfer)( struct i2c_adapter *adap, u16 addr,unsigned short flags,

〃I2C

char r

ead_write,u8 command, 4. i2c_smbus_data *data); 5.

u32 (*functionality)( 6.

};

int size, union

//smbus 传输函数指针 struct i2c_adapter *);

//返回适配器支持的功能

i2c_adapter 对应与物理上的一个适配器,而 i2c_algorithm 对应一套通信方法,一个i2c 适

配器需要i2c_algorithm 中提供的(i2c_algorithm 中的又是更下层与硬件相关的代码提供)通信

函数来控制适配器上产生特定的访问周期。 缺少i2c_algorithm 的i2c_adapter 什么也做不了,因

此i2c_adapter

中包含其使用i2c_algorithm

的指针。

i2c_algorithm 中的关键函数 master_xfer () 用于产生i2c 访问周期需要的start stop ack 信

号,以i2c_msg (即i2c 消息)为单位发送和接收通信数据。

i2c_msg 也非常关键,调用驱动中的发送接收函数需要填充该结构体

[cpp] view pla in copy

1. struct i2c_msg {

2.

u16 addr; /* slave address */ /* msg length

*/

/* pointer to msg data

i2c_driver 和 i2c_client

i2c_driver 对应一套驱动方法,其主要函数是 attach_adapter () 和 detach_client () i2c_client

对应真实的i2c 物理设备device ,每个i2c 设备都需要一个i2c_client 来描述

i2c_driver 与i2c_client 的关系是一对多。一个i2c_driver 上可以支持多个同等类型的

i2c_clie nt. i2c_adapter

和口 i2c_client

i2c_adapter 和i2c_client 的关系与i2c 硬件体系中适配器和设备的关系一致,即 i2c_client 依附于i2c_adapter ,由于一个适配器上可以连接多个 i2c 设备,所以i2c_adapter

中包含依附于它

的i2c_client 的链表。

从i2c 驱动架构图中可以看岀,linux 内核对i2c 架构抽象了一个叫核心层core 的中间件,它分 离了设备驱动device driver

和硬件控制的实现细节(如操作 i2c 的寄存器),core 层不但为上面

的设备驱动提供封装后的内核注册函数,而且还为小面的硬件事件提供注册接口(也就是 i2c 总线注

册接口),可以说core 层起到了承上启下的作用。

具体分析

先看一下i2c-core 为外部提供的核心函数(选取部分),i2c-core 对应的源文件为i2c-core.c

位于内核目录 /driver/i2c/i2c-core.c

[cpp] view pla in copy _

3. __u16 flags;

4. __u16 len;

5. __u8 *buf;

*/

6. };

1. EXP0RT_SYMB0L(i2c_add_adapter);

2. EXPORT_SYMBOL(i2c_del_adapter);

3. EXPORT_SYMBOL(i2c_del_driver);

4. EXP0RT_SYMB0L(i2c_attach_client);

5. EXPORT_SYMBOL(i2c_detach_client);

6.

6. EXP0RT_SYMB0L(i2c_transfer);

i2c_transfer() 函数:i2c_transfer() 函数本身并不具备驱动适配器物理硬件完成消息交互的能力,它只是寻找到i2c_adapter 对应的i2c_algorithm ,并使用i2c_algorithm 的master_xfer() 函数真正的驱动硬件流程,代码清单如下,不重要的已删除。

[cpp] view plain copy

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

2. {

3. int ret;

4. if (adap->algo->master_xfer) { // 女口果master_xfer 函数存在,则调用,否则返回错误

5. ret = adap->algo->master_xfer(adap,msgs,num); //这个函数在硬件相关的代码中给

algorithm 赋值

6. return ret;

7. } else {

8. return -ENOSYS;

9. }

10. }

当一个具体的client被侦测到并被关联的时候,设备和sysfs文件将被注册。

相反的,在client被取消关联的时候,sysfs文件和设备也被注销,驱动开发人员在开发i2c设

备驱动时,需要调用下列函数。程序清单如下

[cpp] view pla in copy

1. int i2c_attach_client( struct i2c_client *client)

2. {

3. ...

4. device_register(&client->dev);

5. device_create_file (&client->dev, & dev_attr_client_name);

6. ...

7. return 0;

8. }

9.

10.

9. [cpp] view plaincopy

10. int i2c_detach_client( struct i2c_client *client)

11. {

12. ...

13. device_remove_file(&client->dev, &dev_attr_client_name);

14. device_unregister (&client->dev);

Linux下I2C驱动介绍

1、I2C概述 I2C是philips公司提供的外设总线,I2C有两条数据线,一条是串行数据线SDA、一条是时钟线SCL,使用SDA和SCL实现了数据的交换,便于布线。I2C总线方便用在EEPROM、实时钟、小型LCD等与CPU外部的接口上。 2、Linux下的驱动思路 Linux系统下编写I2c驱动主要有两种方法:一种是把I2C当做普通字符设备来使用;另一种利用Linux下驱动的体系结构来实现。 第一种方法: 优点:思路比较直接,不用花费大量时间去了解Linux系统下I2C体系结构 缺点:不仅对I2C设备操作要了解,还有了解I2C的适配器操作 不仅对I2C设备器和设备操作需要了解,编写的驱动移植性差,内核 提供的I2C设备器都没有用上。 第二种方法: 第一种的优点就是第二种的缺点,第一种的缺点就是第二种的优点。 3、I2C框架概述 Linux的I2C体系结构分为3部分: 1)I2C核心I2C核心提供了I2C总线驱动和设备驱动的注册和注销的方法,I2C 通信方法(algorithm)上层,与具体适配器无关的代码,检测设备上层的代 码等。 2)I2C总线驱动I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可以直接受CPU来控制。 3)I2C设备驱动I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备端挂在受CPU控制的适配器上,通过I2C适配器与CPU交换数据。 Linux下的I2C体系结构: 1)Linux下的I2C体系结构 4、I2C设备驱动编写方法 首先让我们明白适配器驱动的作用是让我们能够通过它发出标准的I2C时序,在linux

内核源代码中driver/I2C/buss包含一些适配器的驱动,例如s3c2410的驱动I2C-s3c2410.c,适配器被加载到内核中,接下的任务就是实现设备驱动的编写。编写设备驱动的方法主要分为两种方法: 第一种:利用设备提供的I2C-dev.c来实现I2C适配器设备文件,然后通过上层应用程序来操作I2C设备器来控制I2C设备。 第二种:为I2C设备独立编写一个设备驱动 注意:第二种方法不能用设备提供的I2C-dev.c 5、I2C系统下的文件架构 在linux下driver下面有个I2C目录,在I2C目录下包含以下文件和文件夹 1)I2C-core.c 这个文件实现I2C核心功能以及/proc/bus/I2C*接口 2)I2C-dev.c 实现I2C适配器设备文件的功能,每个I2C适配器被分配一个设备,通过 适配器访问设备的时候,主设备号是89,此设备号是0-255. I2C-dev.c并没有针对特定设备而设计,只提供了read() write()和ioctl()等接口,应用层可以通过这些接口访问挂在适配器上的I2C设备存储空间和寄存器,并控制I2C设备的工作方式。 3)Chips 这个文件下面包含特定的I2C设备驱动。 4)Busses 这个文件包含一些I2C总线驱动。 5)Algos文件夹下实现了I2C总线适配器的algorithm 6、重要结构体 1)在内核中的I2C.h这个头文件中对I2C_driver;I2C_client;I2C_adapter和I2C_algorithm 这个四个结构体进行了定义。理解这4个结构体的作用十分关键。 i2c_adapter结构体 struct i2c_adapter { struct module *owner; //所属模块 unsigned int id; //algorithm的类型,定义于i2c-id.h, unsigned int class; const struct i2c_algorithm *algo; //总线通信方法结构体指针 void *algo_data;//algorithm数据 struct rt_mutex bus_lock; //控制并发访问的自旋锁 int timeout; int retries; //重试次数 struct device dev; //适配器设备 int nr; char name[48]; //适配器名称 struct completion dev_released; //用于同步 struct list_head userspace_clients; //client链表头

Linux下I2C驱动架构全面分析概要

Linux下I2C驱动架构全面分析 I2C概述 I2C是philips提岀的外设总线. I2C只有两条线,一条串行数据线:SDA, —条是时钟线SCL,使用SCL , SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线。 因此,I2C总线被非常广泛地应用在EEPROM,实时钟,小型LCD等设备与CPU的接口中。 linux下的驱动思路 在linux系统下编写I2C驱动,目前主要有两种方法,一种是把I2C设备当作一个普通的字符设备来处理,另一种是利用linux下I2C驱动体系结构来完成。下面比较下这两种方法: 第一种方法: 优点:思路比较直接,不需要花很多时间去了解linux中复杂的I2C子系统的操作方法。 缺点: 要求工程师不仅要对I2C设备的操作熟悉,而且要熟悉I2C的适配器(I2C控制器)操作。要求工程师对I2C的设备器及I2C的设备操作方法都比较熟悉,最重要的是写岀的程序可以移植性差。 对内核的资源无法直接使用,因为内核提供的所有I2C设备器以及设备驱动都是基于I2C 子系统的格式。 第一种方法的优点就是第二种方法的缺点, 第一种方法的缺点就是第二种方法的优点。 I2C架构概述 Linux的I2C体系结构分为3个组成部分: I2C核心:I2C核心提供了I2C总线驱动和设备驱动的注册,注销方法,I2C通信方法 (” algorithm 上层的,与具体适配器无关的代码以及探测设备,检测设备地址的上层代码等。 I2C总线驱动:I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至可以直接集成在CPU内部。 I2C设备驱动:I2C设备驱动(也称为客户驱动)是对I2C硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。

Linux驱动之i2c用户态调用

一、概述 I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL.正因为这样,它方便了工程人员的布线. 二、用户态实现设备驱动 在Linux内核代码文件i2c-dev.c中实现了I2C适配器设备文件的功能,针对每个适配器生成一个主设备号为89的设备节点(次设备号为0-255),I2c-dev.c并没有针对特定的设备而设计,只是提供了通用的read(),write(),和ioctl()等文件操作接口,在用户空间的应用层就可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄存器,并控制I2C设备的工作方式。 i2c适配器的设备节点是/dev/i2c-x,其中x是数字。由于适配器编号是动态分配的(和注册次序有关),所以想了解哪一个适配器对应什么编号,可以查看/sys/class/i2c-dev/目录下的文件内容。 三、用户态调用 3.1、i2c-dev 用户空间操作i2c,需要包含以下头文件。 打开适配器对应的设备节点

i2c-dev为打开的线程建立一个i2c_client,但是这个i2c_client并不加到i2c_adapter的client链表当中。他是一个虚拟的临时client,当用户打开设备节点时,它自动产生,当用户关闭设备节点时,它自动被释放。 3.2、ioctl() 查看include/linux/i2c-dev.h文件,可以看到i2c支持的IOCTL命令1.#define I2C_RETRIES0x0701 /*设置收不到ACK时的重试次数*/ 2.#define I2C_TIMEOUT0x0702/*设置超 时时限的jiffies*/ 3.#define I2C_SLAVE0x0703/ *设置从机地址*/ 4.#define I2C_SLAVE_FORCE0x0706/*强制设置从机地 址*/ 5.#define I2C_TENBIT0x0704/* 选择地址位长:=0for7bit,!=0for10bit*/ 6.#define I2C_FUNCS0x0705/* 获取适配器支持的功能*/ 7.#define I2C_RDWR0x0707 /*Combin ed R/W transfer(one STOP only)*/ 8.#define I2C_PEC0 x0708/* !=0to use PEC with SMBus*/ 9.#define I2C_SMBUS0x0720 /*SMBus transfer*/

Linux操作系统期末复习资料

电信2012级《Linux操作系统》期末复习提纲第1章概述 操作系统的概念与功能 操作系統的概念: 1.操作系统是计算机系统的一种基本软件,它直接管理和控制计算机的硬件和软件资源,合理地调度资源,使之得到充分的利用;并为用户使用这些资源提供一个便当的操作环境和优良的用户界面。 2.从资源角度看,操作系统是管理和控制计算机资源的软件。 3.从用户角度看,操作系统是用户与计算机的接口。 操作系統的功能: 1.处理器管理:在多道程序间分配和调度CPU,协调各程序的运行。 2.存储器管理:对内存储器进行分配、保护和扩充。 3.设备管理:对设备进行有用地管理和分配,并控制设备完成I/O操作。 4.文件管理:管理文件的存储和检索操作,并对文件实施共享、保密和保护措施。 5.用户接口:提供使用界面,便当用户使用系统功能。 Linux系统的特点 1.继承UNIX优秀品质,具有出色的性能和稳定性; 2.遵照GPL许可,自由软件; 3.符合POSIX标准,兼容性好; 4.适用于各种硬件平台,可移植性好; 5.网络功能强大;

6.安全性好。第2章Linux操作基础 命令的格式; 命令名[选项1] [选项2] ... [参数1] [参数2] ... 简单命令的功能与用法:echo、who、date、cal 文件系统概念: 文件命名与通配符 1.文件的命名:Linux文件名的最大长度是255个字符,通常由字母、数字、‘.’、‘_’和‘-’组成。以‘.’开头的文件是隐含文件。 2.文件名中不能含有‘/ ’字符和空字符‘\0’,因为它们对Linux内核具有分外含义。如‘/ ’表示根目录或路径分隔符。 3.文件名中不应含有以下字符,因为它们对Shell具有分外含义:; | < > ` “ “$ ! % & * ? \ ( ) [ ] 文件类型及表示法 1.普通文件(-):包括文本文件、数据文件、可执行的二进制程序等。 2.目录文件(d):一种分外的文件,用于构成文件系统的分层树型结构。 每个目录文件中至少包括两个文件,“..”表示上一级目录,“.”表示该目录本身。 3.设备文件:一种分外文件,Linux系统利用它们来标识各个设备驱动器,核心使用它们与硬件设备通信。有两类特别的设备文件:字符设备(c)和块设备(b)。 文件(包括目录)权限的含义及表示法(字符和数字表示法)

linux下iic(i2c)读写AT24C02

https://www.doczj.com/doc/211734635.html,/jammy_lee/ https://www.doczj.com/doc/211734635.html, linux下iic(i2c)读写AT24C02 linux驱动2010-02-09 16:02:03 阅读955 评论3 字号:大中小订阅 linux内核上已有iic的驱动,因此只需要对该iic设备文件进行读写则能够控制外围的iic器件。这里以AT24C02为对象,编写一个简单的读写应用程序。iic设备文件在我的开发板上/dev/i2c/0 ,打开文件为可读写。AT24C02的器件地址为0x50 ,既是iic总线上从器件的地址,每次只读写一字节数据。 /************************************************************/ //文件名:app_at24c02.c //功能:测试linux下iic读写at24c02程序 //使用说明: (1) // (2) // (3) // (4) //作者:jammy-lee //日期:2010-02-08 /************************************************************/ //包含头文件 #include #include #include #include #include #include #include

#include #include #include //宏定义 #define Address 0x50 //at24c02地址 #define I2C_RETRIES 0x0701 #define I2C_TIMEOUT 0x0702 #define I2C_SLAVE 0x0703 //IIC从器件的地址设置 #define I2C_BUS_MODE 0x0780 typedef unsigned char uint8; uint8 rbuf[8] = {0x00}; //读出缓存 uint8 wbuf[8] = {0x01,0x05,0x06,0x04,0x01,0x01,0x03,0x0d}; //写入缓存int fd = -1; //函数声明 static uint8 AT24C02_Init(void); static uint8 i2c_write(int fd, uint8 reg, uint8 val); static uint8 i2c_read(int fd, uint8 reg, uint8 *val); static uint8 printarray(uint8 Array[], uint8 Num); //at24c02初始化 static uint8 AT24C02_Init(void) { fd = open("/dev/i2c/0", O_RDWR); //允许读写 if(fd < 0) { perror("Can't open /dev/nrf24l01 \n"); //打开iic设备文件失败 exit(1);

I2C接口的输入与输出驱动的

I2C接口的输入与输出驱动的PCF8574- pcf8574采用I2C接口,有8个准双向口,可以和外部电路连接,来实现输入输出功能,可以用来对口线进行扩展 有几点需要注意 1.某位作为输入的时候,必须首先置为高电平 2.地址是0100 A2 A1 A0 R/W 3.最多可以扩展8片 4.低电流损耗,静态电流10uA,驱动电流比较大,而且有索存功能,能够驱动LED 发光管 5.带有外部中断输出,低电平有效 我作了一个电路,其中P7-P4作为输入检测开关状态,P3-P0作为输出来驱动LED 灯 程序如下 #include "reg51.h" #define SETBIT(VAR,Place) (VAR|=(1<

unsigned char IC_Re_Time; unsigned char IC_Err_Flag; void Timer0_Init(void) { TMOD=0x00;//timer0工作定时器方式0,13位技术 TH0=0x1e;//5ms TL0=0x0c;//5ms TR0=1;//启动时钟0 ET0=1;//允许时钟0进行中断 EA=1;//开放所有中断 } void Delay(void) { unsigned char i; for(i=0;i<=10;i++) { ; } } unsigned char VALBIT(unsigned int Val,unsigned char Bit) { unsigned int Buf; Buf=0x0001; if(Bit) Buf<<=Bit;

Linux操作系统概述

第1章Linux操作系统概述 Linux操作系统是目前发展最快的操作系统,从1991年诞生到现在的二十多年间,Linux逐步完善和发展。Linux操作系统在服务器、嵌入式等方面获得了长足的发展,并在个人操作系统方面有着大范围的应用,这主要得益于其开放性。本章对Linux的发展进行介绍,主要包括如下内容: ?Linux发展的历史,以时间为主线对Linux的诞生进行介绍; ?分析Linux和UNIX操作系统的异同; ?介绍常用的几种Linux发行版本的特点; ?对Linux操作系统的系统架构进行简单的介绍; ?介绍GNU通用公共许可证及其特点。 通过本章的阅读,读者可以对Linux的发展历史和Linux操作系统的基本特点有一个简单的认识。 1.1 Linux发展历史 Linux操作系统于1991年诞生,目前已经成为主流的操作系统之一。其版本从开始的0.01版本到目前的2.6.28.4版本经历了二十多年的发展,从最初的蹒跚学步的“婴儿”成长为目前在服务器、嵌入式系统和个人计算机等多个方面得到广泛应用的操作系统。 1.1.1 Linux的诞生和发展 Linux的诞生和发展与个人计算机的发展历程是紧密相关的,特别是随着Intel的i386个人计算机的发展而逐步成熟。在1981年之前没有个人计算机,计算机是大型企业和政府部门才能使用的昂贵设备。IBM公司在1981年推出了个人计算机IBM PC,从而造成个人计算机的发展和普及。刚开始的时候,微软帮助IBM公司开发的MS-DOS操作系统在个人计算机中占有统治地位。随着IT行业的发展,个人计算机的硬件价格虽然逐年在下降,但是软件特别是操作系统的价格一直居高不下。 与个人计算机对应,在大型机上的主流操作系统是UNIX,而UNIX操作系统对操作系统的发展有诸多障碍:

iic设备驱动程序.doc

IIC设备驱动程序 IIC设备是一种通过IIC总线连接的设备,由于其简单性,被广泛引用于电子系统中。在现代电子系统中,有很多的IIC设备需要进行相互之间通信 IIC总线是由PHILIPS公司开发的两线式串行总线,用于连接微处理器和外部IIC设备。IIC设备产生于20世纪80年代,最初专用与音频和视频设备,现在在各种电子设备中都广泛应用 IIC总线有两条总线线路,一条是串行数据线(SDA),一条是串行时钟线(SCL)。SDA负责数据传输,SCL负责数据传输的时钟同步。IIC设备通过这两条总线连接到处理器的IIC总线控制器上。一种典型的设备连接如图: 与其他总线相比,IIC总线有很多重要的特点。在选择一种设备来完成特定功能时,这些特点是选择IIC设备的重要依据。 主要特点: 1,每一个连接到总线的设备都可以通过唯一的设备地址单独访问 2,串行的8位双向数据传输,位速率在标准模式下可达到100kb/s;快速模式下可以达到400kb/s;告诉模式下可以达到3.4Mb/s 3,总线长度最长7.6m左右 4,片上滤波器可以增加抗干扰能力,保证数据的完成传输 5,连接到一条IIC总线上的设备数量只受到最大电容400pF的限制 6,它是一个多主机系统,在一条总线上可以同时有多个主机存在,通过冲突检测方式和延时等待防止数据不被破坏。同一时间只能有一个主机占用总线 IIC总线在传输数据的过程中有3种类型的信号:开始信号、结束信号、和应答信号 >>开始信号(S): 当SCL为高电平时,SDA由高电平向低电平跳变,表示将要开始传输数据 >>结束信号(P):当SCL为高电平时,SDA由低电平向高电平跳变,表示结束传输数据 >>响应信号(ACK): 从机接收到8位数据后,在第9个周期,拉低SDA电平,表示已经收到数据。这个信号称为应答信号 开始信号和结束信号的波形如下图:

实例解析linux内核I2C体系结构(2)

实例解析linux内核I2C体系结构(2) 华清远见刘洪涛四、在内核里写i2c设备驱动的两种方式 前文介绍了利用/dev/i2c-0在应用层完成对i2c设备的操作,但很多时候我们还是习惯为i2c设备在内核层编写驱动程序。目前内核支持两种编写i2c驱动程序的方式。下面分别介绍这两种方式的实现。这里分别称这两种方式为“Adapter方式(LEGACY)”和“Probe方式(new style)”。 (1)Adapter方式(LEGACY) (下面的实例代码是在2.6.27内核的pca953x.c基础上修改的,原始代码采用的是本文将要讨论的第2种方式,即Probe方式) ●构建i2c_driver static struct i2c_driver pca953x_driver = { .driver = { .name= "pca953x", //名称 }, .id= ID_PCA9555,//id号 .attach_adapter= pca953x_attach_adapter, //调用适配器连接设备 .detach_client= pca953x_detach_client,//让设备脱离适配器 }; ●注册i2c_driver static int __init pca953x_init(void) { return i2c_add_driver(&pca953x_driver); } module_init(pca953x_init); ●attach_adapter动作 执行i2c_add_driver(&pca953x_driver)后会,如果内核中已经注册了i2c适配器,则顺序调用这些适配器来连接我们的i2c设备。此过程是通过调用i2c_driver中的attach_adapter方法完成的。具体实现形式如下: static int pca953x_attach_adapter(struct i2c_adapter *adapter) { return i2c_probe(adapter, &addr_data, pca953x_detect); /* adapter:适配器 addr_data:地址信息 pca953x_detect:探测到设备后调用的函数 */ } 地址信息addr_data是由下面代码指定的。 /* Addresses to scan */ static unsigned short normal_i2c[] = {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,I2C_CLIENT_END}; I2C_CLIENT_INSMOD;

TI-I2C驱动

TI-I2C驱动 一、与I2C驱动相关的文件分成两部分: 1)应用层接口部分: 程序在svn中的路径如下: 在https://dareglob-971006/svn/eocOS/branches/eocOS_v4/branches/bsp/user/i2c目录下,i2ctest.c文件,提供了lm75a_temp_read()方法,用来读取LM75A设备温度寄存器中的温度信息的功能。 2)内核驱动部分: 内核位于svn中的路径如下: https://dareglob-971006/svn/eocOS/branches/eocOS_v4/branches/bsp/kernel (1)总线驱动: i2c-davinci.c:在内核目录中driver/i2c/busses目录下,适用于TI的I2C总线驱动程序。I2C总线驱动是对I2C硬件体系结构中适配器端的实现。 (2)I2C驱动代码核心: i2c-core.c:在内核目录中driver/i2c/目录下,是I2C代码的核心,用于沟通虚拟文件系统与底层实现。该文件提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。 (3)I2C设备驱动: lm75.c:在内核目录中driver/hwmon目录下,是针对LM75A以及其他能兼容的温度传感器的设备驱动。I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。二、I2C简要工作流程 1)在总线驱动初始化时候,当通过Linux内核源代码/driver/base/platform.c文件中定义platform_driver_register()函数注册platform_driver结构体时,其中probe指针指向的davinci_i2c_probe()函数将被调用,以初始化适配器硬件。 2)而davinci_i2c_remove()函数则完成与davinci_i2c_probe()相反的功能。用于内存和中断等系统资源的释放和注销。 3)总线驱动i2c-davinci.c中,定义了i2c_davinci_xfer函数。该函数是I2C总线通信传输函数。并且I2C适配器对应的i2c_algorithm结构体实例为i2c_davinci_algo,其中的master_xfer函数指针指向i2c_davinci_xfer函数。 4)当设备被打开,并且用户开始读操作时,会调用设备驱动lm75.c中show_temp()函数,该函数会调用i2c-core.c中的i2c_smbus_xfer()函数,i2c_smbus_xfer()函数会检查适配器对应的i2c_algorithm结构体中是否注册了smbus_xfer函数(目前i2c_davinci_algo中未注册smbus_xfer函数),程序会调用i2c_smbus_xfer_emulated()函数,最终,还是会调用标准的I2C总线通信函数master_xfer(),由于master_xfer 已经指向i2c_davinci_xfer函数,所以会调用总线驱动i2c-davinci.c中的i2c_davinci_xfer函数来读取信息。 三、接口函数 1)应用层接口: Int lm75a_temp_read(float *temp) 读取lm75a 温度 2)内核中:lm75.c文件 static ssize_t show_temp(struct device *dev, struct device_attribute *da,char *buf)

i2c总线原理

I2C总线原理 ?什么是I2C总线? I2C即Inter IC,由Philips公司开发,是当今电子设计中应用非常广泛的串行总线之一,主要用于电压、温度监控,EEPROM数据的读写,光模块的管理等。 I2C总线只有两根线,SCL和SDA,SCL即Serial Clock,串行参考时钟,SDA即Serial Data,串行数据。 ?I2C总线的速率能达到多少? 标准模式下:100Kbps 快速模式下:400Kbps 高速模式下:3.4Mbps I2C总线结构如下图所示: 如上图所示,I2C是OC或OD输出结构,使用时必须在芯片外部进行上拉,上拉电阻R的取值根据I2C总线上所挂器件数量及I2C总线的速率有关,一般是标准模式下R选择10kohm,快速模式下R选取1kohm,I2C总线上挂的I2C器件越多,就要求I2C的驱动能力越强,R的取值就要越小,实际设计中,一般是先选取4.7kohm上拉

电阻,然后在调试的时候根据实测的I2C波形再调整R的值。 ?I2C总线上最多能挂多少个I2C器件? I2C总线上允许挂接I2C器件的数量由两个条件决定: 1).I2C从设备的地址位数。I2C标准中有7位地址和10位地址两种。如果是7位地址,允许挂接的I2C器件数量为:27=128,如果是10位地址,允许挂接的I2C 器件数量为:210=1024,一般I2C总线上挂接的I2C器件不会太多,所以现在几乎所有的I2C器件都使用7位地址。 2).挂在I2C总线上所有I2C器件的管脚寄生电容之和。I2C总线规范要求,I2C 总线容性负载最大不能超过470pF。 ?I2C总线是如何工作的? 1).I2C总线传输的特点。 I2C总线按字节传输,即每次传输8bits二进制数据,传输完毕后等待接收端的应答信号ACK,收到应答信号后再传输下一字节。等不到ACK信号后,传输终止。空闲情况下,SCL和SDA都处于高电平状态。 2).如何判断一次传输的开始? 如上图所示,I2C总线传输开始的标志是:SCL信号处于高电平期间,SDA信号出现一个由高电平向低电平的跳变。 3).如何判断一次传输的结束? 如上图所示,I2C总线传输结束的标志是:SCL信号处于高电平期间,SDA信号出现一个由低电平向高电平的跳变。跟开始标识正好相反。 4).什么样的I2C数据才是有效的。

I2C 24CXX驱动程序(真正实用 全)

#define _24cXX_H /* Includes ----------------------------------------------------------------*/ #include "stm32f10x.h" #include "value.h" //#include "stdbool.h" /* Define ------------------------------------------------------------------*/ /* EEPROM Addresses defines */ //注:32 64 的字地址是16位2个字节如果使用32或64请简单修改驱动即可 #define WC24cXX 0x00 // 器件地址写#define RC24cXX 0x01 // 器件地址读 #define USE_24C08 //使用24C08 #ifdef USE_24C02 #define MAXSIZE24cXX 256 // 总容量Bytes //级联时请修改本参数和硬件驱动 #define BLOCK_SIZE 256 // 块容量Bytes #define I2C_PAGESIZE 8 // 8个字节每页 #endif #ifdef USE_24C04 #define MAXSIZE24cXX 512 // 总容量Bytes //级联时请修改本参数和硬件驱动 #define BLOCK_SIZE 256 // 块容量Bytes #define I2C_PAGESIZE 16 // 16个字节每页 #endif #ifdef USE_24C08 #define MAXSIZE24cXX 1024 // 总容量Bytes //级联时请修改本参数和硬件驱动 #define BLOCK_SIZE 256 // 块容量Bytes #define I2C_PAGESIZE 16 // 16个字节每页 /* user define */ #define YBCV_ADDR_0 0x0000 //定义仪表控制数据结构体的EEPROM存储地址0 #define YBCV_ADDR_1 0x0200 //定义仪表控制数据结构体的EEPROM存储地址1 #define EEPROM_VERIFY YB_CTRL_V ALE_SIZE //EEPROM仪表通道修正参数存储地址 #endif #ifdef USE_24C16 #define MAXSIZE24cXX 2048 // 总容量Bytes #define I2C_PAGESIZE 16 // 16个字节每页 #endif

I2C设备与驱动的关联

I2C设备与驱动的关联 作者:leeoo 联系方式:neu_linuxer@https://www.doczj.com/doc/211734635.html, 在Linux操作系统中,驱动程序的加载分为两种:内核启动时自动加载和用户手动加载;硬件设备也可以采用两种方式添加到系统中:在系统启动前及系统运行时的热插拨。下面,我们以arm体系结构下的at91处理器中的I2C控制器为例,介绍一下硬件设备及相关的驱动程序是如何绑定及松绑的。 1.平台驱动注册过程 1.1 at91_i2c_init()函数 在文件drivers/i2c/busses/i2c-at91.c中,定义了结构体struct platform_driver并进行了初始化,通过使用module_init()宏进行声明,当模块被加载到内核时会调用 at91_i2c_init()函数。在此函数中,调用了platform_driver_register()函数来完成注册。 static struct platform_driver at91_i2c_driver = { .probe = at91_i2c_probe, .remove = __devexit_p(at91_i2c_remove), .suspend = at91_i2c_suspend, .resume = at91_i2c_resume, .driver = { .name = "at91_i2c", .owner = THIS_MODULE, }, }; static int __init at91_i2c_init(void) { return platform_driver_register(&at91_i2c_driver); } 1.2 platform_driver_register()函数 在文件drivers/base/platform.c中,实现并导出了platform_driver_register()函数,以便使其他模块中的函数可以调用此函数。它在完成简单的包装后,调用了driver_register()函数,完成了从平台实现到Linux内核实现的过渡。 在此,我们需要关注一下platform_match()和platform_drv_probe()函数。 platform_match() 函数确定驱动与设备的关联,而platform_drv_probe()函数会在随后介绍的函数中被调用。 //比较驱动信息中的name与设备信息中的name两者是否一致 static int platform_match(struct device * dev, struct device_driver * drv) { struct platform_device *pdev = container_of(dev, struct platform_device, dev); return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); } struct bus_type platform_bus_type = { .name = "platform", .dev_attrs = platform_dev_attrs, .match = platform_match, .uevent = platform_uevent, .suspend = platform_suspend, .suspend_late = platform_suspend_late, .resume_early = platform_resume_early, .resume = platform_resume, }; EXPORT_SYMBOL_GPL(platform_bus_type); /** * platform_driver_register * @drv: platform driver structure */ int platform_driver_register(struct platform_driver *drv) { drv->driver.bus = &platform_bus_type;

Linux_I2C总线分析(主要是probe的方式)1

Linux I2C 总线浅析 ㈠ Overview 内核空间层次! i2c adapter 是一个struct, 用来抽象一个物理i2c bus ,而且还和linux 设备驱动架构柔和在一起.. 如果只说硬件的话,就是在CPU内部集成的一个I2C控制器(提供给用户的就是那几个register),硬件上并没的所谓的adapter,client这些东东,,adapter和client都是linux 驱动软件抽象出来的东西 资料帖子: i2c_algorithm { /* If an adapter algorithm can't do I2C-level access, set master_xfer to NULL. If an adapter algorithm can do SMBus access, set smbus_xfer. If set to NULL, the SMBus protocol is simulated

using common I2C messages */ /* master_xfer should return the number of messages successfully processed, or a negative value on error */ i nt (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); i nt (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data); /* To determine what the adapter supports */ u32 (*functionality) (struct i2c_adapter *); }; /* * i2c_adapter is the structure used to identify a physical i2c bus along * with the access algorithms necessary to access it. */ struct i2c_adapter { s truct module *owner; u nsigned int id; u nsigned int class; /* classes to allow probing for */ c onst struct i2c_algorithm *algo; /* the algorithm to access the bus */ v oid *algo_data; /* data fields that are valid for all devices */ u8 level; /* nesting level for lockdep */ s truct mutex bus_lock; i nt timeout; /* in jiffies */ i nt retries; s truct device dev; /* the adapter device */ i nt nr; c har name[48]; s truct completion dev_released; }; Linux的I2C体系结构分为3个组成部分: 1·I2C核心: I2C核心提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法(即“algorithm”)上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。这部分是与平台无关的。 2·I2C总线驱动: I2C总线驱动是对I2C硬件体系结构中适配器端的实现。I2C总线驱动主要包含了I2C适配

51单片机I2C总线驱动程序

51单片机I2C总线驱动程序 SI2I2C 总线是PHLIPS 公司推出的一种串行总线,是具备多主机系统所需 的包括总线裁决和高低速器件同步功能的高性能串行总线。I2C 总线只有两根 双向信号线。一根是数据线SDA,另一根是时钟线SCL。 一.I2C 系统结构每个接到I2C 总线上的器件都有唯一的地址。主机与其它器 件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。由 总线上接收数据的器件则为接收器。 二.数据位的有效性规定I2C 总线进行数据传送时,时钟信号为高电平期间, 数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线 上的高电平或低电平状态才允许变化。 三.字节传送与应答每一个字节必须保证是8 位长度。数据传送时,先传送最 高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有 9 位)。 四.驱动程序#define uchar unsigned char#define uint unsigned int#define somenop() _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_()sbit SCL=P2;sb it SDA=P2;123451.起始信号和终止信号 SCL 线为高电平期间,SDA 线由高电平向低电平的变化表示起始信号;SCL 线为高电平期间,SDA 线由低电平向高电平的变化表示终止信号。 起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用 的状态;在终止信号产生后,总线就处于空闲状态 void I2C_Start() //起始{SCL=1;somenop();SDA=1;somenop(); SDA=0;somenop();SCL=0;somenop();}void I2C_Stop() //终止{ SDA=0;somenop();SCL=1;somenop();SDA=1;somenop();}12345678910111213141

Linux操作系统发展及其特点概述

Linux操作系统发展及其特点概述 Unix操作系统的诞生 Linux 操作系统是UNIX 操作系统的一个克隆版本。UNIX 操作系统是美国贝尔实验室的Ken.Thompson和Dennis Ritchie于1969年夏在DEC PDP-7 小型计算机上开发的一个分时操作系统。当时Ken Thompson 为了能在闲置不用的PDP-7 计算机上运行他非常喜欢的星际旅行(Space travel)游戏,在1969 年夏天乘他夫人回家乡加利福尼亚渡假期间,在一个月内开发出了Unix 操作系统的原型。当时使用的是BCPL 语言(基本组合编程语言),后经Dennis Ritchie 于1972 年用移植性很强的C 语言进行了改写,使得UNIX 系统在大专院校得到了推广。 Linux 操作系统的诞生与发展 Linux 是芬兰赫尔辛基大学高才生Linus Benedict Torvalds在1991年4月编写出来的。Linux内核的创建是由芬兰赫尔辛基的Linus Torvalds个人努力完成的。1991年底,Linus Torvalds首次在Internet上发布T基于Intel386体系结构Linux源代码,许多大专院校的学生和科研机构的研究人员纷纷把它作为学习和研究的对象。他们不断改进Linux版本,不断地为Linux增加新的功能Linux逐渐成为一个基本稳定、可靠、功能比较完善的操作系统,由于Linux操作系统从产生直至现在的发展一直在Internet这个摇篮中,伴随着网络概念的不断膨胀,“网络一代”的迅速崛起,它急速地发展着。 Linux诞生后的几个月里,Torvalds在不断地听取试用者的反馈的同时,仍然潜心于不断地改进程序,使其功能更强大、性能更稳定。到了1991年底,已经陆续推出了0.02版、0.03版、0.1版、0.11版。也许由于Torvalds从小深受其祖父(一名统计学教授,Torvalds少年时代学习的电脑启蒙者)和信仰共产主义的父亲的影响,加上本身淡泊金钱的个性,所以尽管当时Torvalds已欠了大约五千美元的学生货款,但在开始发布源代码时,他就制定了这样的版权规则: (1)任何人可以免费使用该操作系统,但不得将其作为商品出售; (2)任何人可以对该操作系统进行修改,但必须将其修改以源代码的形式公开;(3)如果不同意以上规定,任何人无权对其进行复制或从事任何行为。 软件按其分发方式可以划分为三种模式,即商业软件(Commercial Software)、共享软件(Share Software)和自由软件(Free Software)。商业软件的代表是美国微软公司(Microsoft)的Windows操作系统,用户必须先购买商业软件许可证才能使用软件,并且不能得到软件的源代码,也不能对软件进行任何逆向工程以得到源代码,即使软件存在缺陷用户也无权对软件进行任何修改或改进,否则将被认为侵犯版权。共享软件在分发时,用户可以先试用后付费,通常不提供软件源代码,如果超过试用期没有购买而仍使用,将被认为侵犯版权,目前许多通过网络分发销售的软件都采用这种方式,著名的软件有代理服务器软件WinGate。 自由软件在分发时必须向用户公开源代码,通常用户可以通过某种途径(如网络下载)免费得到其分发版,但用户如果付费的话将得到完善的服务和文档。自由软件的出现给人们带来很多的好处。首先,免费的软件可给用户节省相当一笔费用。其次,源代码公开和可自由修改吸引了众多的开发者参与软件的查错与改

相关主题
文本预览
相关文档 最新文档