文档章节

I2C基本原理及对I2C Adapter的理解

Jerikc
 Jerikc
发布于 2014/04/30 14:28
字数 2186
阅读 175
收藏 0
点赞 0
评论 0
I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线产生于在80年代,最初为音频和视频设 备开发,如今主要在服务器管理中使用,其中包括单个组件状态的通信。例如管理员可对各个组件进行查询,以管理系统的配置或掌握组件的功能状态,如电源和系 统风扇。可随时监控内存、硬盘、网络、系统温度等多个参数,增加了系统的安全性,方便了管理。

简单的I2C协议理解
一. 技术性能:
    工作速率有100Kbit/s、400Kbit/s和3.4Mbit/s三种;
    支持多机通讯;
    支持多主控模块,但同一时刻只允许有一个主控;
    由数据线SDA和时钟SCL构成的串行总线;
    每个电路和模块都有唯一的地址;                  
    每个器件可以使用独立电源;
    连接到总线的接口数量只由总线电容是400pF的限制决定;

二. 基本工作原理:
    SDA和SCL都是双向线路,都通过一个电流源或上拉电阻连接到正的电源电压。当总线空闲时,这两条线路都是高电平。连接到总线的器件输出级必须是漏极开路或集电极开路才能执行线与的功能。
    以启动信号START来掌管总线,以停止信号STOP来释放总线;
    每次通讯以START开始,以STOP结束;
    启动信号START后紧接着发送一个地址字节,其中7位为被控器件的地址码,一位为读/写控制位R/W,R/W位为0表示由主控向被控器件写数据,R/W为1表示由主控从被控器件读数据;
    当主机发送了一个地址后,系统中的每个器件都在起始条件后将头7位与自己的地址比较,如果被控器件检测到收到的地址与自己的地址相同,在第9个时钟期间反馈应答信号;
    每个数据字节在传送时都是高位(MSB)在前;

写通讯过程:
    1. 主控在检测到总线空闲的状况下,首先发送一个START信号掌管总线;
    2. 发送一个地址字节(包括7位地址码和一位R/W);
    3. 当被控器件检测到主控发送的地址与自己的地址相同时发送一个应答信号(ACK);
    4. 主控收到ACK后开始发送第一个数据字节;
    5. 被控器收到数据字节后发送一个ACK表示继续传送数据,发送NACK表示传送数据结束;
    6. 主控发送完全部数据后,发送一个停止位STOP,结束整个通讯并且释放总线;

读通讯过程:
    1. 主控在检测到总线空闲的状况下,首先发送一个START信号掌管总线;
    2. 发送一个地址字节(包括7位地址码和一位R/W);
    3. 当被控器件检测到主控发送的地址与自己的地址相同时发送一个应答信号(ACK);
    4. 主控收到ACK后释放数据总线,开始接收第一个数据字节;
    5. 主控收到数据后发送ACK表示继续传送数据,发送NACK表示传送数据结束;
    6. 主控发送完全部数据后,发送一个停止位STOP,结束整个通讯并且释放总线;

四. 总线信号时序分析
    1. 总线空闲状态
    SDA和SCL两条信号线都处于高电平,即总线上所有的器件都释放总线,两条信号线各自的上拉电阻把电平拉高;
    2. 启动信号START
    时钟信号SCL保持高电平,数据信号SDA的电平被拉低(即负跳变)。启动信号必须是跳变信号,而且在建立该信号前必修保证总线处于空闲状态;
    3. 停止信号STOP
    时钟信号SCL保持高电平,数据线被释放,使得SDA返回高电平(即正跳变),停止信号也必须是跳变信号。
    4. 数据传送
    SCL线呈现高电平期间,SDA线上的电平必须保持稳定,低电平表示0(此时的线电压为地电压),高电平表示1(此时的电压由元器件的VDD决定)。只有在SCL线为低电平期间,SDA上的电平允许变化。
    5. 应答信号ACK
    I2C总线的数据都是以字节(8位)的方式传送的,发送器件每发送一个字节之后,在时钟的第9个脉冲期间释放数据总线,由接收器发送一个ACK(把数据总线的电平拉低)来表示数据成功接收。
    6. 无应答信号NACK
    在时钟的第9个脉冲期间发送器释放数据总线,接收器不拉低数据总线表示一个NACK,NACK有两种用途:
    a. 一般表示接收器未成功接收数据字节;
    b. 当接收器是主控器时,它收到最后一个字节后,应发送一个NACK信号,以通知被控发送器结束数据发送,并释放总线,以便主控接收器发送一个停止信号STOP。

五. 寻址约定
    地址的分配方法有两种:
    1. 含CPU的智能器件,地址由软件初始化时定义,但不能与其它的器件有冲突;
    2. 不含CPU的非智能器件,由厂家在器件内部固化,不可改变。

    高7位为地址码,其分为两部分:
    1. 固定部分,不可改变,由厂家固化的统一地址;
    2. 可编程部分,此部分由器件可使用的管脚决定。例如,如果器件有4个固定的和3个可编程的地址位,那么相同的总线上共可以连接8个相同的器件(并非所有器件都可以设定)。

