I2c总线协议.docx

上传人:b****6 文档编号:9107876 上传时间:2023-02-03 格式:DOCX 页数:14 大小:262.72KB
下载 相关 举报
I2c总线协议.docx_第1页
第1页 / 共14页
I2c总线协议.docx_第2页
第2页 / 共14页
I2c总线协议.docx_第3页
第3页 / 共14页
I2c总线协议.docx_第4页
第4页 / 共14页
I2c总线协议.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

I2c总线协议.docx

《I2c总线协议.docx》由会员分享,可在线阅读,更多相关《I2c总线协议.docx(14页珍藏版)》请在冰豆网上搜索。

I2c总线协议.docx

I2c总线协议

协议

2条双向串行线,一条数据线SDA,一条时钟线SCL。

SDA传输数据是大端传输,每次传输8bit,即一字节。

支持多主控(multimastering),任何时间点只能有一个主控。

总线上每个设备都有自己的一个addr,共7个bit,广播地址全0.

系统中可能有多个同种芯片,为此addr分为固定部分和可编程部份,细节视芯片而定,看datasheet。

I2C位传输

数据传输:

SCL为高电平时,SDA线若保持稳定,那么SDA上是在传输数据bit;

若SDA发生跳变,则用来表示一个会话的开始或结束(后面讲)

数据改变:

SCL为低电平时,SDA线才能改变传输的bit

I2C开始和结束信号

开始信号:

SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。

结束信号:

SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。

I2C应答信号

Master每发送完8bit数据后等待Slave的ACK。

即在第9个clock,若从IC发ACK,SDA会被拉低。

若没有ACK,SDA会被置高,这会引起Master发生RESTART或STOP流程,如下所示:

I2C写流程

写寄存器的标准流程为:

1.Master发起START

2.Master发送I2Caddr(7bit)和w操作0(1bit),等待ACK

3.Slave发送ACK

4.Master发送regaddr(8bit),等待ACK

5.Slave发送ACK

6.Master发送data(8bit),即要写入寄存器中的数据,等待ACK

7.Slave发送ACK

8.第6步和第7步可以重复多次,即顺序写多个寄存器

9.Master发起STOP

写一个寄存器

写多个寄存器

I2C读流程

读寄存器的标准流程为:

1.Master发送I2Caddr(7bit)和w操作1(1bit),等待ACK

2.Slave发送ACK

3.Master发送regaddr(8bit),等待ACK

4.Slave发送ACK

5.Master发起START

6.Master发送I2Caddr(7bit)和r操作1(1bit),等待ACK

7.Slave发送ACK

8.Slave发送data(8bit),即寄存器里的值

9.Master发送ACK

10.第8步和第9步可以重复多次,即顺序读多个寄存器

读一个寄存器

读多个寄存器

2.PowerPC的I2C实现

Mpc8560的CCSR中控制I2C的寄存器共有6个。

I2CADR地址寄存器

CPU也可以是I2C的Slave,CPU的I2C地址有I2CADR指定

I2CFDR频率设置寄存器

TheserialbitclockfrequencyofSCLisequaltotheCCBclockdividedbythedivider.

用来设置I2C总线频率

I2CCR控制寄存器

MEN:

ModuleEnable.置1时,I2C模块使能

MIEN:

ModuleInterruptEnable.置1时,I2C中断使能。

MSTA:

Master/slavemode.1Mastermode,0Slavemode.

当1->0时,CPU发起STOP信号

当0->1时,CPU发起START信号

MTX:

Transmit/receivemodeReceivemode,1Transmitmode

TXAK:

Transferacknowledge.置1时,CPU在9thclock发送ACK拉低SDA

RSTA:

RepeatSTART.置1时,CPU发送REPEATSTART

BCST:

置1,CPU接收广播信息(信息的slaveaddr为7个0)

I2CSR状态寄存器

MCF:

0Bytetransferisinprocess

1Bytetransferiscompleted

MAAS:

当CPU作为Slave时,若I2CDR与会话中Slaveaddr匹配,此bit被置1

MBB:

0I2Cbusidle

1I2Cbusbusy

MAL:

