当前位置:文档之家› I2C的原理与应用

I2C的原理与应用

I2C的原理与应用
I2C的原理与应用

EEPROM的I2C与并口的读写通设计

试验目的:认识计算机并口和I2C总线,用计算机并口模拟I2C总线,最后,以24CL02为例,完成对I2C EEPROM的读写操作。

试验器材:一台装有 Tubor C 2.0 的计算机、一条25针并口电缆(看图1插头可要选对了)、自制的用于插入EEPROM芯片的适配器(图2)、一片 EEPROM 如HT24LC02或AT24C02等。

试验前的准备知识:

一、I2C总线:i2c总线是 Philips 公司首先推出的一种两线制串行传输总线。它由一根数据线(SDA)和一根时钟线(SDL)组成。i2c总线的数据传输过程如图3所示,基本过程为:

1、主机发出开始信号。

2、主机接着送出1字节的从机地址信息,其中最低位为读写控制码(1为读、0为写),高7位为从机器件地址代码。

3、从机发出认可信号。

4、主机开始发送信息,每发完一字节后,从机发出认可信号给主机。

5、主机发出停止信号。

I2C总线上各信号的具体说明:

开始信号:在时钟线(SCL)为高电平其间,数据线(SDA)由高变低,将产生一个开始信号。

停止信号:在时钟线(SCL)为高电平其间,数据线(SDA)由低变高,将产生一个停止信号。

应答信号:既认可信号,主机写从机时每写完一字节,如果正确从机将在下一个时钟周期将数据线(SDA)拉低,以告诉主机操作有效。在主机读从机时正确读完一字节后,主机在下一个时钟周期同样也要将数据线(SDA)拉低,发出认可信号,告诉从机所发数据已经收妥。(注:读从机时主机在最后1字节数据接收完以后不发应答,直接发停止信号)。

注意:在I2C通信过程中,所有的数据改变都必须在时钟线SCL为低电平时改变,在时钟线SCL为高电平时必须保

持数据SDA信号的稳定,任何在时钟线为高电平时数据线上的电平改变都被认为是起始或停止信号。

下面以24LC02为例,对几个主要工作时序做详细说明。

24LC02的控制字(节)格式(图4):发送时紧跟开始信号后的4位是器件选择位,通常为‘1010’,它和后面的3位器件地址码(由24LC02的A0、A1、A2上的电平决定)共同构成了7位的从机地址。从机地址后紧跟1位读/写控制位,该位为1表示读,为0表示写。图中最后1位是应答位,这里它由从机给出。

24LC02写时序(图⑤):主机发送开始信号,接着发出从机地址和写控制码,主机接收从机发出的应答,主机发送1字节的地址信息,主机接收应答,主机写1字节数据到从机,主机接收应答,主机发出停止信号。写操作完成,1字节数据被写入24LC02内指定地址。24LC02提供一种页写的方式,每次最多可连续写入8字节数据再发送停止信号,当写入数据多时可采用这种方式以加快速度。

24LCO2随机读时序(图⑥):主机发送开始信号,接着发送从机地址和写控制码,主机接收应答,主机发送1字节的的地址信息,主机接收应答(注意:前面的时序为写操作,目的把起始地址写入24CL02缓冲中,以告知随后的读操作从哪个地址开始,这个步骤在读时序中有时被称为“伪写”),主机发送开始信号,主机发送从机地址和读控制码,主机接收应答,主机读取1字节数据,主机不发应答,主机发送停止信号。完成上面步骤,主机已从24LCO2中读出指定地址内1字节数据。

24LC02读时序(图⑦):如图⑦所示,与随机读时序相比,主机没有给从机写入起始地址,所以这种方式用于读取当前地址内的数据。另,24LC02也可以采用连续读的方式(见图⑧),这样每次最多可以读取8字节。注意:连续读时每读完1字节后主机要发应答给主机,但在最后1字节后(即停止信号前)主机不发应答。

数据线(SDA)上的信号:读时,从机在SCL的上升沿将数据放到SDA上,写时,遇到SCL 的上升沿,从机将接收SDA上的数据。

二、并行口:它包含了一批输入/输出端口,在PC机上它是一个25针的 D 型插口,一般用于连接打印机,因此有时也称为打印口。

并行口信号:以打印机为例,并口I/0信号中有些是专门用来把数据传送给打印机的,有些则是用来对传送过程给以控制的,还有将打印机的各种工作状态信息发送给CPU的。详细如表1所示。表中所有信号用低电平(0V)表示逻辑0,用高电平(5V)表示逻辑1(电压都是相对于18-25脚上的接地电势而言),凡是前缀用符号‘-’表示的信号均指低电平为现役信号。

可以看出,编号为2-9针脚上的信号是传递实际数的信号,而其它线上的信号则是用在对打印机进行初始化处理和对打印机动作进行同步上。下面简单介绍一下打印过程以加深对并口的理解,CPU通过并口中16和17脚上的信号来选择打印机,并给以初始化处理。且用13脚上的信号给以响应。在打印机已准备好接收数据时,就将11脚置为低电平(表示可以接收),CPU把数据放到并口的数据线(2-9)上,并通过1脚上的选通信号对打印机的数据进行选通。打印机在收到选通信号时将忙信号(11)置为高电平,表示正在接收数据。数据接收完毕后,打印机在短时间内把现役的确认信号(10脚低电平)发送出去,然后再把忙信号(11)置成低电平(既非现役)并准备好接收更多数据。

并行口硬件:并口行现在通常被集成在系统板上,25针插口上的信号可通过数据锁存器、打印状态和打印机控制三个寄存器(也就是三个输入/输出端口)进行程序设计和控制。计算机系统中通常有多个并行端口,表2列出了它们在输入/输出系统中的地址。需要注意的是这些地址是由系统 BIOS 给出的,并不是硬件的物理地址,所以可以通过设置 BIOS 来改变当前端口的配置。

端口寄存器:表3列出了并行端口寄存器各位的意义。这些信号也是在外部插头上出现的主要信号。不过寄存器中有些信号的极性与插头上相应信号的极性正好相反。比如,选通信号在插头上为低电平时,信号是现役的,而在打印机控制寄存器中则为高电平是现役的。

