文档库 最新最全的文档下载
当前位置:文档库 › LinuxI2C总线详解

LinuxI2C总线详解

LinuxI2C总线详解
LinuxI2C总线详解

Linux I2C 总线详解

㈠ Overview

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

·I2C核心:

I2C核心提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法(即“algorithm”)上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。这部分是与平台无关的。

·I2C总线驱动:

I2C总线驱动是对I2C硬件体系结构中适配器端的实现。I2C总线驱动主要包含了I2C适配器数据结构i2c_adapter、I2C适配器的algorithm数据结构i2c_algorithm和控制I2C适配器产生通信信号的函数。经由I2C总线驱动的代码,我们可以控制I2C适配器以主控方式产生开始位、停止位、读写周期,以及以从设备方式被读写、产生ACK等。不同的CPU平台对应着不同的I2C 总线驱动。

总线驱动的职责,是为系统中每个I2C总线增加相应的读写方法。但是总线驱动本身并不会进行任何的通讯,它只是存在在那里,等待设备驱动调用其函数。

这部分在MTK 6516中是由MTK已经帮我们实现了的,不需要我们更改。

· I2C设备驱动:

I2C设备驱动是对I2C硬件体系结构中设备端的实现。设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。I2C设备驱动主要包含了数据结构i2c_driver和

i2c_client,我们需要根据具体设备实现其中的成员函数。在Linux内核源代码中的drivers 目录下的i2c_dev.c文件,实现了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在Android2.1版上用的是Legacy的架构,而在Android2.2版上用的是new-style的架构。(在这里我就只说明Android2.2的new-style的实现方法)

要完成I2C设备的驱动,我们可以分三步走:

第一步:完成适配器的注册(总线);

第二步:完成I2C client的设备注册(设备);

第三步:完成I2C client驱动的注册(驱动);

我们分别给予介绍:(I2C-mt6516.c)

⑴就总线而言,其本质只需要我们填充俩个结构体就可以了:

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);//申请表示i2c设备的结构体空间

if (!devinfo) {

pr_debug("i2c-core: can't register boardinfo!\n");

status = -ENOMEM;

break;

}

/* 填写i2c设备描述结构*/

devinfo->busnum = busnum;

devinfo->board_info = *info;

list_add_tail(&devinfo->list, &__i2c_board_list);//添加到全局链表__i2c_board_list中}

mutex_unlock(&__i2c_board_lock);

return status;

}

在系统初始化的过程中,我们可以通过i2c_register_board_info,将所需要的I2C从设备加入一个名为__i2c_board_list双向循环链表,系统在成功加载I2C主设备adapt后,就会对这张链表里所有I2C从设备逐一地完成i2c_client的注册。

第二步:

系统初始化的时候,会根据板级i2c设备配置信息,创建i2c客户端设备(i2c_client),添加到i2c子系统中:static void i2c_scan_static_board_info (struct i2c_adapter *adapter)

{

struct i2c_devinfo *devinfo;

mutex_lock(&__i2c_board_lock);

list_for_each_entry(devinfo, &__i2c_board_list, list) { //遍历全局链表__i2c_board_list if (devinfo->busnum == adapter->nr

&& !i2c_new_device(adapter,

&devinfo->board_info))

printk(KERN_ERR "i2c-core: can't create i2c%d-%04x\n",

i2c_adapter_id(adapter),

devinfo->board_info.addr);

}

mutex_unlock(&__i2c_board_lock);

}

struct i2c_client *i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)

{

struct i2c_client *client;

int status;

client = kzalloc(sizeof *client, GFP_KERNEL);

if (!client)

return NULL;

client->adapter = adap;

client->dev.platform_data = info->platform_data;

if (info->archdata)

client->dev.archdata = *info->archdata;

client->flags = info->flags;

client->addr = info->addr;

client->irq = info->irq;

strlcpy(client->name, info->type, sizeof(client->name));

/* Check for address business */

status = i2c_check_addr(adap, client->addr);

if (status)

goto out_err;

client->dev.parent = &client->adapter->dev;

client->dev.bus = &i2c_bus_type;

client->dev.type = &i2c_client_type;

dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),

client->addr);

status = device_register(&client->dev);

if (status)

goto out_err;

dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",

client->name, dev_name(&client->dev));

return client;

out_err:

dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "

"(%d)\n", client->name, client->addr, status);

kfree(client);

return NULL;

}