如果有不懂的也可以读i2c规范,附件在文章末。
---------------------------------------------------------------------------------------------------------
注册过程:

drivers/i2c/busses/i2c-qup.c(这是适配器的驱动)
platform_driver_register
qup_i2c_probe    //在arch/arm/mach-msm/devices-msm8x60.c中定义了多少个gsbix_qup_i2c_resources就有多少个I2C Adapter,这个probe函数就会执行多少次
i2c_add_numbered_adapter
i2c_register_adapter
i2c_scan_static_board_info
i2c_new_device    //arch/arm/mach-msm/board-xxx.c里面定义的i2c设备在此注册(这就是静态注册)
device_register //从这句开始即是设备模型的东西
device_add
bus_probe_device
device_attach
__device_attach       //每注册一个设备都会调用此函数,每注册一个驱动也会调用__driver_attach,先注册设备还是驱动无硬性规定,不过驱动和设备是相偎相依的
driver_match_device //会根据device的name字段和bus上挂载的drivers链表中每一个driver的id_table的name字段比较,如果相等即找到了自己的driver
driver_probe_device  //如果相等调用此函数,不相等返回0。接下来会调用具体设备驱动的probe函数

drivers/i2c/i2c-dev.c
调用到的__process_new_driver-->i2c_do_add_adapter-->attach_adapter会真正执行,其他地方调用此函数均不执行。每一个i2c adapter会在/dev下生成一个字符设备。

这里只写了大概的流程,有兴趣的读者可自行跟踪代码流程。
---------------------------------------------------------------------------------------------------------
I2C Adapter/I2C BUS

gsbi是物理上实际存在的部件,它可以模拟成i2c、gpio、spi、uart、sdio等,此i2c即是gsbi模拟的。这里顺便提下i2c adapter和i2c总线,两者都是物理上必须存在的,哪怕是其他部件模拟的,例如GSBI模拟I2C,那么GSBI这个部件是实际存在的。GSBI的 走线会与所有i2c设备互连,GSBI的接口即是i2c adapter,与其他i2c设备互连的走线即是i2c总线。如果GSBI模拟成uart,那么与uart的rx/tx pin连接的走线即是uart串口线。这是高通平台的设计,换作其他平台,也一定会有一个i2c adapter或者说可以模拟成i2c adapter的物理部件存在。猜测i2c adapter位于片上系统中,类似I/O接口的东西,没有固件,驱动它的代码即是各平台相关的i2c adapter driver。GSBI的地址以及模拟成的qup i2c/uart的地址都是编址好的,在arch/arm/mach-msm/devices-msm8x60.c最开头可以看到这些物理地址。我们知道 ARM是统一编址的,在代码中要用ioremap把它映射到虚拟内存,这样就可以访问了。

  I2C规范.pdf  

© 著作权归作者所有

共有 人打赏支持
Jerikc
粉丝 89
博文 245
码字总数 22757
作品 0
浦东
程序员
手把手教你写Linux I2C设备驱动

Linux I2C驱动是嵌入式Linux驱动开发人员经常需要编写的一种驱动,因为凡是系统中使用到的I2C设备,几乎都需要编写相应的I2C驱动去配置和控制它,例如 RTC实时时钟芯片、音视频采集芯片、音视...

nothingfinal ⋅ 2012/10/26 ⋅ 0

SylixOS I2C驱动框架概述

适用范围 本文档为作者在学习I2C总线驱动过程中的总结。提供一些对SylixOS I2C驱动框架的理解经验。适用于学习I2C总线驱动或I2C设备驱动的技术工程师。 原理概述 概述 SylixOS I2C驱动框架主...

诸葛一帆丶 ⋅ 2017/02/04 ⋅ 0

linux的i2c体系结构

i2c体系结构分为3个组成部分: (1)i2c核心 (2)i2c总线驱动 (3)i2c设备驱动 i2c核心:提供了i2c总线驱动和设备驱动的注册,注销方法,i2c通信方法的上层的,与具体适配器无关的代码以及...

长平狐 ⋅ 2012/08/28 ⋅ 0

Linux I2C核心、总线与设备驱动

本章导读 I2C总线仅仅使用SCL、SDA两根信号线就实现了设备之间的数据交互,极大地简化对硬件资源和PCB板布线空间的占用。因此,I2C总线被非常广泛地应用在EEPROM、实时钟、小型LCD等设备与C...

我爱咸蛋黄 ⋅ 2013/04/22 ⋅ 0

Linux的i2c驱动详解

1 简介 I2C 总线仅仅使用 SCL 、 SDA 两根信号线就实现了设备之间的数据交互,极大地简化对硬件资源和 PCB 板布线空间的占用。因此, I2C 总线被非常广泛地应用在 EEPROM 、实时钟、小型 LC...