通过上面的准备知识,应有以下理解:1、可以把并口的25个针脚理解为三个寄存器对外的映射,除了传送8位实际数据的引脚外,还有用于控制打印机和取得打印机当前状态的引脚,这些引脚有的为输入,有的为输出,因此可以像用单片机I/O一样灵活的运用它们。2、I2C总线在通讯过程中,数据线(SDA)上的信号流动方向是不断变化的,如:主机正在写24LC02时,SDA的方向为主机到从机,SDA为输出,写完一字节后,要接收应答时,SDA的方向变为从机到主机,SDA为输入(对于主机)。3、并口模拟I2C总线,其实是用软件控制并口的 I/O 来输入输出 I2C 总线需要的高、低电平信号,从而产生I2C总线的各种时序。

制作试验电路:

试验用的电路如图⑨,分析如后:P1的4-7脚并联(为了加大输出电流),接IC1的VCC 端,为IC1供电。P1的2脚接IC1的SCL端,用做I2C总线的串行时钟输出。因I2C总线中数据线(SDA)在不同的时间可能是输入也可能是输出,所以接在IC1 SDA端上的信号也有两路,输出时,P1 3脚输出低电平T1导通,SDA被置为低电平,P1 3 脚输出高电平T1截止,因 R1的作用SDA被置为高电平。输入时,P1 通过判断 13 脚上的电平高低,来读取SDA上的数据。要注意的是用于输入时T1必须是截止的,以免SDA被箝位。

这个电路具有通用性,24C01、24CO2、24LC64等24系列的I2C EEPROM 均可按这个电路与并口连接,所以不妨把它当作实用工具来认真制作。先找一条并口电缆,看电缆插头的形式,找一个与之配套的25针插座,购买一个拨动式的IC插座,将IC插座按图中IC1的连接方法与找来的并口插座相连,然后按图将T1、R1、C1、直接焊在IC插座或并口插座上,要尽量作的紧凑些。最后将电路固定在一个合适的小塑料盒内,好了,现在它是我们的试验器材,等看过后面的内容,你会发现只要为其配上软件,它就是一个用于读写I2C EEPROM 的好工具。

试验程序编写:

和其它高级语言相比,C 更适合于对硬件编程。本试验所用的程序就是在 Tubor C 2.0 环境下编译通过的。

一、C 语言相关:对本试验较关键的几个函数和运算。

读端口函数 inprotb();可从指定的输入端口读入一个字节,并返回这个字节,用法为:inprotb(端口号或端口地址);例如:b=inprotb(379H);由于379H为‘打印机状态’寄存器的地址,因此执行后变量 b中将存放由函数读取的 379H 的值。

写端口函数 outprotb();可写一字节数据到指定的输出端口,用法为:outprotb(端口地址,整型数);例如:outprotb(378H,1);由于端口地址378H为并口的‘数据锁存器’地址,因此执行后将在并口的 2 脚输出高电平,3-9脚输出低电平。

位运算:位运算的对象只能是整型或字符型数据,本试验程序中用到了两种位运算。左移运算(<<):运算符左边是位移对象,右边是整形表达式,代表左移的位数,左移时,右端补0;左端移出的部分舍弃。右移运算(>>):运算符的使用方法与左移运算符一样,所不同的是移位方向相反。右移时,右端(低位)移出的二进制数舍弃,左端(高位)移入的二进制数分两种情况:对于无符号整数和正整数,高位补 0,对于负整数,高位补 1。举例:假设b和c 为字符型变量,并且 b 已赋初值,用二进制表示时 b 的值为 01110110 ;现在若要求的 b 的第 3 位的二进制数是 1 ,还是 0 ,可暂将 b 的值赋给变量 c (c=b;),再对 c 进行位移运

算,先将 c 右移 2 位(c=c>>2;),再左移 7 位(c=c<<7;),然后用程序判断 c 的值是否为0,为0则所求位的二进制数为 0,否则为所求位的二进制数为 1。经过位移 c 的值变为

‘10000000’,而不是0,因此可以判断 b 的第 3 位中的二进制数是 1。后面的试验程序就是用这种方法来接收应答和读取SDA上的数据的。

二、编程前的分析:现在从编程的角度对图⑨ 的电路再次分析。参见表1、表2、表3。现在计算机上的并口通常被默认的设置成端口2,既数据锁存器地址为378H的端口。

并行口(P1)13脚:它是一个输入端,是‘打印机状态’寄存器(见表2、表3)中的位 4。‘打印机状态’寄存器地址为379H,可以用 C 语言中的 inprotb() 函数来读取379H的值,然后通过位运算即可获得当前P1 13脚(IC1的SDA端)的电平状态。注意:在读端口时,要确认T1是截止的。

并行口(P1)2 脚:它是‘数据锁存’寄存器中的位 0,在这里作为一个输出端。‘数据锁存’寄存器的地址为378H,可以用 C 语言中的 outprotb() 函数给378H的位 0 写入1或0,,从而模拟出 I2C 总线中SCL上的高、低电平。这里需要注意的是,从2脚输出时,用函数写数据锁存器每次只能改变位 0 的状态,而不能影响到其它位的状态。

并行口(P1)3 脚:它是‘数据锁存’寄存器中的位 1,在这里作为输出端与T1基极相连,可以用 C 语言中的 outprotb() 函数给‘数据锁存’378H的位 1 写入1或0,从而控制 T1 的导通和截止,配合 R1 的作用,模拟出I2C时钟线SDA上的高、低电平信号。 3 脚输出低电平将使 T1 导通,SDA既被置为低电平,3 脚输出高电平 T1 截止,由R1将SDA上拉为高电平。要注意操作这一位时不能影响到其它位。

并行口的 4-7 脚:它们分别是‘数据锁存’寄存器中的位2、位3、位4和位5,这4 位全部作为输出端接在IC1的VCC上,通过写端口函数将它们全部写入1(既都输出高电平),用于给IC1提供电源。注意,因这4位是作为电源使用的,必须保证这4位的值始终为1 ,所以每次写378H时要特别注意。这4个引脚是并在一起的,其中若有1位被写成0,就会因高低电平抵消而中断IC1的电源使操作失败,甚至可能会损坏并口。