IDR机制:完成的是设备ID和结构体的关联。

__i2c_first_dynamic_bus_num:当前系统允许的动态总线的最大值。

i2c_scan_static_board_info(adap);/*完成新类型i2c设备的注册,一般只在主板初始化时*/ 此函数为整个I2C子系统的核心,它会去遍历一个由I2C从设备组成的双向循环链表,并完成所有I2C从设备的i2c_client的注册。

struct i2c_devinfo *devinfo; //已经建立好了的I2C从设备链表

status = i2c_check_addr(adap, client->addr);

注:

特别要提一下的是这个“i2c_check_addr”,引用<>里的话:“i2c 设备的7 位地址是就当前i2c 总线而言的,是“相对地址”。不同的i2c 总线上的设备可以使用相同的7 位地址,但是它们所在的i2c 总线不同。所以在系统中一个i2c 设备的“绝对地址”由二元组(i2c 适配器的ID 和设备在该总线上的7 位地址)表示。”,所以这个函数的作用主要是排除同一i2c总线上出现多个地址相同的设备。

3、I2C驱动注册:

第一步:

static inline int i2c_add_driver(struct i2c_driver *driver)

{

return i2c_register_driver(THIS_MODULE, driver);

}

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 */

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.

*/

res = driver_register(&driver->driver);

if (res)

return res;

