Linux_I2C总线分析(主要是probe的方式)1
- 格式:doc
- 大小:468.00 KB
- 文档页数:8
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是一种常用的串行通信协议,用于在电子设备之间进行数据传输。
它的全称是Inter-Integrated Circuit,即片间串行总线。
1. 主设备(Master Device):负责发起通信请求并控制整个传输过程的设备。
主设备通常是微控制器、处理器或其他智能设备。
2. 从设备(Slave Device):被主设备控制的设备。
从设备可以是各种外围设备,如传感器、存储器、显示器等。
3. SDA(Serial Data Line):用于数据传输的双向串行数据线。
主设备和从设备都可以发送和接收数据。
4. SCL(Serial Clock Line):用于同步数据传输的时钟线。
主设备产生时钟信号来同步数据传输。
5. VCC(Supply Voltage):提供电源电压给I2C总线上的设备。
6. GND(Ground):提供共地连接。
I2C总线的工作原理如下:1.初始化:主设备发起一次总线初始化,在I2C总线上产生一个启动信号。
启动信号表示I2C总线上有新的数据传输将开始。
2.寻址:主设备发送一个7位的设备地址到总线上指定要与之通信的从设备。
I2C总线上可以存在多个从设备,每个设备都有唯一的地址。
3.数据传输:主设备发送数据或者命令到从设备,或者从设备向主设备发送数据回复。
数据通过SDA线传输,时钟通过SCL线提供。
4.确认(ACK):数据传输完成后,每个接收设备都会回复一个确认信号,表示它已经成功接收数据。
主设备和从设备都可以发送确认信号。
5.停止:主设备发送一个停止信号来结束一次数据传输过程。
停止信号表示I2C总线上没有更多的数据传输。
I2C总线的工作原理是基于主从结构的,主设备控制数据传输的流程。
主设备通过发送启动信号来开始一个数据传输过程,并通过发送设备地址和数据来与特定的从设备进行通信。
通过SCL线的时钟同步,主设备和从设备可以准确地进行数据传输,避免了数据丢失和冲突。
i2cdetect的用法-回复标题:[i2cdetect的用法]详解i2cdetect是一款在Linux系统中广泛使用的命令行工具,用于检测I2C 总线上的设备。
本文将详细解释i2cdetect的用法,并通过一些实例演示如何使用这个工具。
一、了解I2C总线和i2cdetectI2C(Inter-Integrated Circuit)是一种串行通信协议,允许微控制器和其他设备之间的简单双向通信。
I2C总线上可以连接多个设备,每个设备都有一个唯一的地址。
i2cdetect是I2C调试工具的一部分,可以用来扫描I2C总线并显示出所有连接到该总线的设备及其地址。
二、安装i2cdetect在大多数Linux发行版中,i2cdetect已经预装。
如果没有预装,可以通过包管理器进行安装。
例如,在Debian和Ubuntu上,可以使用以下命令进行安装:sudo apt-get install i2c-tools三、使用i2cdetect1. 打开终端,输入以下命令以获取系统的I2C总线列表:ls /dev/i2c*输出可能类似于:/dev/i2c-0, /dev/i2c-1等。
2. 使用i2cdetect扫描特定的I2C总线。
例如,要扫描/dev/i2c-0总线,输入以下命令:sudo i2cdetect -y 0其中,“-y”选项表示即使总线未被分配也要强制访问,后面的数字“0”表示要扫描的I2C总线。
3. 在扫描完成后,i2cdetect会显示一个表格,其中列出了所有连接到指定I2C总线的设备及其地址。
例如,输出可能如下所示:0 1 2 3 4 5 6 7 8 9 a b c d e f00:10:20:30:40:50: UU UU UU UU UU UU UU UU60:70:在这个例子中,“UU”表示该地址没有设备响应,而空白则表示该地址有设备存在但没有被探测到。
四、解读i2cdetect的输出i2cdetect的输出是一个16x16的表格,每行代表一个八位的十六进制地址。
I2C详解1、基本概念主机初始化发送,产⽣时钟信号和终⽌发送的器件从机被主机寻址的器件发送器发送数据到总线的器件接收器从总线接收数据的器件多主机同时有多于⼀个主机尝试控制总线但不破坏报⽂仲裁是⼀个在有多个主机同时尝试控制总线,但只允许其中⼀个控制总线并使报⽂不被破坏的过程同步两个或多个器件同步时钟信号的过程2、硬件结构每⼀个I2C总线器件内部的SDA、SCL引脚电路结构都是⼀样的,引脚的输出驱动与输⼊缓冲连在⼀起。
其中输出为漏极开路的场效应管、输⼊缓冲为⼀只⾼输⼊阻抗的同相器。
这种电路具有两个特点:(1)由于SDA、SCL 为漏极开路结构,借助于外部的上拉电阻实现了信号的“线与”逻辑;(2)引脚在输出信号的同时还将引脚上的电平进⾏检测,检测是否与刚才输出⼀致。
为“时钟同步”和“总线仲裁”提供硬件基础。
3、时钟同步如果从机希望主机降低传送速度可以通过将SCL主动拉低延长其低电平时间的⽅法来通知主机,当主机在准备下⼀次传送发现SCL的电平被拉低时就进⾏等待,直⾄从机完成操作并释放SCL线的控制控制权。
这样以来,主机实际上受到从机的时钟同步控制。
可见SCL 线上的低电平是由时钟低电平最长的器件决定;⾼电平的时间由⾼电平时间最短的器件决定。
这就是时钟同步,它解决了I2C总线的速度同步问题。
4、主机发送数据流程(1)主机在检测到总线为“空闲状态”(即SDA、SCL 线均为⾼电平)时,发送⼀个启动信号“S”,开始⼀次通信的开始(2)主机接着发送⼀个命令字节。
该字节由7 位的外围器件地址和1 位读写控制位R/W 组成(此时R/W=0)(3)相对应的从机收到命令字节后向主机回馈应答信号ACK(ACK=0)(4)主机收到从机的应答信号后开始发送第⼀个字节的数据(5)从机收到数据后返回⼀个应答信号ACK(6)主机收到应答信号后再发送下⼀个数据字节(7)当主机发送最后⼀个数据字节并收到从机的ACK 后,通过向从机发送⼀个停⽌信号P结束本次通信并释放总线。
I2C总线简介1.概述:I²C是Inter-Integrated Circuit的缩写,发音为"eye-squared cee" or"eye-two-cee", 它是一种两线接口。
I²C 只是用两条双向的线,一条 Serial Data Line (SDA) ,另一条Serial Clock (SCL)。
SCL:上升沿将数据输入到每个EEPROM器件中;下降沿驱动EEPROM器件输出数据。
(边沿触发)SDA:双向数据线,为OD门,与其它任意数量的OD与OC门成"线与"关系。
2.输出级每一个I2C总线器件内部的SDA、SCL引脚电路结构都是一样的,引脚的输出驱动与输入缓冲连在一起。
其中输出为漏极开路的场效应管,输入缓冲为一只高输入阻抗的同相器,这种电路具有两个特点:1)由于SDA、SCL为漏极开路结构(OD),因此它们必须接有上拉电阻,阻值的大小常为1k8, 4k7 and 10k ,但1k8 时性能最好;当总线空闲时,两根线均为高电平。
连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线"与"关系。
2)引脚在输出信号的同时还将引脚上的电平进行检测,检测是否与刚才输出一致,为"时钟同步"和"总线仲裁"提供了硬件基础。
3.主设备与从设备系统中的所有外围器件都具有一个7位的"从器件专用地址码",其中高4位为器件类型,由生产厂家制定,低3位为器件引脚定义地址,由使用者定义。
主控器件通过地址码建立多机通信的机制,因此I2C总线省去了外围器件的片选线,这样无论总线上挂接多少个器件,其系统仍然为简约的二线结构。
终端挂载在总线上,有主端和从端之分,主端必须是带有CPU的逻辑模块,在同一总线上同一时刻使能有一个主端,可以有多个从端,从端的数量受地址空间和总线的最大电容 400pF的限制。
linux系统i2c协议详解I2C总线概述I2C(两线接口)是一种串行通信协议,用于连接嵌入式系统中的集成电路(IC)。
它以其低成本、低功耗和高可靠性著称。
I2C总线需要两条双向信号线:串行数据线(SDA)和串行时钟线(SCL)。
这些信号线由一个主设备控制,可以与多个从设备通信。
I2C通信I2C通信由以下步骤组成:起始条件:主设备将SDA线下拉至低电平,同时保持SCL线为高电平。
设备地址:主设备发送7位或10位从设备地址,后跟一个读/写位。
数据传输:主设备和从设备交换数据。
停止条件:主设备将SDA线拉至高电平,同时保持SCL线为高电平。
主设备和从设备I2C总线上的设备分为两种:主设备和从设备。
主设备:发起通信并控制总线。
通常是主微控制器或处理器。
从设备:响应主设备请求并提供或接收数据。
可以是传感器、执行器或其他外围设备。
I2C寻址从设备通过唯一的7位或10位地址进行寻址。
地址的最高位表示是否可读/写,0表示写,1表示读。
I2C模式I2C协议支持以下模式:主写从读:主设备向从设备写入数据,然后从从设备读取数据。
主读从写:主设备从从设备读取数据,然后向从设备写入数据。
从读从写:两个从设备在主设备的监督下进行通信。
I2C传输速率I2C传输速率通常在10kbps到400kbps之间。
速率由主设备设置。
I2C错误检测I2C协议包含几个错误检测机制,例如校验和和超时。
这些机制有助于确保数据的可靠传输。
I2C应用I2C总线用于各种应用,包括:传感器和执行器接口EEPROM和闪存编程LED和LCD控制模拟-数字转换器(ADC)和数字-模拟转换器(DAC)接口电源管理时钟同步I2C优点I2C协议的优点包括:低成本:无需额外的硬件接口低功耗:仅使用两根信号线高可靠性:错误检测机制确保数据完整性容易使用:简单的协议易于实施广泛采用:支持广泛的设备和库I2C缺点I2C协议的缺点包括:数据速率低:与其他串行接口相比,数据速率较低主机限制:总线上只能有一个主设备总线无仲裁:在总线冲突的情况下,没有内置的仲裁机制有限的寻址范围:仅支持有限数量的设备地址I2C技术演进I2C协议正在不断发展,以满足新应用的需求。
I2C驱动传入probe的参数解释在进行I2C设备的驱动开发过程中,常常会涉及到I2C驱动的probe 函数。
probe函数是Linux内核驱动中的一种特殊函数,它在驱动被加载并且设备被检测到时被调用,用于初始化设备并注册设备驱动。
在编写I2C驱动的probe函数时,通常需要传入不同的参数进行配置和初始化。
本文将对I2C驱动传入probe的参数进行解释和说明,帮助读者更好地理解和使用I2C设备驱动。
1. struct i2c_client *client在I2C驱动的probe函数中,通常需要传入一个指向structi2c_client结构体的指针作为参数。
这个结构体是I2C设备在内核中的表示,包含了I2C设备的位置区域、总线信息、驱动信息等。
通过这个参数,我们可以获取I2C设备的各种信息,并进行相应的初始化和配置。
2. const struct i2c_device_id *id另一个常见的参数是一个指向const struct i2c_device_id结构体的指针,用于指定要注册的设备驱动的ID信息。
这个结构体中通常包含了设备的厂商ID、设备类型、设备名称等信息,用于匹配加载指定的设备驱动。
在probe函数中,我们可以使用这个参数来判断当前检测到的I2C设备是否匹配当前的驱动,从而进行相应的初始化和注册操作。
3. int (*probe)(struct i2c_client *client, const struct i2c_device_id *id)最后一个重要的参数是probe函数本身。
这个参数是一个函数指针,用于指定实际的probe函数的位置区域。
在probe函数中,我们可以根据传入的client和id参数,进行设备的初始化、资源的申请、注册设备驱动等操作。
通过这个函数指针参数,内核可以在加载驱动并检测到设备时正确地调用对应的probe函数。
I2C驱动传入probe的参数包括指向I2C设备结构体的指针、指向设备ID信息的指针以及probe函数的函数指针。
I2C总线协议及工作原理I2C(Inter-Integrated Circuit)是一种串行通信总线协议,由Philips公司提出,适用于在电路板上连接各种集成电路的短距离通信。
I2C总线协议的工作原理是基于主从结构的,其中一个设备作为主设备,其他设备作为从设备。
主设备负责发起通信操作,而从设备则被动响应主设备的指令。
主设备在总线上发出启动信号,然后发送器件地址。
发起通信的主设备控制总线的速度和时序,并且主设备确定读写的类型。
从设备根据地址进行匹配,并根据主设备请求的读写进行响应。
通信完成后,主设备会发送停止信号释放总线。
在I2C总线上,每个设备都有一个唯一的7位或10位地址。
主设备在传输数据之前,会发送起始信号,这个信号告诉从设备通信即将开始。
随后主设备会发送一个地址字节,包含了要通信的从设备的地址和读写控制位。
如果从设备的地址和发送的地址匹配,从设备会发送一个应答(ACK)信号,表示准备好接收数据。
主设备然后才开始发送或接收数据。
数据在I2C总线上传输是以字节为单位的,并且每个字节之后都会有一个应答信号。
主设备负责设置时钟线的电平来控制数据的传输,而从设备负责读取或发送数据位。
在读取数据时,主设备会发送应答位,如果从设备准备好读取下一个字节,会发送应答信号;反之,如果从设备不准备好,会发送非应答信号。
在I2C总线上,主设备还可以使用多主模式,允许多个主设备操作相同的总线。
当多个主设备在通信总线上发起通信时,总线的冲突可能会发生。
为了解决这个问题,I2C总线使用了仲裁机制。
仲裁机制根据优先级决定那个设备能够继续发送数据,优先级高的设备可以中断优先级低的设备的传输,从而保证通信的顺利进行。
总结起来,I2C总线协议是一种简单、高效的串行通信协议。
它通过两根线实现设备之间的通信,并且支持多主模式。
它的工作原理是基于主从结构,主设备发起通信,从设备被动响应。
通过仲裁机制,解决了多主模式下的冲突问题。
实例解析linux内核I2C体系结构(1)一、概述谈到在linux系统下编写I2C驱动,目前主要有两种方式,一种是把I2C设备当作一个普通的字符设备来处理,另一种是利用linux I2C驱动体系结构来完成。
下面比较下这两种驱动。
第一种方法的好处(对应第二种方法的劣势)有:●思路比较直接,不需要花时间去了解linux内核中复杂的I2C子系统的操作方法。
第一种方法问题(对应第二种方法的好处)有:●要求工程师不仅要对I2C设备的操作熟悉,而且要熟悉I2C的适配器操作;●要求工程师对I2C的设备器及I2C的设备操作方法都比较熟悉,最重要的是写出的程序可移植性差;●对内核的资源无法直接使用。
因为内核提供的所有I2C设备器及设备驱动都是基于I2C子系统的格式。
I2C适配器的操作简单还好,如果遇到复杂的I2C适配器(如:基于PCI的I2C适配器),工作量就会大很多。
本文针对的对象是熟悉I2C协议,并且想使用linux内核子系统的开发人员。
网络和一些书籍上有介绍I2C子系统的源码结构。
但发现很多开发人员看了这些文章后,还是不清楚自己究竟该做些什么。
究其原因还是没弄清楚I2C子系统为我们做了些什么,以及我们怎样利用I2C子系统。
本文首先要解决是如何利用现有内核支持的I2C适配器,完成对I2C设备的操作,然后再过度到适配器代码的编写。
本文主要从解决问题的角度去写,不会涉及特别详细的代码跟踪。
二、I2C设备驱动程序编写首先要明确适配器驱动的作用是让我们能够通过它发出符合I2C标准协议的时序。
在Linux内核源代码中的drivers/i2c/busses目录下包含着一些适配器的驱动。
如S3C2410的驱动i2c-s3c2410.c。
当适配器加载到内核后,接下来的工作就要针对具体的设备编写设备驱动了。
编写I2C设备驱动也有两种方法。
一种是利用系统给我们提供的i2c-dev.c来实现一个i2c 适配器的设备文件。
然后通过在应用层操作i2c适配器来控制i2c设备。
1. 几个基本概念1.1. 设备模型由总线(bus_type)+ 设备(device)+ 驱动(device_driver)组成,在该模型下,所有的设备通过总线连接起来,即使有些设备没有连接到一根物理总线上,linux为其设置了一个内部的、虚拟的platform总线,用以维持总线、驱动、设备的关系。
因此,对于实现一个linux下的设备驱动,可以划分为两大步:1、设备注册;2、驱动注册。
当然,其中还有一些细节问题:1、驱动的probe函数2、驱动和设备是怎么进行绑定的。
1.2. i2c设备驱动的几个数据结构i2c_adapter:每一个i2c_adapter对应一个物理上的i2c控制器,在i2c总线驱动probe函数中动态创建。
通过i2c_add_adapter注册到i2c_core。
i2c_algorithm:i2c_algorithm中的关键函数master_xfer(),以i2c_msg为单位产生i2c访问需要的信号。
不同的平台所对应的master_xfer()是不同的,需要根据所用平台的硬件特性实现自己的xxx_xfer()方法以填充i2c_algorithm的master_xfer指针;在A31上即是sun6i_i2c_algorithm函数。
i2c_client:代表一个挂载到i2c总线上的i2c从设备,包含该设备所需要的数据:该i2c从设备所依附的i2c控制器 struct i2c_adapter *adapter该i2c从设备的驱动程序struct i2c_driver *driver该i2c从设备的访问地址addr, name该i2c从设备的名称name。
2. i2c总线驱动2.1. 功能划分从硬件功能上可划分为:i2c控制器和i2c外设(从设备)。
每个i2c控制器总线上都可以挂载多个i2c外设。
Linux中对i2c控制器和外设分开管理:通过i2c-sun6i.c 文件完成了i2c控制器的设备注册和驱动注册;通过i2c-core.c为具体的i2c外设提供了统一的设备注册接口和驱动注册接口,它分离了设备驱动device driver和硬件控制的实现细节(如操作i2c的寄存器)。
I2C总线协议详解简介:I2C(Inter-Integrated Circuit)是一种由PHILIPS公司开发的两线式串行总线,用于衔接微控制器及其外围设备。
I2C总线产生于在80年月,最初为音频和视频设备开发,如今主要在服务器管理中用法,其中包括单个组件状态的通信可随时监控内存、硬盘、网络、系统温度等多个参数,增强了系统的平安性,便利了管理。
I2C总线特点I2C总线最主要的优点是其容易性和有效性。
因为接口挺直在组件之上,因此I2C总线占用的空间十分小,削减了板的空间和芯片管脚的数量,降低了互联成本。
总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。
I2C总线的另一个优点是,它支持多主控(multimastering),其中任何能够举行发送和接收的设备都可以成为主总线。
一个主控能够控制信号的传输和时钟频率。
固然,在任何时光点上只能有一个主控。
I2C总线工作原理总线的构成及信号类型I2C总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。
在CPU与被控IC之间、IC与IC之间举行双向传送,最高传送速率100kbps。
各种被控制电路均并联在这条总线上,但就像电话机一样惟独拨通各自的号码才干工作,所以每个电路和模块都有唯一的地址,在信息的传输过程中,I2C总线上并接的每一模块电路既是主控器(或被控器),又是发送器(或接收器),这取决于它所要完成的功能。
CPU发出的控制信号分为地址码和控制量两部分,地址码用来选址,即接通需要控制的电路,确定控制的种类;控制量打算该调节的类别(如对照度、亮度等)及需要调节的量。
这样,各控制电路虽然挂在同一条总线上,却彼此自立,互不相关。
I2C总线在传送数据过程*有三种类型信号,它们分离是:开头信号、第1页共4页。
i2c总线的工作原理
I2C(Inter-Integrated Circuit)是一种串行通信总线,其工作原理如下:
1. I2C总线包括两根信号线:SDA(Serial Data Line)和SCL (Serial Clock Line)。
SDA用于数据传输,SCL用于数据的时钟同步。
2. 所有的I2C设备都连接在同一根总线上,每个设备通过一个唯一的地址来进行识别。
3. 在任何时刻,总线上只能有一个主设备,其他设备都是从设备。
主设备负责发起和控制通信,而从设备则被动地响应主设备的请求。
4. 主设备通过发送START信号来开始一次通信。
START信号表明一个新的传输即将开始。
5. 主设备发送一个地址字节,指定要与之通信的从设备。
地址字节包括7位地址和1位读/写标志位。
读标志表示主设备将从设备读取数据,写标志表示主设备将向从设备发送数据。
6. 一旦从设备收到其地址,它会发送一个ACK信号以确认接收到地址。
7. 数据传输过程中,主设备和从设备通过SDA线进行数据的传输。
每个数据字节都会被从设备发送或接收。
8. 每个数据字节的传输都以一个ACK信号的发送结束,用于
确认数据字节的正确接收。
9. 主设备可以在传输过程中继续发送数据字节,直到传输完成。
10. 传输完成后,主设备发送STOP信号来终止通信。
总的来说,I2C总线的工作原理是通过主设备和从设备之间的
数据交换和时钟同步来实现设备之间的通信。
主设备在总线上发送START和STOP信号来控制通信流程,从设备则被动地
接收和发送数据。
I2C总线工作原理I2C总线工作原理 (1)1 I2C总线特点 (1)2 I2C总线协议 (2)2.1 起始和停止条件 (2)2.2 数据传输格式 (3)2.3 应答ACK信号的传送 (3)2.4仲裁和时钟同步 (4)2.5 7位的地址格式 (4)3 串/并、并/串转换 (5)3.1并串转换原理 (5)3.2串并转换原理 (5)4 HE寄存器总线工作原理 (5)5 E2PROM原理 (6)6 V erilog 硬件设计语言 (7)7 集成电路设计流程 (8)1 I2C总线特点I2C双向串行总线将主机或者从机的并行数据转换为串行数据,并通过SDA 线传输。
SCL则是串行时钟线,I2C总线通过SDA和SCL两条串行总线实现设备器件间的通信。
与其它串行总线相比,I2C总线具有一下几方面的特点:(1).只有两条总线线路:一条串行数据线(SDA);一条串行时钟线(SCL)。
(2).每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机、从机关系软件设定的地址;主机可以作为主机发送器或者主机接收器。
(3).它是一个真正的多主机系统,如果两个或者更多主机同时初始化数据传输可以通过冲突检测和仲裁防止数据被破坏。
(4).串行的8位双向数据传输位速率在标准模式下可以达到100kbit/s,快速模式下可以达到400kbit/s,高速模式下可以达到3.4Mbit/s。
(5).I2C总线支持任何IC生产过程(NMOS、CMOS、双极性)。
并且通过SDA、SCL两条串行线与连接到总线上的器件间传递信息。
每个器件都有一个唯一的是地址识别,而且都可以作为一个接收器或者发送器(由器件的功能决定)。
I2C 总线的相关术语定义如下表所示:I2C总线术语的定义表1SDA 和SCL 都是双向线路,都通过一个电流源或上拉电阻连接到正的电源电压。
当总线空闲时,这两条线路都是高电平。
连接到总线的器件输出级必须是漏极开路或集电极开路才能执行线与的功能。
i2c总线工作原理I2C总线是一种用于连接微控制器和外部设备的串行通信协议。
它采用两根信号线,分别是时钟线(SCL)和数据线(SDA),通过这两根线实现数据的传输和通信。
I2C总线的工作原理如下:1. 总线结构:I2C总线由一个主设备和多个从设备组成。
主设备负责发起通信并控制总线,从设备则接受主设备的指令并返回数据。
2. 起始信号和结束信号:通信开始时,主设备发出起始信号。
起始信号由将SCL线拉低,然后再将SDA线由高电平拉低构成,表示通信即将开始。
通信结束时,主设备发出结束信号,由将SCL线保持高电平的同时将SDA线由低电平拉高构成,表示通信结束。
3. 数据传输:数据传输通过时钟线(SCL)和数据线(SDA)进行。
时钟线由主设备控制,用于驱动数据传输。
数据线上的数据必须在时钟线为低电平时才能改变,而在时钟线为高电平时必须保持稳定。
4. 主设备和从设备地址:主设备发送数据时,首先发送从设备的地址。
地址由7位或10位构成,前7位是从设备的地址,最高位是读/写位。
读/写位为0表示写操作,为1表示读操作。
从设备接收到自己的地址后,确认信号应答ACK返回给主设备。
5. 数据传输确认:数据传输时,每传输一个字节后,接收方需要发送一个应答信号ACK给发送方,表示已成功接收。
如果接收方不能接收数据或者接收错误,会发送应答信号NAK给发送方。
6. 时钟速率:I2C总线的时钟速率可以根据需求设定,其中标准模式下的时钟速率为100 kbit/s,快速模式为400 kbit/s,高速模式可达到3.4 Mbit/s。
总的来说,I2C总线通过起始和结束信号进行通信的开始和结束,通过时钟线和数据线实现数据的传输和控制。
主设备发送地址和数据,从设备接收并返回数据。
通过应答信号确认数据是否成功传输。
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_xferto NULL. If an adapter algorithm can do SMBus access, setsmbus_xfer. If set to NULL, the SMBus protocol is simulatedusing common I2C messages *//* master_xfer should return the number of messages successfullyprocessed, 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适配器数据结构i2c_adapter、I2C适配器的algorithm数据结构i2c_algorithm和控制I2C适配器产生通信信号的函数。
经由I2C总线驱动的代码,我们可以控制I2C适配器以主控方式产生开始位、停止位、读写周期,以及以从设备方式被读写、产生ACK等。
不同的CPU平台对应着不同的I2C总线驱动。
总线驱动的职责,是为系统中每个I2C总线增加相应的读写方法。
但是总线驱动本身并不会进行任何的通讯,它只是存在在那里,等待设备驱动调用其函数。
这部分在MTK 6516中是由MTK已经帮我们实现了的,不需要我们更改。
3· I2C设备驱动:I2C设备驱动是对I2C硬件体系结构中设备端的实现。
设备一般挂接在受CPU控制的I2C 适配器上,通过I2C适配器与CPU交换数据。
I2C设备驱动主要包含了数据结构i2c_driver和i2c_client,我们需要根据具体设备实现其中的成员函数。
在Linux内核源代码中的drivers 目录下的文件,实现了I2C适配器设备文件的功能,应用程序通过“i2c-%d”文件名并使用文件操作接口open()、write()、read()、ioctl()和close()等来访问这个设备。
应用层可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄存器并控制I2C设备的工作方式。
设备驱动则是与挂在I2C总线上的具体的设备通讯的驱动。
通过I2C总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。
这部分在MTK 6516中是由具体的设备实现的。
(比如camera)struct i2c_client:代表一个挂载到i2c总线上的i2c从设备,该设备所需要的数据结构,其中包括该i2c从设备所依附的i2c主设备 struct i2c_adapter *adapter 该i2c 从设备的驱动程序struct i2c_driver *driver 作为i2c从设备所通用的成员变量,比如addr, name等该i2c从设备驱动所特有的数据,依附于dev->driver_data下struct i2c_adapter:代表主芯片所支持的一个i2c主设备。
struct i2c_algorithm *algo:是该i2c主设备传输数据的一种算法,或者说是在i2c总线上完成主从设备间数据通信的一种能力。
Linux的i2c子系统新、旧架构并存。
主要分为旧架构(Legacy)也有人称之为adapter方式,和新的架构new-style的方式。
这俩者的区别主要在于设备注册和驱动注册的不同。
对于Legacy的设备注册是在驱动运行的时候动态的创建,而新式的new-style则是采用静态定义的方式。
注:MTK在版上用的是Legacy的架构,而在版上用的是new-style的架构。
(在这里我就只说明的new-style的实现方法)要完成I2C设备的驱动,我们可以分三步走:第一步:完成适配器的注册(总线);第二步:完成I2C client的设备注册(设备);第三步:完成I2C client驱动的注册(驱动);我们分别给予介绍:()⑴就总线而言,其本质只需要我们填充俩个结构体就可以了:i2c_adapter;i2c_algorithm;i2c_add_adapter(i2c->adap); 往总线上添加对应的适配器;struct i2c_adapter {struct module *owner;unsigned int id;unsigned int class; /* classes to allow probing for */const struct i2c_algorithm *algo; /* the algorithm to access the bus */ void *algo_data;/* --- administration stuff. */int (*client_register)(struct i2c_client *);int (*client_unregister)(struct i2c_client *);/* data fields that are valid for all devices */u8 level; /* nesting level for lockdep */struct mutex bus_lock;struct mutex clist_lock;int timeout; /* in jiffies */int retries;struct device dev; /* the adapter device */int nr; /*该成员描述了总线号*/struct list_head clients; /* i2c_client结构链表,该结构包含device,driver 和 adapter结构*/char name[48];struct completion dev_released;};static struct i2c_algorithm mt6516_i2c_algorithm = {.master_xfer = mt6516_i2c_transfer,.smbus_xfer = NULL,.functionality = mt6516_i2c_functionality,};2、设备注册第一步:记得以前的i2c设备驱动,设备部分喜欢驱动运行的时候动态创建,新式的驱动倾向于向传统的linux 下设备驱动看齐,采用静态定义的方式来注册设备,使用接口为:int __init i2c_register_board_info(int busnum,struct i2c_board_info const *info, unsigned len){int status;mutex_lock(&__i2c_board_lock);/* dynamic bus numbers will be assigned after the last static one */if (busnum >= __i2c_first_dynamic_bus_num)__i2c_first_dynamic_bus_num = busnum + 1;for (status = 0; len; len--, info++) {struct i2c_devinfo *devinfo;devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); */res = driver_register(&driver->driver);if (res)return res;pr_debug("i2c-core: driver [%s] registered\n", driver->;INIT_LIST_HEAD(&driver->clients);/* Walk the adapters that are already present */mutex_lock(&core_lock);bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);mutex_unlock(&core_lock);return 0;}设备和驱动的关联过程:首先当I2C从设备和I2C驱动如果处于同一条总线上,那么其在设备和驱动注册之后,将会促使I2C_bus_type中的match获得调用;()如下:struct bus_type i2c_bus_type = {.name = "i2c",.match = i2c_device_match,.probe = i2c_device_probe,.remove = i2c_device_remove,.shutdown = i2c_device_shutdown,.suspend = i2c_device_suspend,.resume = i2c_device_resume,};继续跟进i2c_device_match;i2c_match_id(driver->id_table, client) != NULL;我们回到i2c_device_probe;这个函数的关键是:status = driver->probe(client, i2c_match_id(driver->id_table, client));它将函数的流程交回到了driver->probe的手中;流程图:过程分享:1、设备和驱动的关联大家知道,对于一个驱动程序有两个元素不可或缺,即设备和驱动,一般驱动都是通过设备名和驱动名的匹配建立关系的,最开始我从代码中只能发现驱动的注册,却不见设备注册的踪影,令人疑惑,跟踪发现,在i2c adapter注册时会遍历i2c_board_info这样一个结构,而这个结构在29以前或更早的内核里是不存在的,它会完成驱动与设备的匹配问题,2、名字匹配一个i2c驱动是可以有多个名字的,即一个驱动程序可以支持多个设备,该机制是通过struct i2c_device_id实现的,驱动中建立这么一个结构体数组,i2c架构层便会扫描该数组,与设备名去匹配,匹配成功的都会进入相应probe函数。