三、编程:通过上面分析,要用并口来模拟I2C总线来读写 24LC02 ,程序需有以下几部分。

发送I2C开始信号:用 outprotb() 函数向378H写入16进制数“0XFF”(即2-9脚全部输出高电平),SCL和SDA都为高电平,延时一段时间后,向378H写入“0XFD”(其它脚状态不变,只是将位 1 置为低电平),使SDA由高电平变为低电平,即产生了I2C的开始信号。最后将在378H中写入“0XFC”(即其它脚不变,将位0和位1置为低电平)使SCL为低电平,以完成一个时钟,也为后面的读写作准备。

发送I2C停止信号:I2C的停止信号是在SCL为高时,SDA由低变高。程序可按下面步骤来写,用写端口函数向378H写入“0XFC”,使SCL和SDA为低电平,延时一段时间,向378H写入“0XFD”,使SCL变为高电平,SDA为低电平,延时,向378H写入“0XFF”SCL保持不变,使SDA由原来的低电平变为高电平,即产生了一个停止信号。延时一段时间,最后向378H写入

“0XFE”,使SCL为低电平,以完成一个时钟。

发送数据:先把要发送的数据放在一个变量里,然后按位发送。方法为,通过位运算求得欲发送位的值(1或0),然后用写端口函数模拟出SCL和SDA,并按I2C的写时序将一位数据发送出去,程序中可用while循环语句来控制发送的位数和字节数。

主机(并口)发送应答:I2C总线,主机发送应答用在连续读时序中,每读取一字节(8位)后,主机使SDA保持一个时钟周期的低电平。可以用写端口函数先将SDA、SCL置为 0,然后将SCL变高,SDA保持低电平,一个应答信号既被发送,最后将SCL置低,完成一个时钟。

接收数据:并口读取I2C总线的数据时,必须让 T1截止,使用并口的13脚来接收SDA上的数据。可按下面步骤操作,先用写端口函数使SCL为低电平,同时在并口3脚输出高电平使 T1 截止。然后用写端口函数单独将SCL置1,其它位保持不变,模拟出时钟上升沿,IC1 将把一位数据放到数据线SDA上,用读端口函数 inprotb() 读取‘打印机状态’寄存器379H当前的值,将结果赋值给一个变量,然后对这个变量进行先右移4位,再左移7位的运算(用以获得13 脚电平状态,即打印机状态寄存器的位 4 的值),判断该变量是否为0,最后将判断结果移入另外的一个用于存放‘已读取数据’的变量中,完成读取一位数据的操作,用写端口函数使SCL

为低电平,在下一个SCL的上升沿,同样用上面的方法将一位数据加入‘已读取数据’变量中。可用while循环控制要读的位数和字节数。注意:以上过程都是在 T1 为截止态时进行的。

主机(并口)接收应答:接收应答用于写 I2C 时,每写一字节数据到从机后,如果操作成功,从机在下一个时钟内使 SDA 为低。主机查询应答可以加强操作的可靠性。接收应答和上面说的接收数据大致相同,只是仅接收一位数据并且不存储,直接判断其值是否为 0,不为 0 时(即没有收到应答)转错误处理程序,为 0则继续后面的操作。在实际编程时将这个步骤合并到写I2C的操作中。

有关延时:I2C器件对SDA和SCL上的高、低电平信号需保持的时间是有规定的。如:开始信号的高、低电平要保持多长时间,数据信号的高、低电平最低要保持多长时间等。不同的器件对这个时间有不同的规定。查找24LO02的数据手册,可以知道,它在不同的电压下对各信号要保持的时间分别在几百纳秒到几微秒之间。这个时间也体现了I2C器件的读写速度。因为计算机的速度不同,要用计算机并口来模拟I2C很难将这个时间精确到微秒。为了能够在不同的计算机上可靠的操作I2C总线,试验程序用了C语言的延时函数delay();这个函数能产生的最小延时为1毫秒。虽然这样做降低了I2C的读写速度,但可以保证操作的可靠性。

四、用并口读写I2C总线的源程序:程序中把I2C的一些操作时序定义成了独立的函数供主函数调用,这样增加了程序的灵活性,也方便对程序的修改和扩充。

源程序如下:

#include "stdio.h"

#include "dos.h"

#include "conio.h"

/***********void i2cstart()***********/

void i2cstart(){

outportb(0x378,0xff);/*scl 1, sda 1*/ delay(1);/**/

outportb(0x378,0xfd);/*scl 1, sda 0*/ delay(1);/**/

outportb(0x378,0xfc);/*scl 0, sda 0*/ delay(1);

}

/***********void i2cstop()***********/ void i2cstop(){

outportb(0x378,0xfc);/*scl 0, sda 0*/ delay(1);/**/

outportb(0x378,0xfd);/*scl 1, sda 0*/ delay(1);/***/

outportb(0x378,0xff);/*scl 1, sda 1*/ delay(1);/**/

outportb(0x378,0xfe);/*scl 0, sad 1*/ }

/***********writebyte()***********/ writebyte(char s){

short int a=7;

char d,e;

outportb(0x378,0xfc);/*scl 0, sda 0*/ delay(1);/***/

while(a>=0){

d=s>>a; d=d<<7;

if (d=='\x80')/*****"1"***/

{

outportb(0x378,0xfe);/*scl 0, sda 1*/ delay(1);/***/

outportb(0x378,0xff);/*scl 1, sda 1*/ }

else

{

outportb(0x378,0xfc);/*scl 0, sda 0*/ delay(1);/***/

outportb(0x378,0xfd);/*scl 1, sda 0*/ }

a=(a-1);

}

/**ask**/

delay(1);/***/

outportb(0x378,0xfe);/*scl 0, sda 1*/ delay(1);/***/

outportb(0x378,0xff);/*scl 1, sda 1*/ delay(1);/***/

outportb(0x378,0xfc);/*scl 0, sda 1*/ delay(1);/***/

e=inportb(0x379); d=e>>4; d=d<<7;

if (d=='\x0') return 0;

else

printf("not acknowledge!\n");

return 1;

}

/***********readbyte()***************/

