Linux驱动之i2c用户态调用

合集下载

Linux下I2C驱动介绍

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设备。

Linux I2C驱动完全分析2

Linux I2C驱动完全分析2

Linux I2C驱动完全分析(二)先说一下,本文中有个疑惑,一直没有搞懂,写在这里,望高人指点一二,不胜感激!#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */这里I2C_FUNC_PROTOCOL_MANGLING 是什么意思?为什么定义这些东东?看了注释也不太理解。

求解释!3. I2C总线驱动代码分析s3c2440的总线驱动代码在i2c-s3c2410.c中。

照例先从init看起。

static int __init i2c_adap_s3c_init(void){return platform_driver_register(&s3c24xx_i2c_driver);}在init中只是调用了平台驱动注册函数注册了一个i2c的平台驱动s3c24xx_i2c_driver。

这个驱动是一个platform_driver的结构体变量。

注意这里不是i2c_driver结构体,因为i2c_driver是对设备的驱动,而这里对控制器的驱动要使用platform_driverstatic struct platform_driver s3c24xx_i2c_driver = {.probe = s3c24xx_i2c_probe,.remove = s3c24xx_i2c_remove,.suspend_late = s3c24xx_i2c_suspend_late,.resume = s3c24xx_i2c_resume,.id_table = s3c24xx_driver_ids,.driver = {.owner = THIS_MODULE,.name = "s3c-i2c",},};同样的,重要的函数还是那几个:probe,remove,suspend_late,resume。

linux下S3C2440–I2C驱动学习之四“i2c

linux下S3C2440–I2C驱动学习之四“i2c

linux下S3C2440–I2C驱动学习之四“i2c我们进入I2C驱动的最后一个小节,在这个小节里,我们主要探讨 i2c_algorithm 数据结构和i2c-core.c 的一些主要函数及其作用。

i2c_algorithm 结构体struct i2c_algorithm {int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,unsigned short flags, char read_write,u8 command, int size, union i2c_smbus_data *data);u32 (*functionality) (struct i2c_adapter *);};一个i2c 适配器上的i2c 总线通信方法由其驱动程序提供的i2c_algorithm 数据结构描述,由algo 指针指向。

i2c_algorithm 数据结构即为i2c_adapter 数据结构与具体i2c 适配器的总线通信方法的中间层,正是这个中间层使得上层的i2c 框架代码与与具体i2c 适配器的总线通信方法无关,从而实现了i2c 框架的可移植性和重用性。

当安装具体i2c 适配器的驱动程序时由相应驱动程序实现具体的i2c_algorithm 数据结构,其中的函数指针指向操作具体i2c 适配器的代码。

master_xfer/smbus_xfer 指针指向i2c 适配器驱动程序模块实现的i2c 通信协议或者smbus 通信协议。

在用户进程通过i2c-dev 提供的/dev/i2c/%d 设备节点访问i2c 设备时,最终是通过调用master_xfer 或者smbus_xfer 指向的方法完成的。

i2c-core.ci2c.h 和i2c-core.c 为i2c 框架的主体,提供了核心数据结构的定义、i2c 适配器驱动和设备驱动的注册、注销管理,i2c 通信方法上层的、与具体适配器无关的代码、检测设备地址的上层代码等;i2c-dev.c 用于创建i2c 适配器的/dev/i2c/%d 设备节点,提供i2c 设备访问方法等。

嵌入式Linux的I2C设备驱动程序的操作系统分析

嵌入式Linux的I2C设备驱动程序的操作系统分析

嵌入式Linux的I2C设备驱动程序的操作系统分析
0 引言
 由于I2C总线的通用性,Linux作为一款优秀的嵌入式操作系统,也必须
要对其要有很好的支持。

在Linux内核源码中对I2C总线的驱动是基于总线设备驱动模型的,其驱动程序用到了特殊的几个数据结构,对I2C总线协议进行了更抽象更通用的定义,极大的增加了设备驱动的可移植性。

要编写出自己的I2C 设备驱动程序,必须对这种内核I2C总线驱动的架构有深刻的理解。

 1 I2C总线的硬件构成
 I2C 总线协议只有两条总线线路,一条是串行数据线(SDA),一条是串行时钟线(SCL)。

SDA 负责数据的传输,SCL 负责数据传输的时钟同步。