pr_debug("i2c-core: driver [%s] registered\n", driver->https://www.wendangku.net/doc/df14747886.html,);

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函数。

3、进入probe

该过程困惑了我一段时间,其实要进入自己驱动的probe首先需要进入总线的probe,而进入总线probe的前提是与总线的match成功。

待解决的困惑:

1、I2C从设备名;

Legacy 的相关知识:

(一)Linux的I2C驱动框架中的主要数据结构及其关系

Linux的I2C驱动框架中的主要数据结构包括:i2c_driver、i2c_client、i2c_adapter 和i2c_algorithm。

i2c_adapter对应于物理上的一个适配器,这个适配器是基于不同的平台的,一个I2C 适配器需要i2c_algorithm中提供的通信函数来控制适配器,因此i2c_adapter中包含其使用的i2c_algorithm的指针。i2c_algorithm中的关键函数master_xfer()以i2c_msg为单位产生I2C访问需要的信号。不同的平台所对应的master_xfer()是不同的,开发人员需要根据所用平台的硬件特性实现自己的XXX_xfer()方法以填充i2c_algorithm的master_xfer指针。

i2c_ driver对应一套驱动方法,不对应于任何的物理实体。i2c_client对应于真实的物理设备,每个I2C设备都需要一个i2c_client来描述。i2c_client依附于i2c_adpater,这与I2C硬件体系中适配器和设备的关系一致。i2c_driver提供了i2c-client与i2c-adapter产生联系的函数。当attach a_dapter()函数探测物理设备时,如果确定存在一个client,则把该client使用的i2c_client数据结构的adapter指针指向对应的i2e_ adapter,driver指针指向该i2c_driver,并调用i2e_adapter的client_register()函数来注册此设备。相反的过程发生在i2c_ driver的detach_client()函数被调用的时候。

(二)Linux的I2C体系结构中三个组成部分的作用

I2C核心提供了一组不依赖于硬件平台的接口函数,I2C总线驱动和设备驱动之间依赖于I2C核心作为纽带。I2C核心提供了i2c_adapter的增加和删除函数、i2c_driver的增加和删除函数、i2c_client的依附和脱离函数以及i2c传输、发送和接收函数。i2c传输函数

i2c_transfer()用于进行I2C适配器和I2C设备之间的一组消息交互i2c_master_send()函数和i2c_master_recv()函数内部会调用i2c_ transfer()函数分别完成一条写消息和一条读消息.

I2C总线驱动包括I2C适配器驱动加载与卸载以及I2C总线通信方法。其中I2C适配器驱动加载(与卸载)要完成初始化(释放)I2C适配器所使用的硬件资源,申请I/0地址、中断号、通过i2c_add_ adapter()添加i2c_adapter的数据结构(通过i2c_del_adapter()删除i2c

_adapter的数据结构)的工作。12C总线通信方法主要对特定的I2C适配器实现i2c_algorithm 的master_xfer()方法来实现i2c_ msg的传输。不同的适配器对应的master_xfer()方法由其处理器的硬件特性决定。

I2C设备驱动主要用于I2C设备驱动模块加载与卸载以及提供I2C设备驱动文件操作接口。I2C 设备驱动的模块加载通用的方法遵循以下流程:首先通过register_chrdev()将I2C设备注册为一个字符设备,然后利用I2C核心中的i2c_add_a_dapter()添加i2c_driver。调用

i2c_add_adapter()过程中会引发i2c_driver结构体中的YYY_attach_adapter()的执行,它通过调用I2C核心的i2e_probe()实现物理设备的探测。i2c_probe()会引发yyy_detect()的调用。yyy_detect()中会初始化i2c_ client,然后调用内核的i2e_attach_client()通知I2C 核心此时系统中包含了一个新的I2C设备。之后会引发I2C设备驱动中yyy_init_client()来初始化设备。卸载过程执行相反的操作。

I2C设备驱动模块加载与卸载的流程如图2所示。

can总线协议完全解析

CAN总线协议解析 李玉丽 (吉林建筑工程学院电气与电子信息工程学院,吉林长春,130021 ) 摘要:现场总线的发展与应用引起了传统控制系统结构的改变。控制局域网(C AN)总线因其自身的特点被广泛应用于 自动控制领域。本文对C AN总线协议作了详尽解析。 关键词:C AN总线;隐性位;显性位;节点 中图分类号:T U 85 文献标识码:A CAN(Cont roll e r A rea N et work)是分布式实时控 制系统的串行通信局域网,称谓CAN总线。在数据 实时传输中,设计独特、低成本,具有高可靠性,得到 广泛应用。 本文着重解析C AN 技术规范2.0B 版的CAN 的分层结构规范和CAN 报文结构规范。重点在于 充分理解CAN总线协议精髓,有助于CAN总线的 局网设计、软件编程、局网维护。 一、C AN的分层结构 CAN 遵从O SI ( Ope n Syste m I nte rc onnec ti on Re fe re nce Mode l ) 模型,其分层结构由高到低如图1 所示。 图1 C AN的分层结构 对应OSI 模型为两层,实际为三层,即LLC、 MA C、PL S。由此而知,对应于CAN总线系统每个 节点都是三层结构。数据发送节点数据流为LLC→ MA C→P LS ,然后将数据发送到总线上;而对于挂在 总线上的所有节点(包括发送节点)的接收的数据流 为PL S→MA C→LLC。 这种分层结构的规范保证了CAN 总线的多主 方式工作模式,即不分主从,非破坏性的仲裁工作模 式。而LLC 层的报文滤波功能可实现点到点、一点 对多点、全局广播、多点对一点,多点对多点等数据 传递方式。 各分层主要功能如下: LLC 层:接收滤波、超载通知、恢复管理; MAC 层:控制帧结构、执行仲裁、错误检测、出 错标定、故障界定。该层是CAN的核心; PL S 层:位编码/ 解码、位定时。 二、CAN总线的报文规范 CAN报文的传送有4 种不同类型的帧结构,数 据帧、远程帧、出错帧、超载帧。CA B2.0B 有4 种帧 格式。 (一)数据帧

AMBAAXI总线详解

AXI 总线协议资料整理 第一部分: 1、AXI 简介:AXI (Adva need eXte nsible In terface 是一种总线协议,该协议是ARM 公司提出的AMBA( Advanced Microcontroller Bus Architecture)3.0 协议中最重要的部分,是一种面向高性能、高带宽、低延迟的片内总线。它的地址/控 制和数据相位是分离的,支持不对齐的数据传输,同时在突发传输中,只需要首 地址,同时分离的读写数据通道、并支持显著传输访问和乱序访问,并更加容易就行时序收敛。AXI 是AMBA 中一个新的高性能协议。AXI 技术丰富了现有的AMBA标准内容,满足超高性能和复杂的片上系统(SoC)设计的需求。 2、AXI 特点:单向通道体系结构。信息流只以单方向传输,简化时钟域间的桥接,减少门数量。当信号经过复杂的片上系统时,减少延时。 支持多项数据交换。通过并行执行猝发操作,极大地提高了数据吞吐能力,可在更短的时间内完成任务,在满足高性能要求的同时,又减少了功耗。 独立的地址和数据通道。地址和数据通道分开,能对每一个通道进行单独优化,可以根据需要控制时序通道,将时钟频率提到最高,并将延时降到最低。第二部分: 本部分对AXI1.0 协议的各章进行整理。 第一章 本章主要介绍AXI 协议和AXI 协议定义的基础事务。 1 、AXI 总线共有5 个通道分别是read address channel 、write address channel 、read data channel、write data channe、l write response ehanne。每一个AXI传输通道都是单方向的。 2、每一个事务都有地址和控制信息在地址通道( address channel 中,用来描述被传输数据的性质。 3、读事务的结构图如下:

AI总线中文详解

AXI总线协议资料整理 第一部分: 1、AXI简介:AXI(Advanced eXtensible Interface)是一种总线协议,该协议是ARM公司提出的AMBA(Advanced Microcontroller Bus Architecture)3.0协议中最重要的部分,是一种面向高性能、高带宽、低延迟的片内总线。它的地址/控制和数据相位是分离的,支持不对齐的数据传输,同时在突发传输中,只需要首地址,同时分离的读写数据通道、并支持显著传输访问和乱序访问,并更加容易就行时序收敛。AXI 是AMBA 中一个新的高性能协议。AXI 技术丰富了现有的AMBA 标准内容,满足超高性能和复杂的片上系统(SoC)设计的需求。 2、 AXI 特点:单向通道体系结构。信息流只以单方向传输,简化时钟域间的桥接,减少门数量。当信号经过复杂的片上系统时,减少延时。 支持多项数据交换。通过并行执行猝发操作,极大地提高了数据吞吐能力,可在更短的时间内完成任务,在满足高性能要求的同时,又减少了功耗。 独立的地址和数据通道。地址和数据通道分开,能对每一个通道进行单独优化,可以根据需要控制时序通道,将时钟频率提到最高,并将延时降到最低。 第二部分: 本部分对AXI1.0协议的各章进行整理。 第一章 本章主要介绍AXI协议和AXI协议定义的基础事务。 1、 AXI总线共有5个通道分别是read address channel 、 write address channel 、 read data channel 、 write data channel、 write response channel。每一个AXI传输通道都是单方向的。2、每一个事务都有地址和控制信息在地址通道(address channel)中,用来描述被传输数据的性质。 3、读事务的结构图如下:

单片机常用总线讲解

第8章单片机常用总线讲解 8.1 C总线接口 80C51单片机本身不具有总线接口,但是通过软件进行模拟,可以挂接具有C接口的芯片。 8.1.1 C总线的介绍 串行扩展总线在单片机系统中的应用是目前单片机技术发展的一种趋势。在目前比较流行的几种串行扩展总线中,总线以其严格的规范和众多带接口的外围器件而获得广泛应用。总线是PHILIPS公司推出的芯片间串行传输总线,它由两根线组成,一根是串行时钟线(SCL),一根是串行数据线(SDA)。主控器利用串行时钟线发出时钟信号,利用串行数据线发送或接收数据。总线由主控器电路引出,凡具有接口的电路(受控器)都可以挂接在总线上,主控器通过总线对受控器进行控制。 随着总线研究的深入,总线已经广泛应用于视/音频领域、IC卡行业和一些家电产品中,在智能仪器、仪表和工业测控领域也越来越多地得到应用。 8.1.2 总线的特点 总线的广泛应用是同它卓越的性能和简便的操作方法分不开的。总线的特点主要表现在以下几个方面: 硬件结构上具有相同的硬件接口界面。总线系统中,任何一个总线接口的外围器件,不论其功能差别有多大,都是通过串行数据线(SDA)和串行时钟线(SCL)连接到总线上。这一特点给用户在设计用用系统中带来了极大的便利性。用户不必理解每个总线接口器件的功能如何,只需将器件的SDA和SCL引脚连到总线上,然后对该器件模块进行独立的电路设计,从而简化了系统设计的复杂性,提高了系统抗干扰的能力。 线接口器件地址具有根大的独立性。每个接口芯片具有唯一的器件地址,由于不能发出串行时钟信号而只能作为从器件使用。各器件之间互不干扰,相互之间不能进行通信,各个器件可以单独供电。单片机与器件之间的通信是通过独一无二的器件地址来实现的。 软件操作的一致性。由于任何器件通过总线与单片机进行数据传送的方式是基本一样的, .v .. ..

各类总线解析

查漏补缺-总线 以前在找工作的时候,每次笔试总会遇到各种总线协议什么的题目,每次都头大,不是没听到过,而是基本上都是了解但是不清晰的状态,需要查资料、翻书才能搞得清楚的。也没太在意,但是到了实际工作的时候,慢慢地发现它就变成一个疑难杂症了(因为他总是不能被记住,每到要的时候到处找资料),我觉得做技术的东西就是要把是事情做牢靠,把产品做稳定。那些个所谓的高科技、高技术含量的的东西,如果不稳定那就跟垃圾无异。 根据以前碰到的问题,经过查阅资料和一些自己的理解汇总如下,今天特地把他整理出来,大家如果觉得有必要的可以瞅瞅,不过高手就可以飘过了。 微机中总线一般有内部总线、系统总线和外部总线。内部总线是微机内部各外围芯片与处理器之间的总线,用于芯片一级的互连;而系统总线是微机中各插件板与系统板之间的总线,用于插件板一级的互连;外部总线则是微机和外部设备之间的总线,微机作为一种设备,通过该总线和其他设备进行信息与数据交换,它用于设备一级的互连。内部总线有以下几种类型。 1.1IIC总线 I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。 为了避免总线信号的混乱,要求各设备连接到总线的输出端时必须是漏极开路(OD)输出或集电极开路(OC)输出。设备上的串行数据线SDA接口电路应该是双向的,输出电路用于向总线上发送数据,输入电路用于接收总线上的数据。而串行时钟线也应是双向的,作为控制总线数据传送的主机,一方面要通过SCL输出电路发送时钟信号,另一方面还要检测总线上的SCL电平,以决定什么时候发送下一个时钟脉冲电平;作为接受主机命令的从机,要按总线上的SCL 信号发出或接收SDA上的信号,也可以向SCL线发出低电平信号以延长总线时钟信号周期。总线空闲时,因各设备都是开漏输出,上拉电阻Rp使SDA和SCL 线都保持高电平。任一设备输出的低电平都将使相应的总线信号线变低,也就是说:各设备的SDA是“与”关系,SCL也是“与”关系。

I2C总线时序详解

I2C 总线时序详解 I2C总线位传输 由于连接到I2C总线的器件有不同种类的工艺(CMOSNMOS双极性),逻辑0 (低)和逻辑1 (高)的电平不是固定的,它由电源VCC的相关电平决定,每传输一个数据位就产生一个时钟脉冲。 数据的有效性 SDA线上的数据必须在时钟的高电平周期保持稳定。数据线的高或低电平状态只有在SCL线的时钟信号是低电平时才能改变。 I2C位传输数据有效性 起始和停止条件 SCL线是高电平时,SDA线从高电平向低电平切换,这个情况表示起始条件; SCL线是高电平时,SDA线由低电平向高电平切换,这个情况表示停止条件。 起始和停止条件一般由主机产生,总线在起始条件后被认为处于忙的状态 SDA

起始和停止条件 ,在停止条件的某段时间后总线被认为再次处于空闲状态。如果产生重复起始条件而不产生停止条件,总线会一直处于忙的状态,此时的起始条件(S)和重复起始条件(Sr)在功能上是一样的。 I2C总线数据传输 字节格式 发送到SDA线上的每个字节必须为8位,每次传输可以发送的字节数量不受限制。每个字节后必须跟一个响应位。首先传输的是数据的最高位 (MSB,如果从机要完成一些其他功能后(例如一个内部中断服务程序)才能接收或发送下一个完整的数据字节,可以使时钟线SCL保持低电平, 迫使主机进入等待状态,当从机准备好接收下一个数据字节并释放时钟线SCL后数据传输继续。应答响应 数据传输必须带响应,相关的响应时钟脉冲由主机产生。在响应的时钟脉冲期间发送器释放SDA线(高)。 在响应的时钟脉冲期间,接收器必须将SDA线拉低,使它在这个时钟 脉冲的高电平期间保持稳定的低电平。 通常被寻址的接收器在接收到的每个字节后,除了用CBUS地址开头的 数。

CAN总线解析

一、概述 CAN(Controller Area Network)即控制器局域网,是一种能够实现分布式实时控制的串行通信网络。 想到CAN就要想到德国的Bosch公司,因为CAN就是这个公司开发的(和Intel)CAN 有很多优秀的特点,使得它能够被广泛的应用。比如:传输速度最高到1Mbps,通信距离最远到10KM,无损位仲裁机制,多主结构。 近些年来,CAN控制器价格越来越低,很多MCU也集成了CAN控制器。现在每一辆汽车上都装有CAN总线。 一个典型的CAN应用场景: 二、CAN总线标准 CAN总线标准只规定了物理层和数据链路层,需要用户来自定义应用层。不同的CAN标准仅物理层不同。

CAN收发器负责逻辑电平和物理信号之间的转换,将逻辑信号转换成物理信号(差分电平)或者将物理信号转换成逻辑电平。 CAN标准有两个,即IOS11898和IOS11519,两者差分电平特性不同。(有信号时,CANH 3.5V,CANL 1.5V,即显性;没有信号时,CANH 2.5V,CANL 2.5V,即隐性) IOS11898高速CAN电平中,高低电平的幅度低,对应的传输速度快。 双绞线共模消除干扰,是因为电平同时变化,电压差不变。 2.1物理层 CAN有三种接口器件

多个节点连接,只要有一个为低电平,总线就为低电平,只有所有的节点都输出高电平时,才为高电平。所谓“线与”。 CAN总线有5个连续性相同的位后,就会插入一个相反位,产生跳变沿,用于同步。从而消除累计误差。 和485、232一样,CAN的传输速度与距离成反比。 CAN总线终端电阻的接法:

特点:低速CAN在CANH和CANL上串入2.2kΩ的电阻;高速CAN在CANH和CANL 之间并入120Ω电阻。为什么是120Ω,因为电缆的特性阻抗为120Ω,为了模拟无限远的传输线。(因为大多数双绞线电缆特性阻抗大约在100~120Ω。) 120欧姆只是为了保证阻抗完整性,消除回波反射,提升通信可靠性的,因此,其只需要在总线最远的两端接上120欧姆电阻即可,而中间节点并不需要接(接了反而有可能会引起问题)。因此各位在使用CAN Omega做CAN总线侦听的时候,大多数情况下是不需要这个120欧姆电阻的,当然,即使当前网络中并没有终端匹配电阻,只要传输线长度不长(比如SysCan360比赛环境中,传输线只有1-2米)CAN节点数量不多的情况下,不要这个120欧姆电阻也完全可以工作,甚至,你接任意电阻都是不会有影响的。因为此时传输线长度和波长还相差甚远,节点不多的情况下,反射波的叠加信号强度也不会很强,因此传输线效应完全可以忽略。 而哪些情况需要呢,主要就是,当使用2个CAN Omega对发或者当前网络中仅有2个CAN设备的时候,此时两个端点最好都加上终端匹配电阻,当然,前面也说过了,传输线长度不长的时候,也可以不需要2端120欧姆电阻,但为了信号完整性考虑,加上这两个电阻才是严谨的。 2个120欧姆电阻的意义在于,使用USB CAN调试某些不带终端电阻的中间节点设备时,有时候CAN总线上没有2个120欧姆电阻通信可能会异常,此时可以接入2个120欧姆电阻作为2个终端电阻来作阻抗匹配,这时候其他端点不应接入任何终端电阻!并且,这2个120欧姆电阻不可用1个60欧姆电阻代替!

常见九大现场总线全解析

常见九大现场总线全解析 内容来源网络,由“深圳机械展(11万㎡,1100多家展商,超10万观众)”收集整理!更多cnc加工中心、车铣磨钻床、线切割、数控刀具工具、工业机器人、非标自动化、数字化无人工厂、精密测量、3D打印、激光切割、钣金冲压折弯、精密零件加工等展示,就在深圳机械展. 目前国际上有40多种现场总线,但没有任何一种现场总线能覆盖所有的应用面,按其传输数据的大小可分为3类:传感器总线(sensorbus),属于位传输;设备总线(devicebus),属于字节传输;现场总线,属于数据流传输。 什么是现场总线? 现场总线(Fieldbus)是20世纪80年代末、90年代初国际上发展形成的,用于现场总线技术过程自动化、制造自动化、楼宇自动化等领域的现场智能设备互连通讯网络。它作为工厂数字通信网络的基础,沟通了生产过程现场及控制设备之间及其与更高控制管理层次之间的联系。它不仅是一个基层网络,而且还是一种开放式、新型全分布控制系统。这项以智能传感、控制、计算机、数字通讯等技术为主要内容的综合技术,已经受到世界范围的关注,成为自动化技术发展的热点,并将导致自动化系统结构与设备的深刻变革。现场总线设备的工作环境处于过程设备的底层,作为工厂设备级基础通讯网络,要求具有协议简单、容错能力强、安全性好、成本低的特点:具有一定的时间确定性和较高的实时性要求,还具有网络负载稳定,多数为短帧传送、信息交换频繁等特点。由于上述特点,现场总线系统从网络结构到通讯技术,都具有不同上层高速数据通信网的特色。

目前国际上有40多种现场总线,但没有任何一种现场总线能覆盖所有的应用面,按其传输数据的大小可分为3类:传感器总线(sensorbus),属于位传输;设备总线(devicebus),属于字节传输;现场总线,属于数据流传输。下面让我一起去认识主要的几种总线。 一、FF现场总线 FF现场总线基金会是由WORLDFIPNA(北美部分,不包括欧洲)和ISPFoundation于1994年6月联合成立的,它是一个国际性的组织,其目标是建立单一的、开放的、可互操作的现场总线国际标准。这个组织给予了IEC现场总线标准起草工作组以强大的支持。这个组织目前有l00多成员单位,包括了全世界主要的过程控制产品及系统的生产公司。1997年4月这个组织在中国成立了中国仪协现场总线专业委员会(CFC)。致力于这项技术在中国的推广应用。FF成立的时间比较晚,在推出自己的产品和把这项技术完整地应用到工程上相对于PROFIBUS和WORLDFIP要晚。但是正由于FF是1992年9月成立的,是以

CNA总线详解

详解车载网络CAN总线系统 息,并将此信息发送至相对应的控制单元内。 『车身上各种控制单元的分布图』 通过上图我们可以看到车身上的各种控制单元,车越高级,车身上的控制单元也就越多,每个控制单元都可看做一台独立的电脑,它可以接受信息,同时能对各种信息进行处理、分析,然后发出一个指令。比如发动机控制单元会接受来自进气压力传感器、发动机温度传感器、油门踏板位置传感器、发动机转速传感器等等的信息,在经过分析和处理后会发送相应的指令来控制喷油嘴的喷油量、点火提前角等等,其它控制单元的工作原理也都类似。在这里可以给大家做一个比喻,车上的各种控制单元就好比一家公司各个部门的经理,每个部门的经理接受来自自己部门员工的工作汇报,经过分析作出决策,并命令该部门的员工去执行。

『控制单元』 车身上的这些控制单元并不是独立工作的,它们作为一个整体,需要信息的共享,那么这就存在一个信息传递的问题。比如发动机控制单元内的发动机转速与油门踏板位置这两个信号也需要传递给自动变速器的控制单元,然后自动变速器控制单元会据此来发出升档和降档的操作指令,那么两个控制单元之间又是如何进行通信的呢? 『每项信息都通过各自独立的数据线进行交换』 目前在车辆上应用的信息传递形式有两种。第一种是每项信息都通过各自独立的数据线进行交换。比如两个控制单元间有5种信息需要传递,那么则需要5根独立的数据线。也就是说信息的种类越多,数据线的数量和控制单元的针脚数也会相应增加。这些复杂繁多的线束无疑会增加车身重量,也为整车的布线带来一定困难。

『所有信息都通过两根数据线进行交换』 第二种方式是控制单元之间的所有信息都通过两根数据线进行交换,这种数据线也叫CAN 数据总线。通过该种方式,所有的信息,不管信息容量的大小,都可以通过这两条数据线进行传递,这种方式充分的提高了整个系统的运行效率。我们常见的电脑键盘有104个按键,却可以发出数百种不同的指令,但键盘与电脑主机之间的数据连接线只有7根,键盘正是依靠这7根数据连接线上不同的编码信号来传递信息的。CAN数据总线的原理也正是如此。这种一线一用的专线制改为一线多用制,可以大大减少汽车上电线的数量,同时也简化了整车的布线。 在了解到两个控制单元是通过两根数据线来进行信息交换的基础上,我们可以将其推而广之,多个控制单元之间的通信其实就是将每个控制单元都连接到这两条CAN总线上,从而实现多个控制单元间的信息共享。 『多个控制单元间的信息传递』 目前汽车上的CAN总线连接方式主要有两种,一种是用于驱动系统的高速CAN总线,速率可达到500kb/s,另一种是用于车身系统的低速CAN总线,速率为100kb/s。当然对于中高级轿车还有一些如娱乐系统或智能通讯系统的总线,它们的传输速率更高,可以超过1Mb/s。高速CAN总线主要连接发动机控制单元、ABS控制单元、安全气囊控制单元、组合仪表等这

相关文档