char readbyte(){

unsigned short a=8;

char d,e,f='\x0';

while(a>0){

delay(1);/***/

outportb(0x378,0xfe);/*scl 0, sda 1*/ delay(1);/***/

outportb(0x378,0xff);/*scl 1, sda 1*/ delay(1);/***/

e=inportb(0x379); d=e>>4; d=d<<7;

if(d=='\x80') d='\x1';

f=f<<1; f=(f+d); a=(a-1);

outportb(0x378,0xfe);/*scl 0, sda 1*/ delay(1);/***/

}

return f;

}

/************mainask()*****************/ mainask(){

delay(1);/**/

outportb(0x378,0xfc);/*scl 0, sda 0*/ delay(1);/**/

outportb(0x378,0xfd);/*scl 1, sda 0*/

delay(1);

outportb(0x378,0xfc);/*scl 0, sda 0*/

}

/*************************************/

main(){

unsigned short a,b,c,g;

char d,e,f;

textcolor(2);

clrscr();

printf("press 'r' or 'w' :");

scanf("%c",&f);

if(f=='w')

{

/************ W 256 BYTES ****/

e='\x0'; c=32; /* 24lc02: 32=256/8 */

while(c>0){

i2cstart();/*****start****/

writebyte('\xa0');/***send contbyte***/

writebyte(e);/***send start address***/

/************W 8 bytes****/

b=8; d='\x0'; /* num */

while(b>0){

if ((writebyte(d))==1) exit(0);/***send a byte***/ b=(b-1);d=(d+1);

}

i2cstop();

delay(40); /****writer delay****/

c=(c-1);e=(e+8);

}

printf("write ok!!\n"); exit(0);

}

if(f=='r')

{

/****** read ***********************************/ printf("please import start address:");

scanf("%x",&b);

a=(256-b); c=(a%8); a=(a/8);

while(a>0){

g=8;

i2cstart();/*****start****/

writebyte('\xa0');/***send contbyte***/

d=(char)b;/****/

writebyte(d);/***send start address***/

i2cstart();/*****start****/

writebyte('\xa1');/***send contbyte***/

while(g>0){

d=readbyte();

if(d=='\xff')

printf(" FF");

else

printf(" %.2X",d);

g=(g-1); if(g>0) mainask();

b=(b+1);

}

i2cstop();

a=(a-1);

}

while(c>0){

i2cstart();/*****start****/

writebyte('\xa0');/***send contbyte***/

d=(char)b;/****/

writebyte(d);/***send start address***/

i2cstart();/*****start****/

writebyte('\xa1');/***send contbyte***/

d=readbyte();

if(d=='\xff')

printf(" FF");

else

printf(" %.2X",d);

c=(c-1); if(c>0) mainask();

}

printf("\nREAD OK!\n");

exit(0);

}

else {printf("\nCommand Error!!!"); exit(0);}

}

以上程序是在 Tubor C 2.0 环境下编译通过的,运行结果如后:程序先在屏幕上提示“press 'r' or 'w' :”'r'为读24LC02,'w'为写。如果输入'r'并按回车,程序将会提示:“please import start address:”这时请按16进制的格式输入要读的起始地址,然后回车,程序将会从该地址开始把后面的所有数据读出并按大写 16进制的格式在屏幕上打印出来。完成后提示“READ

O K!”并结束程序。如果在程序开始时输入的是'w',程序将从24LC02的00H地址开始,按“00 01 02 03 04 05 06 07”的格式,每8字节循环一次,直到写满24LC02所有的存储空间,即256

个字节。写的过程中如果出现错误将提示“not acknowledge!”,如果操作顺利完成,程序将提示“write ok!!”并结束运行。在程序开始时如果输入的不是'r'也不是'w',程序将提示“Command Error!!!”并退出运行。

这个程序虽然只是个简单的演示,但却是并口模拟I2C的最关键的核心部分,只要给它加些改动并配上简单的界面,即可以成为一个很实用的并口 I2C 总线读写程序。

I2C原理简介及那些坑