nothingfinal ⋅ 2012/04/18 ⋅ 0

New Linux2.6 I2C Driver Model Example

闲话不说,先给出完整的示例代码,加好注释,后面再进一步解释。 ////////////////////////////////////////////////////////////////////////// // COPYRIGHT NOTICE // Copyright (c) 2012...

乐搏学院 ⋅ 2016/12/12 ⋅ 0

S3C2410 I2C 总线驱动实例

1.S3C2410I2C 控制器硬件描述 S3C2410处理器内部集成了一个I2C控制器,通过4个寄存器就可方便地对其进行控制,这4个寄存器如下。 1 IICCON:I2C 控制寄存器。 2 IICSTAT:I2C 状态寄存器。 3 II...

长平狐 ⋅ 2012/08/28 ⋅ 0

对S3C2440裸板程序设计(无操作系统)的抽象

对S3C2440裸板程序设计(无操作系统)的抽象 在嵌入式领域中,几乎所有的设备控制和各种协议控制都在同一个嵌入式CPU当中,非常有利于对CPU Core和设备进行抽象。如果能对CPU Core和设备的各...

长平狐 ⋅ 2013/06/03 ⋅ 0

手把手教你写Linux I2C设备驱动

Linux I2C驱动是嵌入式Linux驱动开发人员经常需要编写的一种驱动,因为凡是系统中使用到的I2C设备,几乎都需要编写相应的I2C驱动去配置和控制它,例如 RTC实时时钟芯片、音视频采集芯片、音视...

乐搏学院 ⋅ 2016/12/09 ⋅ 0

基于S3C6410芯片,linux-2.6.38内核的ov9650摄像头驱动

1编写OV9650驱动之前的准备工作: 1.1 使用资源: 开发板:S3C6410芯片 Linux内核: linux-2.6.38 CMOS摄像头: ov9650 1.2 了解需要完成的工作: 1.2.1 背景知识: I2C驱动: Linux I2C驱动...

__August__ ⋅ 2015/04/29 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java 后台判断是否为ajax请求

/** * 是否是Ajax请求 * @param request * @return */public static boolean isAjax(ServletRequest request){return "XMLHttpRequest".equalsIgnoreCase(((HttpServletReques......

JavaSon712 ⋅ 28分钟前 ⋅ 0

Redis 单线程 为何却需要事务处理并发问题

Redis是单线程处理,也就是命令会顺序执行。那么为什么会存在并发问题呢? 个人理解是,虽然redis是单线程,但是可以同时有多个客户端访问,每个客户端会有 一个线程。客户端访问之间存在竞争...

码代码的小司机 ⋅ 59分钟前 ⋅ 0

到底会改名吗?微软GVFS 改名之争

微软去年透露了 Git Virtual File System(GVFS)项目,GVFS 是 Git 版本控制系统的一个开源插件,允许 Git 处理 TB 规模的代码库,比如 270 GB 的 Windows 代码库。该项目公布之初就引发了争...

linux-tao ⋅ 今天 ⋅ 0

笔试题之Java基础部分【简】【二】

1.静态变量和实例变量的区别 在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变...

anlve ⋅ 今天 ⋅ 0

Lombok简单介绍及使用

官网 通过简单注解来精简代码达到消除冗长代码的目的 优点 提高编程效率 使代码更简洁 消除冗长代码 避免修改字段名字时忘记修改方法名 4.idea中安装lombnok pom.xml引入 <dependency> <grou...

to_ln ⋅ 今天 ⋅ 0

【转】JS浮点数运算Bug的解决办法

37.5*5.5=206.08 (JS算出来是这样的一个结果,我四舍五入取两位小数) 我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998 怎么会这样,两个只有一位小数的数字相乘,怎...

NickSoki ⋅ 今天 ⋅ 0

table eg

user_id user_name full_name 1 zhangsan 张三 2 lisi 李四 `` ™ [========] 2018-06-18 09:42:06 星期一½ gdsgagagagdsgasgagadsgdasgagsa...

qwfys ⋅ 今天 ⋅ 0

一个有趣的Java问题

先来看看源码: public class TestDemo { public static void main(String[] args) { Integer a = 10; Integer b = 20; swap(a, b); System.out......

linxyz ⋅ 今天 ⋅ 0

十五周二次课

十五周二次课 17.1mysql主从介绍 17.2准备工作 17.3配置主 17.4配置从 17.5测试主从同步 17.1mysql主从介绍 MySQL主从介绍 MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主...

河图再现 ⋅ 今天 ⋅ 0

docker安装snmp rrdtool环境

以Ubuntu16:04作为基础版本 docker pull ubuntu:16.04 启动一个容器 docker run -d -i -t --name flow_mete ubuntu:16.04 bash 进入容器 docker exec -it flow_mete bash cd ~ 安装基本软件 ......

messud4312 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部