I2C 设备通过这两条总线连接到处理器的I2C总线控制器上,不同设备之间通过7 位地址来区别,而且数据的传输是双向的,方向的确定由1位二进制数确定,地址位加方向位是操作I2C 设备的惟一标示,I2C 设备与CPU 的连接如图1所示。

 I2C 总线上有3 种类型的信号,分别是:开始信号,结束信号和应答信号。

这些信号都是由SDA和SCL上的电平变化来表示的。

 开始信号(S):当SCL为高电平时,SDA由高电平向低电平跳变,表示开始传输数据。

 结束信号(P):当SCL为高电平时,SDAY由低电平向高电平跳变,表示结束传输数据。

 相应信号(ACK):从机接收到8位数据后,在第9个时钟周期,拉低SDA。

LinuxI2C驱动--用户态驱动简单示例

LinuxI2C驱动--用户态驱动简单示例

LinuxI2C驱动--⽤户态驱动简单⽰例1. Linux内核⽀持I2C通⽤设备驱动(⽤户态驱动:由应⽤层实现对硬件的控制可以称之为⽤户态驱动),实现⽂件位于drivers/i2c/i2c-dev.c,设备⽂件为/dev/i2c-02. I2C通⽤设备驱动以字符设备注册进内核的static const struct file_operations i2cdev_fops = {.owner = THIS_MODULE,.llseek = no_llseek,.read = i2cdev_read,.write = i2cdev_write,.unlocked_ioctl = i2cdev_ioctl,.open = i2cdev_open,.release = i2cdev_release,};res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops);3. 对设备⽂件进⾏读写时,可以调⽤read、write或者ioctl等⽅法,他们都是通过调⽤函数i2c_transfer来实现对I2C设备的操作的int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num){int ret;/* REVISIT the fault reporting model here is weak:** - When we get an error after receiving N bytes from a slave,* there is no way to report "N".** - When we get a NAK after transmitting N bytes to a slave,* there is no way to report "N" ... or to let the master* continue executing the rest of this combined message, if* that's the appropriate response.** - When for example "num" is two and we successfully complete* the first message but get an error part way through the* second, it's unclear whether that should be reported as* one (discarding status on the second message) or errno* (discarding status on the first one).*/if (adap->algo->master_xfer) {#ifdef DEBUGfor (ret = 0; ret < num; ret++) {dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, ""len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)'R' : 'W', msgs[ret].addr, msgs[ret].len,(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");}#endifif (in_atomic() || irqs_disabled()) {ret = mutex_trylock(&adap->bus_lock);if (!ret)/* I2C activity is ongoing. */return -EAGAIN;} else {mutex_lock_nested(&adap->bus_lock, adap->level);}ret = adap->algo->master_xfer(adap,msgs,num);mutex_unlock(&adap->bus_lock);return ret;} else {dev_dbg(&adap->dev, "I2C level transfers not supported\n");return -EOPNOTSUPP;}}4. i2c_transfer通过代码可以看出,i2c_transfer 通过调⽤相应的 adapter 的 master_xfer ⽅法实现的,⽽ master_xfer 主要是根据 struct i2c_msg 类型的msgs来进⾏处理的。

linux i2c驱动

linux i2c驱动

linux i2c驱动1. i2c-dev interfaceI2C dev-interface通常,i2c设备由某个内核驱动控制。

但是在用户空间,也可以访问某个I2C设备:你需要加载i2c-dev模块。

每个被注册的i2c适配器(控制器)会获得一个数字号,从0开始。

你可以检查/sys/class/i2c-dev,来查看适配器对应哪个数字号。

你也可以通过命令"i2cdetect -l"获取你的当前系统的所有I2c适配器的列表。

i2cdetct是i2c-tool包中的一个工具。

i2c设备文件是字符设备,主设备号是89,次设备号的分配如上所述。

设备文件名通常被规定为"i2c-%d"(i2c-0, i2c-1, ...,i2c-10, ...)i2c设备文件是字符设备,主设备号是89,次设备号的分配如上所述。

设备文件名通常被规定为"i2c-%d"(i2c-0, i2c-1, ...,i2c-10, ...).所有256个次设备号都保留给i2c使用。

C example=========假定你要在你的C应用程序中访问i2c适配器。

第一件事情就是包含头文件"#include<linux/i2c-dev.h>"。

注意,存在两个"i2c-dev.h"文件: 一个属于Linux kernel,用于内核驱动中;一个由i2c-tools发布,用于用户程序。

显然,这里需要使用第二个i2c-dev.h文件。

现在,你需要确定访问哪个适配器。

你需要通过查看/sys/class/i2c-dev/或者运行"i2cdetect -l"确定。

适配器号时常是动态分配的,你无法预先假定某个值。

因为它们甚至会在系统重启后变为不同的值。

下一步,打开设备文件,如下:int file;int adapter_nr = 2; /*probably dynamically determined */char filename[20];snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);file = open(filename, O_RDWR);if (file < 0) {/* ERROR HANDLING; you can check errno to see what went wrong */ exit(1);}当你打开设备后,你必须明确说明你相与哪个设备地址进行通信:int addr = 0x40;if (ioctl(file, I2C_SLAVE, addr) < 0) {/* ERROR HANDLING; you can check errno to see what went wrong */ exit(1);}Well, 你现在准备好与I2C设备通信了。

Linux2.6内核i2c驱动架构

Linux2.6内核i2c驱动架构

三. i2c驱动架构分析 i2c驱动架构分析
2、硬件抽象层 、 i2c-core.h和i2c-core.c为其主体框架代码,提供了 为其主体框架代码, 和 为其主体框架代码 核心数据结构的定义、 适配器驱动和设备驱动的注 核心数据结构的定义、i2c适配器驱动和设备驱动的注 注销管理等API。其为硬件平台无关层,向下屏 册、注销管理等 。其为硬件平台无关层, 蔽了物理总线适配器的差异, 蔽了物理总线适配器的差异,定义了统一的访问策略 和接口;其向上提供了统一的接口,以便I2C设备驱 和接口;其向上提供了统一的接口,以便 设备驱 动通过总线适配器进行数据收发。 动通过总线适配器进行数据收发。 3、用户接口层 、 i2c设备驱动层为用户接口层,其为用户提供了通 设备驱动层为用户接口层, 设备驱动层为用户接口层 总线访问具体设备的接口。 过I2C总线访问具体设备的接口。 I2c设备驱动主要包 总线访问具体设备的接口 设备驱动主要包 含了数据结构i2c_driver和i2c_client,我们需要根据 含了数据结构 和 , 具体设备实现其中的成员函数。 具体设备实现其中的成员函数。
Linux2.6内核i2c驱动架构
目录
一.i2c简介 i2c简介 二.驱动相关知识介绍 三.i2c驱动架构分析 i2c驱动架构分析
一. i2c简介 i2c简介
I2C 协议
I2C协议是有PHILIPS公司在1992年最先提出, PHILIPS公司专利。 I2C协议是有PHILIPS公司在1992年最先提出,乃PHILIPS公司专利。只要购 协议是有PHILIPS公司在1992年最先提出 公司专利 Philips的I2C元件同时传递了一个在Philips的 元件同时传递了一个在Philips 专利下, 买Philips的I2C元件同时传递了一个在Philips的I2C 专利下,在I2C 系统使用 元件使系统符合由Philips定义的I2C规范的许可证。任何使用I2C Philips定义的I2C规范的许可证 I2C的元件都必须 元件使系统符合由Philips定义的I2C规范的许可证。任何使用I2C的元件都必须 得到PHILIPS公司的授权。 PHILIPS公司的授权 得到PHILIPS公司的授权。 I2C总线的特征 I2C总线的特征 只要求两条总线线路一条串行数据线(SDA)一条串行时钟线(SCL)。 1.只要求两条总线线路一条串行数据线(SDA)一条串行时钟线(SCL)。 同时SDL SCL都是双向线路 分别通过上拉电阻连接到正的电源电压。 SDL和 都是双向线路, 同时SDL和SCL都是双向线路,分别通过上拉电阻连接到正的电源电压。 .每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主 2 .每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主 从机关系软件设定地址;主机可以作为主机发送器或主机接收器。 机/从机关系软件设定地址;主机可以作为主机发送器或主机接收器。 3.它是一个真正的多主机总线 它是一个真正的多主机总线, 3.它是一个真正的多主机总线,如果两个或更多主机同时初始化数据传输 可以通过冲突检测和仲裁防止数据被破坏。 可以通过冲突检测和仲裁防止数据被破坏。 串行的8 位双向数据传输位速率在标准模式下可达100kbit/s 100kbit/s。 4. 串行的8 位双向数据传输位速率在标准模式下可达100kbit/s。快速模 式下可达400kbit/s 高速模式下可达3.4Mbit/s 400kbit/s。 3.4Mbit/s。 式下可达400kbit/s。高速模式下可达3.4Mbit/s。 5.片上的滤波器可以滤去总线数据线上的毛刺波, 5.片上的滤波器可以滤去总线数据线上的毛刺波,保证数据完整 片上的滤波器可以滤去总线数据线上的毛刺波

linux 应用访问i2c设备原理

linux 应用访问i2c设备原理

linux 应用访问i2c设备原理Linux是一个开放源代码的操作系统内核,支持许多硬件设备的驱动程序。

其中一种常用的硬件接口是I2C(Inter-Integrated Circuit)总线。

I2C总线允许多个设备通过共享同一组线路进行通信,这些设备可以是传感器、存储器、转换器等外围设备。

Linux提供了一种访问I2C设备的机制,通过此机制,应用程序可以与I2C设备进行通信。

在本文中,将介绍Linux应用程序访问I2C设备的原理及步骤。

1.硬件连接:首先,需要将I2C设备连接到主机上。

I2C总线由两根线路组成,即SDA(Serial Data Line)和SCL(Serial Clock Line)。

SDA用于传输数据,SCL用于提供时钟信号。

I2C设备通常具有一个I2C地址,用于在总线上识别不同的设备。

2. Linux内核驱动:Linux内核提供了I2C总线的驱动程序,用于与I2C设备进行通信。

通常,这些驱动程序已经包含在内核中,不需要单独安装。

但是,可能需要通过编译内核时打开相应的配置选项来启用I2C支持。

3. I2C设备驱动:每个I2C设备都需要一个设备驱动程序,用于与应用程序进行交互。

这些驱动程序通常由设备制造商提供,也有一些常见的驱动程序包含在Linux内核中。

设备驱动程序将设备上的读写操作映射到I2C总线上的读写操作。

4.用户空间库:为了更方便地编写应用程序,Linux提供了一些用户空间库,用于访问I2C设备。

其中最常用的库是libi2c-dev,它提供了一组API函数,可以通过文件描述符进行I2C通信。

此库通常已经安装在Linux系统中,可以通过编译时链接到应用程序中。

5.应用程序访问:应用程序需要通过打开I2C总线来访问I2C设备。

首先,需要获取I2C总线的文件描述符,可以通过调用open()函数并传递文件路径来实现。

常见的I2C总线路径为"/dev/i2c-x",其中"x"是总线号。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、概述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_PEC0x0708/* !=0to use PEC with SMBus*/9.#define I2C_SMBUS0x0720/*SMBus transfer*/例如:1、设置重试次数:ioctl(fd, I2C_RETRIES,m);设置适配器收不到ACK时重试的次数为m。

默认的重试次数为12、设置超时ioctl(fd, I2C_TIMEOUT,m);设置SMBus的超时时间为m,单位为jiffies。

3、设置从机地址ioctl(fd, I2C_SLAVE,addr);ioctl(fd, I2C_SLAVE_FORCE, addr);在调用read()和write()函数之前必须设置从机地址。

这两行都可以设置从机的地址,区别是第二行无论内核中是否已有驱动在使用这个地址都会成功,第一行则只在该地址空闲的情况下成功。

由于i2c-dev 创建的i2c_client不加入i2c_adapter的client列表,所以不能防止其它线程使用同一地址,也不能防止驱动模块占用同一地址。

4、设置地址模式ioctl(file,I2C_TENBIT,select)如果select不等于0选择10bit地址模式,如果等于0选择7bit模式,默认7位模式。

3.3数据包i2c发送或者接收一次数据都以数据包( struct i2c_msg )封装addr是设备从地址。

flags是通信标志,发送数据为0,接收数据为I2C_M_RD。

len是数据长度buf是传输数据3.4、接受数据设备驱动中我们通常调用/driver/i2c/i2c-core.c 定义的接口i2c_master_recv 来接收一次数据。

通过i2c_transfer调用数据包。

int i2c_master_recv(struct i2c_client *client, char *buf ,int count){struct i2c_adapter *adap=client->adapter; // 获取adapter信息struct i2c_msg msg; // 定义一个临时的数据包int ret;msg.addr = client->addr; // 将从机地址写入数据包msg.flags = client->flags & I2C_M_TEN; // 将从机标志并入数据包msg.flags |= I2C_M_RD; // 将此次通信的标志并入数据包msg.len = count; // 将此次接收的数据字节数写入数据包msg.buf = buf;ret = i2c_transfer(adap, &msg, 1); // 调用平台接口接收数据/* If everything went ok (i.e. 1 msg transmitted), return #bytestransmitted, else error code. */return (ret == 1) ? count : ret; // 如果接收成功就返回字节数}EXPORT_SYMBOL(i2c_master_recv);参考驱动i2c_master_recv()函数封装属于自己用户态的接受函数。

用户态是通过ioctl(handle->fd, I2C_RDWR, &data)函数与i2c从设备进行数据交互。

主要有2个步骤:首先是写入需要读取的寄存器的地址,然后从寄存器中读取数据。

需要2个数据包。

如下:3.5、发送数据设备驱动中我们通常调用/driver/i2c/i2c-core.c 定义的接口i2c_master_send来发送一次数据。

通过i2c_transfer调用数据包int i2c_master_send(struct i2c_client *client,const char *buf ,int count){int ret;struct i2c_adapter *adap=client->adapter; // 获取adapter信息struct i2c_msg msg; // 定义一个临时的数据包msg.addr = client->addr; // 将从机地址写入数据包msg.flags = client->flags & I2C_M_TEN; // 将从机标志并入数据包msg.len = count; // 将此次发送的数据字节数写入数据包msg.buf = (char *)buf; // 将发送数据写入数据包ret = i2c_transfer(adap, &msg, 1); // 调用平台接口发送数据/* If everything went ok (i.e. 1 msg transmitted), return #bytestransmitted, else error code. */return (ret == 1) ? count : ret; // 如果发送成功就返回字节数}EXPORT_SYMBOL(i2c_master_send);参考驱动i2c_master_send()函数封装属于自己用户态的接受函数。

用户态是通过ioctl(handle->fd, I2C_RDWR, &data)函数与i2c从设备进行数据交互。

每次要写入两个字节数据主要包括写入的寄存器地址和要写入的数据。

只需发送一次数据包。

如下:3.6、使用案例1.#include<stdio.h>2.#include<linux/i2c.h>3.#include<linux/i2c-dev.h>4.#include<fcntl.h>5.#include<stdio.h>6.#include<unistd.h>7.#include<sys/ioctl.h>8.#include<string.h>9.#include<stdlib.h>10.11.#define I2C_FILE_NAME "/dev/i2c-1"12.#define I2C_ADDR 0x4013.14.int fd;15.16.int i2c_open()17.{18.fd = open(I2C_FILE_NAME, O_RDWR);19.if(fd < 0){20.perror("Unable to open i2c control file");21.return 1;22.}23.}24.25.int i2c_write(int fd, unsigned char dev_addr, unsigned char reg_addr,unsigned char val)26.{27.int ret;28.unsigned char buf[2];29.struct i2c_rdwr_ioctl_data data;30.struct i2c_msg messages;31.32.buf[0] = reg_addr;33.buf[1] = val;34.messages.addr = dev_addr; //device address35.messages.flags = 0; //write36.messages.len = 2;37.messages.buf = buf; //data address38.39.data.msgs = &messages;40.data.nmsgs = 1;41.if(ioctl(fd, I2C_RDWR, &data) < 0){42.printf("write ioctl err\n");43.return 1;44.}leep(1000);46.47.return 1;48.}49.50.int i2c_read(int fd, unsigned char addr, unsigned char reg, unsigned char *val)51.{52.int ret;53.struct i2c_rdwr_ioctl_data data;54.struct i2c_msg messages[2];55.56.messages[0].addr = addr; //device address57.messages[0].flags = 0; //write58.messages[0].len = sizeof(reg);59.messages[0].buf = &reg; //data address60.61.messages[1].addr = addr; //device address62.messages[1].flags = I2C_M_RD; //read63.messages[1].len = sizeof(val);64.messages[1].buf = val;65.66.data.msgs = messages;67.data.nmsgs = 2;68.if(ioctl(fd, I2C_RDWR, &data) < 0){69.printf("read ioctl err\n");70.return 1;71.}72.73.return 0;74.}75.76.int main()77.{78.int i;79.unsigned char buf[4];80.unsigned char val[] = {0x04, 0x05, 0x06, 0x07};81.82.i2c_open();83.84.85.for(i =0; i< 4; i++)86.i2c_write(fd, I2C_ADDR, i, val[i]);87.88.89.memset(buf, 0x00, sizeof(buf));90.for(i = 0; i < sizeof(buf); i++){91.if(i2c_read(fd, I2C_ADDR, i, &buf[i])){92.printf("Unable to get register!\n");93.}94.}95.96.for(i=0; i< 4;i++)97.printf("buf[%d]=%d\n",i, buf[i]);98.99.}。

相关文档
最新文档