一般情况下, i2c 设备焊接没什么问题,按照设备手册一步步来,基本上就顺风顺水能够用起来。如果这么一个简单的东西,有时候想要的结果死活不出来,反复的检查问题的原因,查询解决办法,核查设备的数据手册,甚至发送和接收的每一条命令与数据都知道是什么意思,仍然无法解决问题,那该怎么办呢? 本文主要针对 i2c 设备,讲解如何解决 i2c 设备主机与从机直接无法正常数据交互的问题,侧重点是针对硬件设计不太合理、i2c 设备设计不标准导致总线故障的情况,并且通过分析现象,提出解决方案。对于在设备初始化中,没有设置相应的寄存器或者发送命令,而导致的无法获取想要的数据情况,不作详细介绍。 1 i2c 基本用法 i2c 总线是一种简单、双向二线制同步串行总线。所有主机在 SCL 线上产生它们自己的时钟来传输总线上的报文,SDA 线传输每个字节必 须为 8 位,每次传输可以发送的字节数量不受限制,每个字节后必须跟 一个响应位。在空闲状态时,SCL 与 SDA 均为高电平。 通常一些低功耗 i2c 设备,芯片引脚使用上拉输出即可满足与其正 常数据交互,还有一些 i2c 设备,则需要在总线上外加一个上拉电阻, 此时相应的 I/O 配置成开漏输出,其他的按照芯片手册进行标准配置。 2 硬件问题汇总 2.1 无法正常拉高拉低引脚 首先确定 SDA 与SCL 引脚能够被拉高、拉低,检测方式直接软件控 制 I/O 口输出引脚低电平/高电平,测量引脚电压是否能够随着芯片引 脚的设置输出相应的状态。 如果不能被拉低,检测虚焊、上拉电阻断开、i2c 设备是否正常、 芯片引脚是否损坏等问题,确保能够正常被拉高或者拉低。 2.2 电气特性无法满足 如果正常拉高、拉低的情况下,依然无法正常读取数据。通常建 议,根据负载电流更换小阻值的电阻。 如果需要详细知道原因,就具体查询 i2c 设备电气特性。大多数 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设备。 第二种:为I2C设备独立编写一个设备驱动 注意:第二种方法不能用设备提供的I2C-dev.c 5、I2C系统下的文件架构 在linux下driver下面有个I2C目录,在I2C目录下包含以下文件和文件夹 1)I2C-core.c 这个文件实现I2C核心功能以及/proc/bus/I2C*接口 2)I2C-dev.c 实现I2C适配器设备文件的功能,每个I2C适配器被分配一个设备,通过 适配器访问设备的时候,主设备号是89,此设备号是0-255. I2C-dev.c并没有针对特定设备而设计,只提供了read() write()和ioctl()等接口,应用层可以通过这些接口访问挂在适配器上的I2C设备存储空间和寄存器,并控制I2C设备的工作方式。 3)Chips 这个文件下面包含特定的I2C设备驱动。 4)Busses 这个文件包含一些I2C总线驱动。 5)Algos文件夹下实现了I2C总线适配器的algorithm 6、重要结构体 1)在内核中的I2C.h这个头文件中对I2C_driver;I2C_client;I2C_adapter和I2C_algorithm 这个四个结构体进行了定义。理解这4个结构体的作用十分关键。 i2c_adapter结构体 struct i2c_adapter { struct module *owner; //所属模块 unsigned int id; //algorithm的类型,定义于i2c-id.h, unsigned int class; const struct i2c_algorithm *algo; //总线通信方法结构体指针 void *algo_data;//algorithm数据 struct rt_mutex bus_lock; //控制并发访问的自旋锁 int timeout; int retries; //重试次数 struct device dev; //适配器设备 int nr; char name[48]; //适配器名称 struct completion dev_released; //用于同步 struct list_head userspace_clients; //client链表头

I2C总线的结构与工作原理

I2C总线的结构与工作原理 2.1概述 2.1.1 I2C总线在单片机应用系统设计中的意义 现代消费类产品、通讯类产品、仪器仪表、工业测控系统中,逐渐形成了以一个或 多个单片机组成的智能系统,这些系统硬件结构都有相似之处: 1.单片机电路已日趋简单化和标准化。通常是由单片机(MICROCONTROLLER)、程序存储器(EPROM)、数据存储器(SRAM)构成的三片体系,或采用有在片程序存储器的单片机与数据存储器构成的二片体系,以及单片机与通用外围接口器件(PSD)构成的最简单体系。 2. 都有一些外围通用电路,如EEPROM、I/O口、A/D、D/A、日历时钟等外围器件和键盘、LED/LCD显示器、打印机接口等外围设备模块等。 3.面对系统特殊应用的一些电路,如无线电、电视、音像系统中的数字协调、编码、解码、图象处理、频率合成、音调控制、立体声处理等。 在上述的一些电路中,除与单片机直接相关的程序存储器、并行扩展的数据存储器外,单片机对许多外围电路之间主要是实现控制功能,而且许多外设并不要求很高的数据传送速度。为了简化系统,提高系统的可靠性,缩短产品开发周期,增加硬件结构的灵活性,Philips公司推出了一种高效、可靠、方便的串行扩展总线I2C总线。 在单片机应用系统中推广I2C总线后将会大大改变单片机应用系统结构性能、对单片机的应用开发带来以下好处: 可最大限度地简化结构。二线制的I2C串行总线使得各电路单元之间只需最简单的连接,而且总线接口都集成在器件中,不需另加总线接口电路。电路的简化省去了电路板上大量走线,减少电路板面积,提高了可靠性,降低了成本。 可实现电路系统的模块化、标准化设计。在I2C总线上各单元电路除了个别中断引线外,相互之间没有其他连线,用户常用的单元电路基本上与系统电路无关,故极易形成用户自己的标准化、模块化设计。 标准I2C总线模块的组合开发方式大缩短了新品的开发周期。 I2C总线各节点具有独立的电器特性,各节点单元电路能在相互不受影响的情况下,甚至在系统供电情况下,接入或撤除。I2C总线系统构成具有最大的灵活性。系统该型设计、或对已加工好的电路板需扩展功能时,对原有设计及电路板系统影响最小。 I2C总线系统可方便地对某一接点电路进行故障诊断与跟踪,有极好的可维护性 目前Philips及I2C总线器件,除带有I2C总线单片机、常用的通用外围器件外,在家电产品、电讯、电视、音像产品中已发展成套I2C总线器件,在这些部门中I2C总线系统已得到了广泛的应用。 2.1.2 I2C总线的一般应用特性 I2C总线系统中,带有I2C总线的单片机,其I2C总线输入输出口的电器结构、相关的特殊功能寄存器(SFR)设置以及所提供的标准程序模块,为用户掌握I2C总线的系统设计和应用软件的编制带来极大的方便。 I2C总线的串行数据传送与一般UART的串行数据传送无论从借口电器特性、传送状态管理以及程序编制特点都有很大的不同,了解这些特点十分重要。 1.二线传输。I2C总线上所有的节点,如主器件(单片机,微处理器)、外围器件、借口模块等都连到同名端的SDA、SCL上。 2.系统中有多个主器件时,这些器件都可作总线的主控制器(无中心主机),I2C总线工作时任何一个主件都可成为主控制器,多机竞争时的时钟同步与总线仲裁都由硬件与标准软件模块自动完成,无须用户介入。 3.I2C总线传输时,采用状态码的管理方法。对应于总线数据传输时的任何一种状态,在状态寄存器中会出现相应的状态码,并且会自动进入响应的状态处理程序中进行自动处理,无须用户介入,用户只须将Philips公司提供的标准状态处理器一定的空间即可。 4.系统中所有外围器件及模块采用器件地址及引脚地址的编码方法。系统中主控制器对任何节点的寻址采用纯软件寻址方法,避免了片选线的先连方法。系统中若有地址编码冲突可通过改变地址引脚的电平设置来解决。 5.所有带I2C接口的外围器件都具有应答功能。片有多少单元地址时,读数据、写时都有地址自动加1功能。这样,在I2C 总线对某一器件读写多个字节时很容易实现自动操作,即准备好读、写入口条件后,只须启动I2C总线就可自动完成n个字节的读、写操作。 6.I2C总线电器接口为开漏晶体管组成,开路输出没有找到电源的钳位二级管,而连到I2C总线的每个器件上,其自身

Linux下I2C驱动架构全面分析概要

Linux下I2C驱动架构全面分析 I2C概述 I2C是philips提岀的外设总线. I2C只有两条线,一条串行数据线:SDA, —条是时钟线SCL,使用SCL , SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线。 因此,I2C总线被非常广泛地应用在EEPROM,实时钟,小型LCD等设备与CPU的接口中。 linux下的驱动思路 在linux系统下编写I2C驱动,目前主要有两种方法,一种是把I2C设备当作一个普通的字符设备来处理,另一种是利用linux下I2C驱动体系结构来完成。下面比较下这两种方法: 第一种方法: 优点:思路比较直接,不需要花很多时间去了解linux中复杂的I2C子系统的操作方法。 缺点: 要求工程师不仅要对I2C设备的操作熟悉,而且要熟悉I2C的适配器(I2C控制器)操作。要求工程师对I2C的设备器及I2C的设备操作方法都比较熟悉,最重要的是写岀的程序可以移植性差。 对内核的资源无法直接使用,因为内核提供的所有I2C设备器以及设备驱动都是基于I2C 子系统的格式。 第一种方法的优点就是第二种方法的缺点, 第一种方法的缺点就是第二种方法的优点。 I2C架构概述 Linux的I2C体系结构分为3个组成部分: I2C核心:I2C核心提供了I2C总线驱动和设备驱动的注册,注销方法,I2C通信方法 (” algorithm 上层的,与具体适配器无关的代码以及探测设备,检测设备地址的上层代码等。 I2C总线驱动:I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至可以直接集成在CPU内部。 I2C设备驱动:I2C设备驱动(也称为客户驱动)是对I2C硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。

I2C总线中文讲解,详尽通俗

一. I2C总线简介 I2C管理总线:(Intel-Integrated Circuit bus)I2C总线是一种由飞利浦Philip公司开发的串行总线,产生于80年代,最初为音频和视频设备开发,现主要在服务器管理中使用。是两条串行的总线,它由一根数据线(SDA)和一根时钟线(SDL)组成。 ◆I2C总线的数据传输过程基本过程为: ●主机发出开始信号。 ●主机接着送出1字节的从机地址信息,其中最低位为读写控制码(1为读、0为写), 高7位为从机器件地址代码。 ●从机发出认可信号。 ●主机开始发送信息,每发完一字节后,从机发出认可信号给主机。 ●主机发出停止信号。 I2C数据传输图 ◆I2C总线上各信号的具体说明: ●开始信号:在时钟线(SCL)为高电平其间,数据线(SDA)由高变低,将产生一 个开始信号。 ●停止信号:在时钟线(SCL)为高电平其间,数据线(SDA)由低变高,将产生一 个停止信号。 ●应答信号:既认可信号,主机写从机时每写完一字节,如果正确从机将在下一个时钟 周期将数据线(SDA)拉低,以告诉主机操作有效。在主机读从机时正确读完一字节后,主机在下一个时钟周期同样也要将数据线(S DA)拉低,发出认可信号,告诉从机所发数据已经收妥。(注:读从机时主机在最后1字节数据接收完以后不发应答,直接发停止信号)。 注意:在I2C通信过程中,所有的数据改变都必须在时钟线SCL为低电平时改变,在时钟线SCL为高电平时必须保持数据SDA信号的稳定,任何在时钟线为高电平时数据线上的电平改变都被认为是起始或停止信号。 ◆I2C总线数据格式:

I2C数据格式图 I2C支持两种数据格式: _ 7-bit/10-bit 寻址数据格式 _ 7-bit/10-bit 寻址和重复开始信号的数据格式 ?S ―I2C 开始标识 ?Slava address ―从设备地址。 有两种从地址类型: 1)固定的从地址,I2C总线只能接一个同类型的固定的从地址设备。 2)半固定的从地址,前半部分地址是固定的,后半部分地址是可编程的,I2C总线只能接多个同类型的半固定的从地址设备。 如7bit半固定从地址通常7-bit 中四个较重要的位(MSB) 为固定的,并依器件本身性质的分类区分,如1010 即代表串行EEPROM,而其他三个较不重要的位(LSB),即A2、A1 与A0 则可以通过硬件电子引脚设定,并取得高达8 个不同的I2C 地址组合,因此在同一个I2C 总线上可以有8 个相同形式的器件运作,这些引脚固定在VCC 高电压代表逻辑1,固定在接地低电压则代表逻辑0,7-bit 的定址方式可以带来总线上128 个器件的组合,但由于部份地址设定保留给特殊指令应用,因此实际上最高器件数大约为120 个。 ?R/W ―读写操作表示位,0 表示写,1表示读。 ?ACK ―读写完一个byte的地址数据的应答信号 ?Data ―数据,紧跟设备地址传输的第一个byte数据(Data)可以是子地址(sub-address) 表示设备的寄存器。 ?S ―I2C结束标识 ◆关于从地址的分配 I2C器件的从地址是由I2C总线协会实行统一分配的,飞利浦作为标准I2C总线标准的维护者,负责所有I2C从地址的注册程序以确保能够适当协助授权厂商或其他公司进行从地址的分配。为了避免I2C器件的从地址的冲突必须依赖现有从地址的完整性和可靠的申请注册资料才能达成,所以I2C器件厂家必须向philip公司提交I2C从地址申请并提交一定的费用。 从地址的申请有两种: 第一种是为某一特定的I2C器件设备申请从地址;

