2012/02/09 下午 3:49
i2c驱动用gpio模拟也可,当然用linux模型才是趋势。(api应用笔记)
维基百科,自由的百科全书
I2C是内部整合电路的称呼,是一种串行通讯总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边装置而发展。I2C的正确读法为"I-squared-C" ,而"I-two-C"则是另一种错误但被广泛使用的读法,在中国则多以"I方C"称之。截至2006年11月1日为止,使用I2C协定不需要为其专利付费,但制造商仍然需要付费以获得I2C从属装置位址。
IIC总线 一般串行数据通讯都有 时钟和数据之分, 异步和同步之别. 单线,双线和三线等.I2C肯定是2线的(不算地线). I2C协议确实很科学,比3/4线的SPI要好, 当然线多通讯速率相对就快了. I2C的原则是: 在SCL=1(高 电平 )时 , SDA千万别忽悠!!! 否则,SDA下跳则"判罚"为"起始信号S",SDA上跳则"判罚"为"停止信号P". 在SCL=0(低电平)时,SDA随便忽悠!!!(可别忽悠 过火 到SCL跳高) 每个字节后应该由对方回送一个应答信号ACK做为对方在线的标志.
非应答信号一般在所有字节的最后一个字节后. 一般要由双方协议签定. SCL必须由主机发送, 否则天下大乱. 首字节是"片选信号",即7位从机地址加1位方向(读写)控制. 从机收到(听到)自己的地址才能发送应答信号(必须应答!!!)表示自己在线. 其他地址的从机不允许忽悠!!!(当然群呼可以忽悠但只能听不许说话) 读写是站在主机的立场上定义的. "读"是主机接收从机数据,"写"是主机发送数据给从机. 重复位主要用于主机从发送模式到接收模式的转换"信号",由于只有2线, 所以收发转换肯定要比SPI复杂,因为SPI可用不同的边沿来收发数据,而I2C不行. 在硬件I2C模块,特别是MCU/ARM/DSP等每个阶段都会得到一个准确的状态码, 根据这个状态码可以很容易知道现在在什么状态和什么出错信息. 7位I2C总线可以挂接127个不同地址的I2C设备,0号"设备"作为群呼地址. 10位I2C总线可以挂接更多的10位I2C设备. 总之,只要掌握I2C的忽悠记,一般很容易掌控... 第一个字节(为slave address)由7位地址和一位R/W读写位组成的,这字节是个器件地址。 首先,你要知道:常用IIC接口通用器件的器件地址是由种类型号,及寻址码组成的,共7位。 如格式如下: D7 D6 D5 D4 D3 D2 D1 D0
2-用户自定义地址码 :D3-D1共3位。这是由用户自己设置的,通常的作法如EEPROM这些器件是 由外部IC的3个引脚所组合电平决定的 (用常用的名字如A0,A1,A2)。这也就是寻址码。 所以为什么同一IIC总线上同一型号的IC只能最多共挂8片同种类芯片的原因了。 3-最低一位就是R/W位。这位不用我多说了。
每个器件都有一个唯一的地址,而且可以是单接收的器件(例如:LCD 驱动器 )或者可以接收也可以发送的器件(例如: 存储器 )。发送器或接收器可以在主模式或从模式下操作,这取决于芯片是否必须启动数据的传输还是仅仅被寻址。I2C是一个多主总线,即它可以由多个连接的器件控制。 基本的I2C总线规范于20年前发布,其 数据传输 速率最高为100Kbits/s,采用7位寻址。但是由于数据传输速率和应用功能的迅速增加,I2C总线也增强为快速模式(400Kbits/s)和10位寻址以满足更高速度和更大寻址空间的需求。 I2C总线始终和先进技术保持同步,但仍然保持其向下兼容性。并且最近还增加了高速模式,其速度可达3.4Mbits/s。它使得I2C总线能够支持现有以及将来的高速串行传输应用,例如EEPROM和Flash存储器。 在现代电子系统中,有为数众多的IC需要进行相互之间以及与外界的通信。为了提供硬件的效率和简化电路的设计,PHILIPS开发了一种用于内部IC控制的简单的双向两线串行总线I2C。I2C总线支持任何一种IC制造工艺,并且PHILIPS和其他厂商提供了种类非常丰富的I2C兼容芯片。作为一个专利的控制总线,I2C已经成为世界性的工业标准。 每个器件都有一个唯一的地址,而且可以是单接收的器件(例如:LCD驱动器)或者可以接收也可以发送的器件(例如:存储器)。发送器或接收器可以在主模式或从模式下操作,这取决于芯片是否必须启动数据的传输还是仅仅被寻址。I2C是一个多主总线,即它可以由多个连接的器件控制。 基本的I2C总线规范于20年前发布,其数据传输速率最高为100Kbits/s,采用7位寻址。但是由于数据传输速率和应用功能的迅速增加,I2C总线也增强为快速模式(400Kbits/s)和10位寻址以满足更高速度和更大寻址空间的需求。 I2C总线始终和先进技术保持同步,但仍然保持其向下兼容性。并且最近还增加了高速模式,其速度可达3.4Mbits/s。它使得I2C总线能够支持现有以及将来的高速串行传输应用,例如EEPROM和Flash存储器
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
“ 先简单的做些了解,关键是对图中层次的理解。” I2C bus 是multi-master 总线,单条bus上也可以有多个slave(device)。 一个host系统中可能存在多个这样的bus 和 bus adaptor。 图例:有 2个adaptor 和 3 个device(分别挂在两个adaptor 上)
总线适配器Adaptor struct i2c_adaptor
I2C Core i2c-core对设备驱动屏蔽了不同adaptor 硬件的细节,也就是对设备驱动完全透明.
http://www.embexperts.com/viewthread.php?tid=186&extra=page%3D1 一般关注core层以上,作为基础设施的adapter驱动应该已注册,所以重点关注i2c_add_driver。 453 #define i2c_add_driver(driver) \ 454 i2c_register_driver(THIS_MODULE, driver) 也就是i2c_register_driver ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 一些硬件知识: http://blog.csdn.net/sirzjp/article/details 串行总线I2C由数据线SDA、时钟线SCL 构成,双工同步数据传输。 如果在系统中同时存在2个或2个以上的主器件节点企图控制总线,则形成总线冲突状态。 由于I2C引入了同步时钟和总线仲裁机制,即使出现总线冲突也不会造成信息丢失。 发生总线冲突时,为了避免信息丢失,需要进行总线仲裁以决定谁是主控器。总线仲裁是通过裁定SDA线上的控制权来解决的。 时钟同步是连接到SCL线上的所有器件进行“线与”实现的。只要有一个器件向SCL输出低电平,SCL就为低电平。因此SCL线的低电平时间由时钟低电平期最长的器件决定,而高电平时间由时钟高电平期最短的器件决定,由此形成了时钟的同步。 从设备地址也支持7位和10位方式,但大多数设备都是使用7位地址。
在通信过程应注意以下6点: ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- http://blog.csdn.net/sdustliyang/article/details/6743453 I2C的设备驱动是通过i2c_add_driver(&my_driver)向i2c-core注册,
int i2c_register_driver(struct module *owner, struct i2c_driver *driver) { int res; /* Can't register until after driver model init*/ if (unlikely(WARN_ON(!i2c_bus_type.p))) return -EAGAIN; /* add the driver to the list of i2c drivers in the driver core */
/* * i2c_driver内嵌的标准driver赋值,其bus指定为i2c_bus_type */ driver->driver.owner = owner; driver->driver.bus = &i2c_bus_type; /* When registration returns, the driver core * will have called probe() for all matching-but-unbound devices. */
/*注册标准的driver,driver注册后会去i2c_bus_type的设备链表上匹配 *设备,匹配函数用的是bus端的,也就是i2c_device_match,如果匹配成功 *将建立标准关联,并且将调用bus端的probe函数初始化这个设备,即 *函数i2c_device_probe,下面会逐个分析 */ res = driver_register(&driver->driver); if (res) return res; pr_debug("i2c-core: driver [%s] registered/n", driver->driver.name); /* * 把该driver的clients初始化,该成员连接着这个driver可以操作的具 * 体设备 */ INIT_LIST_HEAD(&driver->clients); /* Walk the adapters that are already present */ mutex_lock(&core_lock);
/* * 遍历挂接在该i2c设备链表上的设备,并对其都调用__process_new_driver * 函数 */ bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver); mutex_unlock(&core_lock); return 0; } ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
" 注册的i2c_board_info数组中的信息没有生成i2c_client.? "
/** 这点注释中已经说明了。查看i2c_adapter的注册代码可以发现, i2c_adapter注册的时候 --> 扫描已经注册的board_info的链表 -->为每一个注册的信息调用i2c_new_device函数生成i2c_client 这样在i2c_driver注册的时候,设备和驱动就能匹配并调用probe.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 关于i2c_client的生成,是i2c_new_device的功劳,将平台资源 i2c_board_info配置的内容转移到驱动代码。
426 /** 427 * i2c_new_device - instantiate an i2c device 428 * @adap: the adapter managing the device 429 * @info: describes one I2C device; bus_num is ignored 430 * Context: can sleep 431 * 432 * Create an i2c device. Binding is handled through driver model 433 * probe()/remove() methods. A driver may be bound to this device when we 434 * return from this function, or any later moment (e.g. maybe hotplugging will 435 * load the driver module). This call is not appropriate for use by mainboard 436 * initialization logic, which usually runs during an arch_initcall() long 437 * before any i2c_adapter could exist. 438 * 439 * This returns the new i2c client, which may be saved for later use with 440 * i2c_unregister_device(); or NULL to indicate an error. 441 */ 442 struct i2c_client * 443 i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) 444 { 445 struct i2c_client *client; 446 int status; 447 448 client = kzalloc(sizeof *client, GFP_KERNEL); 449 if (!client) 450 return NULL; 451 452 client->adapter = adap; 453 454 client->dev.platform_data = info->platform_data; 455 456 if (info->archdata) 457 client->dev.archdata = *info->archdata; 458 459 client->flags = info->flags; 460 client->addr = info->addr; 461 client->irq = info->irq; 462 463 strlcpy(client->name, info->type, sizeof(client->name)); 464 465 /* Check for address validity */ 466 status = i2c_check_client_addr_validity(client); 467 if (status) { 468 dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n", 469 client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr); 470 goto out_err_silent; 471 } 472 473 /* Check for address business */ 474 status = i2c_check_addr_busy(adap, client->addr); 475 if (status) 476 goto out_err; 477 478 client->dev.parent = &client->adapter->dev; 479 client->dev.bus = &i2c_bus_type; 480 client->dev.type = &i2c_client_type; 481 #ifdef CONFIG_OF 482 client->dev.of_node = info->of_node; 483 #endif 484 485 dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), 486 client->addr); 487 status = device_register(&client->dev); 488 if (status) 489 goto out_err; 490 491 dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n", 492 client->name, dev_name(&client->dev)); 493 494 return client; 495 496 out_err: 497 dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " 498 "(%d)\n", client->name, client->addr, status); 499 out_err_silent: 500 kfree(client); 501 return NULL; 502 } 503 EXPORT_SYMBOL_GPL(i2c_new_device); |