若置1,表示仲裁失败

BCSTM:

若置1,表示接收到广播信息

SRW:

WhenMAASisset,SRWindicatesthevalueoftheR/Wcommandbitofthecallingaddress,whichissentfromthemaster.

0Slavereceive,masterwritingtoslave

1Slavetransmit,masterreadingfromslave

MIF:

Moduleinterrupt.TheMIFbitissetwhenaninterruptispending,causingaprocessorinterruptrequest(providedI2CCR[MIEN]isset)

RXAK:

若置1,表示收到了ACK

I2CDR数据寄存器

这个寄存器储存CPU将要传输的数据。

3.PPC-Linux中I2C的实现

内核代码中,通过I2C总线存取寄存器的函数都在文件drivers/i2c/busses/中

最重要的函数是mpc_xfer.

 

1.staticintmpc_xfer(structi2c_adapter*adap,structi2c_msg*msgs,intnum)

2.{

3.structi2c_msg*pmsg;

4.inti;

5.intret=0;

6.unsignedlongorig_jiffies=jiffies;

7.structmpc_i2c*i2c=i2c_get_adapdata(adap);

8.

9.mpc_i2c_start(i2c);//设置I2CCR[MEN],使能I2Cmodule

10.

11./*Allowbusupto1stobecomenotbusy*/

12.//一直读I2CSR[MBB],等待I2C总线空闲下来

13.while(readb(i2c->base+MPC_I2C_SR)&CSR_MBB){

14.if(signal_pending(current)){

15.pr_debug("I2C:

Interrupted\n");

16.writeccr(i2c,0);

17.return-EINTR;

18.}

19.if(time_after(jiffies,orig_jiffies+HZ)){

20.pr_debug("I2C:

timeout\n");

21.if(readb(i2c->base+MPC_I2C_SR)==

22.(CSR_MCF|CSR_MBB|CSR_RXAK))

23.mpc_i2c_fixup(i2c);

24.return-EIO;

25.}

26.schedule();

27.}

28.

29.for(i=0;ret>=0&&i

30.pmsg=&msgs[i];

31.pr_debug("Doing%s%dbytesto0x%02x-%dof%dmessages\n",

32.pmsg->flags&I2C_M_RD"read":

"write",

33.pmsg->len,pmsg->addr,i+1,num);

34.//根据消息里的flag进行读操作或写操作

35.if(pmsg->flags&I2C_M_RD)

36.ret=mpc_read(i2c,pmsg->addr,pmsg->buf,pmsg->len,i);

37.else

38.ret=mpc_write(i2c,pmsg->addr,pmsg->buf,pmsg->len,i);

39.}

40.mpc_i2c_stop(i2c);//保证为I2CCSR[MSTA]为0,保证能触发STOP

41.return(ret<0)ret:

num;

42.}

 

1.staticintmpc_write(structmpc_i2c*i2c,inttarget,

2.constu8*data,intlength,intrestart)

3.{

4.inti;

5.unsignedtimeout=i2c->;

6.u32flags=restartCCR_RSTA:

0;

7.

8./*StartwithMEN*///以防万一,保证I2C模块使能起来

9.if(!

restart)

10.writeccr(i2c,CCR_MEN);

11./*Startasmaster*///写了I2CCR[CCR_MSTA],触发CPU发起START信号

12.writeccr(i2c,CCR_MIEN|CCR_MEN|CCR_MSTA|CCR_MTX|flags);

13./*Writetargetbyte*///CPU发送一个字节,slaveI2Caddr和0(写操作bit)

14.writeb((target<<1),i2c->base+MPC_I2C_DR);

15.

16.if(i2c_wait(i2c,timeout,1)<0)//等待slave发ACK

17.return-1;

18.

19.for(i=0;i

20./*Writedatabyte*/

21.writeb(data[i],i2c->base+MPC_I2C_DR);//CPU接着发数据,包括regaddr和data

22.

23.if(i2c_wait(i2c,timeout,1)<0)//等待slave发ACK

24.return-1;

25.}

26.

27.return0;

28.}

 

1.staticinti2c_wait(structmpc_i2c*i2c,unsignedtimeout,intwriting)

2.{

3.unsignedlongorig_jiffies=jiffies;

4.u32x;

5.intresult=0;

6.

7.if(i2c->irq==0)

8.{//循环读I2CSR,直到I2CSR[MIF]置1

9.while(!

(readb(i2c->base+MPC_I2C_SR)&CSR_MIF)){

10.schedule();

11.if(time_after(jiffies,orig_jiffies+timeout)){

12.pr_debug("I2C:

timeout\n");

13.writeccr(i2c,0);

14.result=-EIO;

15.break;

16.}

17.}

18.x=readb(i2c->base+MPC_I2C_SR);

19.writeb(0,i2c->base+MPC_I2C_SR);

20.}else{

21./*Interruptmode*/

22.result=wait_event_interruptible_timeout(i2c->queue,

23.(i2c->interrupt&CSR_MIF),timeout*HZ);

24.

25.if(unlikely(result<0)){

26.pr_debug("I2C:

waitinterrupted\n");

27.writeccr(i2c,0);

28.}elseif(unlikely(!

(i2c->interrupt&CSR_MIF))){

29.pr_debug("I2C:

waittimeout\n");

30.writeccr(i2c,0);

31.result=-ETIMEDOUT;

32.}

33.

34.x=i2c->interrupt;

35.i2c->interrupt=0;

36.}

37.

38.if(result<0)

39.returnresult;

40.

41.if(!

(x&CSR_MCF)){

42.pr_debug("I2C:

unfinished\n");

43.return-EIO;

44.}

45.

46.if(x&CSR_MAL){//仲裁失败

47.pr_debug("I2C:

MAL\n");

48.return-EIO;

49.}

50.

51.if(writing&&(x&CSR_RXAK)){//写后没收到ACK

52.pr_debug("I2C:

NoRXAK\n");

53./*generatestop*/

54.writeccr(i2c,CCR_MEN);

55.return-EIO;

56.}

57.return0;

58.}

 

1.staticintmpc_read(structmpc_i2c*i2c,inttarget,

2.u8*data,intlength,intrestart)

3.{

4.unsignedtimeout=i2c->;

5.inti;

6.u32flags=restartCCR_RSTA:

0;

7.

8./*StartwithMEN*///以防万一,保证I2C模块使能

9.if(!

restart)

10.writeccr(i2c,CCR_MEN);

11./*Switchtoread-restart*/

12.//注意这里,再次把CCR_MSTA置1,再触发START

13.writeccr(i2c,CCR_MIEN|CCR_MEN|CCR_MSTA|CCR_MTX|flags);

14.

15.

16./*Writetargetaddressbyte-thistimewiththereadflagset*/

17.//CPU发送slaveI2Caddr和读操作1

18.writeb((target<<1)|1,i2c->base+MPC_I2C_DR);

//等待Slave发ACK

1.if(i2c_wait(i2c,timeout,1)<0)

2.return-1;

3.

4.if(length){

5.if(length==1)

6.writeccr(i2c,CCR_MIEN|CCR_MEN|CCR_MSTA|CCR_TXAK);

7.else//为什么不置TXAK

8.writeccr(i2c,CCR_MIEN|CCR_MEN|CCR_MSTA);

9./*Dummyread*/

10.readb(i2c->base+MPC_I2C_DR);

11.}

12.

13.for(i=0;i

14.if(i2c_wait(i2c,timeout,0)<0)

15.return-1;

16.

17./*Generatetxackonnexttolastbyte*/

18.//注意这里TXAK置1,表示CPU每收到1byte数据后,会发送ACK

19.if(i==length-2)

20.writeccr(i2c,CCR_MIEN|CCR_MEN|CCR_MSTA|CCR_TXAK);

21.

22./*Generatestoponlastbyte*/

23.//注意这里CCR_MSTA[1->0]CPU会触发STOP

24.if(i==length-1)

25.writeccr(i2c,CCR_MIEN|CCR_MEN|CCR_TXAK);

26.

27.data[i]=readb(i2c->base+MPC_I2C_DR);

28.}

29.

30.returnlength;

31.}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1