linux下iic(i2c)读写AT24C02

https://www.doczj.com/doc/6017025517.html,/jammy_lee/ https://www.doczj.com/doc/6017025517.html, linux下iic(i2c)读写AT24C02 linux驱动2010-02-09 16:02:03 阅读955 评论3 字号:大中小订阅 linux内核上已有iic的驱动,因此只需要对该iic设备文件进行读写则能够控制外围的iic器件。这里以AT24C02为对象,编写一个简单的读写应用程序。iic设备文件在我的开发板上/dev/i2c/0 ,打开文件为可读写。AT24C02的器件地址为0x50 ,既是iic总线上从器件的地址,每次只读写一字节数据。 /************************************************************/ //文件名:app_at24c02.c //功能:测试linux下iic读写at24c02程序 //使用说明: (1) // (2) // (3) // (4) //作者:jammy-lee //日期:2010-02-08 /************************************************************/ //包含头文件 #include #include #include #include #include #include #include

#include #include #include //宏定义 #define Address 0x50 //at24c02地址 #define I2C_RETRIES 0x0701 #define I2C_TIMEOUT 0x0702 #define I2C_SLAVE 0x0703 //IIC从器件的地址设置 #define I2C_BUS_MODE 0x0780 typedef unsigned char uint8; uint8 rbuf[8] = {0x00}; //读出缓存 uint8 wbuf[8] = {0x01,0x05,0x06,0x04,0x01,0x01,0x03,0x0d}; //写入缓存int fd = -1; //函数声明 static uint8 AT24C02_Init(void); static uint8 i2c_write(int fd, uint8 reg, uint8 val); static uint8 i2c_read(int fd, uint8 reg, uint8 *val); static uint8 printarray(uint8 Array[], uint8 Num); //at24c02初始化 static uint8 AT24C02_Init(void) { fd = open("/dev/i2c/0", O_RDWR); //允许读写 if(fd < 0) { perror("Can't open /dev/nrf24l01 \n"); //打开iic设备文件失败 exit(1);

实例解析linux内核I2C体系结构(2)

实例解析linux内核I2C体系结构(2) 华清远见刘洪涛四、在内核里写i2c设备驱动的两种方式 前文介绍了利用/dev/i2c-0在应用层完成对i2c设备的操作,但很多时候我们还是习惯为i2c设备在内核层编写驱动程序。目前内核支持两种编写i2c驱动程序的方式。下面分别介绍这两种方式的实现。这里分别称这两种方式为“Adapter方式(LEGACY)”和“Probe方式(new style)”。 (1)Adapter方式(LEGACY) (下面的实例代码是在2.6.27内核的pca953x.c基础上修改的,原始代码采用的是本文将要讨论的第2种方式,即Probe方式) ●构建i2c_driver static struct i2c_driver pca953x_driver = { .driver = { .name= "pca953x", //名称 }, .id= ID_PCA9555,//id号 .attach_adapter= pca953x_attach_adapter, //调用适配器连接设备 .detach_client= pca953x_detach_client,//让设备脱离适配器 }; ●注册i2c_driver static int __init pca953x_init(void) { return i2c_add_driver(&pca953x_driver); } module_init(pca953x_init); ●attach_adapter动作 执行i2c_add_driver(&pca953x_driver)后会,如果内核中已经注册了i2c适配器,则顺序调用这些适配器来连接我们的i2c设备。此过程是通过调用i2c_driver中的attach_adapter方法完成的。具体实现形式如下: static int pca953x_attach_adapter(struct i2c_adapter *adapter) { return i2c_probe(adapter, &addr_data, pca953x_detect); /* adapter:适配器 addr_data:地址信息 pca953x_detect:探测到设备后调用的函数 */ } 地址信息addr_data是由下面代码指定的。 /* Addresses to scan */ static unsigned short normal_i2c[] = {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,I2C_CLIENT_END}; I2C_CLIENT_INSMOD;

i2c总线原理

I2C总线原理 ?什么是I2C总线? I2C即Inter IC,由Philips公司开发,是当今电子设计中应用非常广泛的串行总线之一,主要用于电压、温度监控,EEPROM数据的读写,光模块的管理等。 I2C总线只有两根线,SCL和SDA,SCL即Serial Clock,串行参考时钟,SDA即Serial Data,串行数据。 ?I2C总线的速率能达到多少? 标准模式下:100Kbps 快速模式下:400Kbps 高速模式下:3.4Mbps I2C总线结构如下图所示: 如上图所示,I2C是OC或OD输出结构,使用时必须在芯片外部进行上拉,上拉电阻R的取值根据I2C总线上所挂器件数量及I2C总线的速率有关,一般是标准模式下R选择10kohm,快速模式下R选取1kohm,I2C总线上挂的I2C器件越多,就要求I2C的驱动能力越强,R的取值就要越小,实际设计中,一般是先选取4.7kohm上拉

电阻,然后在调试的时候根据实测的I2C波形再调整R的值。 ?I2C总线上最多能挂多少个I2C器件? I2C总线上允许挂接I2C器件的数量由两个条件决定: 1).I2C从设备的地址位数。I2C标准中有7位地址和10位地址两种。如果是7位地址,允许挂接的I2C器件数量为:27=128,如果是10位地址,允许挂接的I2C 器件数量为:210=1024,一般I2C总线上挂接的I2C器件不会太多,所以现在几乎所有的I2C器件都使用7位地址。 2).挂在I2C总线上所有I2C器件的管脚寄生电容之和。I2C总线规范要求,I2C 总线容性负载最大不能超过470pF。 ?I2C总线是如何工作的? 1).I2C总线传输的特点。 I2C总线按字节传输,即每次传输8bits二进制数据,传输完毕后等待接收端的应答信号ACK,收到应答信号后再传输下一字节。等不到ACK信号后,传输终止。空闲情况下,SCL和SDA都处于高电平状态。 2).如何判断一次传输的开始? 如上图所示,I2C总线传输开始的标志是:SCL信号处于高电平期间,SDA信号出现一个由高电平向低电平的跳变。 3).如何判断一次传输的结束? 如上图所示,I2C总线传输结束的标志是:SCL信号处于高电平期间,SDA信号出现一个由低电平向高电平的跳变。跟开始标识正好相反。 4).什么样的I2C数据才是有效的。

Linux_I2C总线分析(主要是probe的方式)1

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_xfer to NULL. If an adapter algorithm can do SMBus access, set smbus_xfer. If set to NULL, the SMBus protocol is simulated

using common I2C messages */ /* master_xfer should return the number of messages successfully processed, 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总线原理及应用实例

I2C总线 原理及应 用实例 I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线产生于在80年代,最初为 音频和视频设备开发,如今主要在服务器管理中使用,其中包括单个组件状态的 通信。例如管理员可对各个组件进行查询,以管理系统的配置或掌握组件的功能 状态,如电源和系统风扇。可随时监控内存、硬盘、网络、系统温度等多个参数, 增加了系统的安全性,方便了管理。 1 I2C总线特点 I2C总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互 联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持 40个组件。I2C总线的另一个优点是,它支持多主控(multimastering),其中 任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传 输和时钟频率。当然,在任何时间点上只能有一个主控。 2 I2C总线工作原理 2.1 总线的构成及信号类型 I2C总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,最高传送速率100kbps。各种 被控制电路均并联在这条总线上,但就像电话机一样只有拨通各自的号码才能工 作,所以每个电路和模块都有唯一的地址,在信息的传输过程中,I2C总线上并 接的每一模块电路既是主控器(或被控器),又是发送器(或接收器),这取决 于它所要完成的功能。CPU发出的控制信号分为地址码和控制量两部分,地址码 用来选址,即接通需要控制的电路,确定控制的种类;控制量决定该调整的类别 (如对比度、亮度等)及需要调整的量。这样,各控制电路虽然挂在同一条总线 上,却彼此独立,互不相关。 I2C总线在传送数据过程中共有三种类型信号,它们分别是:开始信号、结束信号和应答信号。 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。 结束信号:SCL为低电平时,SDA由低电平向高电平跳变,结束传送数据。 应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单 元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递 信号的判断。若未收到应答信号,由判断为受控单元出现故障。 目前有很多半导体集成电路上都集成了I2C接口。带有I2C接口的单片机有:CYGNAL的 C8051F0XX系列,PHILIPSP87LPC7XX系列,MICROCHIP的PIC16C6XX 系列等。很多外围器件如存储器、监控芯片等也提供I2C接口。 3 总线基本操作 I2C规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。主器件和从器件都可以工作于接收和发送状态。总

实例解析linux内核I2C体系结构

实例解析linux内核I2C体系结构 作者:刘洪涛,华清远见嵌入式学院讲师。 一、概述 谈到在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串行总线通信原理

采用串行总线技术可以使系统的硬件设计大大简化、系统的体积减小、可靠性提高。同时,系统的更改和扩充极为容易。 常用的串行扩展总线有:I2C (Inter IC BUS)总线、单总线(1-WIRE BUS)、SPI(Serial Peripheral Interface)总线等。本章仅讨论I2C串行总线。

一、IIC概述 IIC(Inter-Integrated Circuit)总线,许多文献写作I2C,主要用于同一电路板内各集成电路模块(IC)之间的连接。IIC采用双向2线制串行数据传输方式,简化IC之间的通信连接。IIC协议是PHILIPS公司于二十世纪八十年代初提出,其后,PHILIPS和其他厂商提供了种类丰富的IIC兼容芯片。目前,IIC总线标准已经成为世界性的工业标准。各大半导体公司推出了大量的带有IIC接口的芯片,如RAM、EEPROM、Flash ROM、A/D、D/A转换、 LED/LCD驱动、I/O接口、实时时钟等。

二、IIC总线特点 在硬件结构上,它采用数据(SDA)和时钟(SCL)两根线来完成数据的传输及外围器件的扩展,任何一个具有IIC总线接口的外围器件,不论其功能差别有多大,都具有相同的电气接口,因 此都可以挂接在总线上,使其连接方式变得十分 简单。 对各器件的寻址是软寻址方式,因此节点上没有必须的片选线,器件地址给定完全取决于器件 类型与单元结构,这也简化了IIC系统的硬件连接。

另外IIC总线能在总线竞争过程中进行总线控制权的仲裁和时钟同步,并且不会造成数据丢失,因此由IIC总线连接的多机系统可以是一个多主机系统,支持多主控。 串行的8位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s。

linux i2c驱动

linux i2c驱动 1. i2c-dev interface I2C 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 "。注意,存在两个"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];

I2C总线协议及工作原理

I2C总线协议及工作原理 一、概述 1、I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。 SCL:上升沿将数据输入到每个EEPROM器件中;下降沿驱动EEPROM器件输出数据。(边沿触发) SDA:双向数据线,为OD门,与其它任意数量的OD与OC门成"线与"关系。 I2C总线通过上拉电阻接正电源。当总线空闲时,两根线均为高电平(SDL=1;SCL=1)。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。 2、主设备与从设备 系统中的所有外围器件都具有一个7位的"从器件专用地址码",其中高4位为器件类型,由生产厂家制定,低3位为器件引脚定义地址,由使用者定义。主控器件通过地址码建立多机通信的机制,因此I2C总线省去了外围器件的片选线,这样无论总线上挂接多少个器件,其系统仍然为简约的二线结构。终端挂载在总线上,有主端和从端之分,主端必须是带有CPU的逻辑模块,在同一总线上同一时刻使能有一个主端,可以有多个从端,从端的数量受地址空间和总线的最大电容400pF的限制。 主端主要用来驱动SCL line; 从设备对主设备产生响应; 二者都可以传输数据,但是从设备不能发起传输,且传输是受到主设备控制的。 二、协议 1.空闲状态 I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。 2.起始位与停止位的定义: 起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。 停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。 起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。

Linux驱动之i2c用户态调用

一、概述 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_PEC0 x0708/* !=0to use PEC with SMBus*/ 9.#define I2C_SMBUS0x0720 /*SMBus transfer*/

Android I2C精析

Android I2C精析 基于linux内核开发的arm系统,会用到很多components。要让这些components正常的工作,我们必须了解它们的接口,懂得如何去注册总线,初始化芯片,进而让芯片正常的工作。下面我会介绍在arm开发过程中使用最频繁的一些接口和总线的原理,以及如何在开发的过程中去使用它们。 1 I2C总线与接口 I2C总线具有结构简单,使用方便的特点。下面我会描述linux下I2C驱动的结构,幷给出I2C设备驱动和应用的实现。 1.1 I2C总线概述 I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。 I2C总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据,每个器件都有一个惟一的地址识别。I2C 规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。主器件和从器件都可以工作于接收和发送状态。总线必须由主器件(通常为微控制器)控制,主器件产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件。SDA 线上的数据状态仅在SCL为低电平的期间才能改变,SCL为高电平的期间,SDA 状态的改变被用来表示起始和停止条件。 从理论上说一根I2C总线上可以挂载128个I2C设备,但是通常情况下,由于有些设备在传输数据时占用的I2C总线带宽频繁,所以我们在一根I2C总线上挂载的设备是越少越好。下面给出I2C总线的连线图:

相关主题
相关文档 最新文档