I2C总线原理与应用.docx

上传人:b****6 文档编号:4776224 上传时间:2022-12-08 格式:DOCX 页数:10 大小:33.07KB
下载 相关 举报
I2C总线原理与应用.docx_第1页
第1页 / 共10页
I2C总线原理与应用.docx_第2页
第2页 / 共10页
I2C总线原理与应用.docx_第3页
第3页 / 共10页
I2C总线原理与应用.docx_第4页
第4页 / 共10页
I2C总线原理与应用.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

I2C总线原理与应用.docx

《I2C总线原理与应用.docx》由会员分享,可在线阅读,更多相关《I2C总线原理与应用.docx(10页珍藏版)》请在冰豆网上搜索。

I2C总线原理与应用.docx

I2C总线原理与应用

I2C总线原理与应用

一.简介

I2C(Inter-IntegratedCircuit)总线是一种由Philips公司开发的两线式串行总线,用于连接微控制器及其外围设备。

I2C总线产生于在80年代,最初为音频和视频设备开发。

由于其简单性,如今方泛用于微控制器与各种功能模块的连接,可以说是学单片机的人,入门之后,必定要涉及到的。

I2C总线实际上已经成为一个国际标准在超过100种不同的IC上实现,而且得到超过50家公司的许可,正因为其简单和应用广泛,因此其功能也越来不满足人们的要求,其速度也从原来的100Kbit/S,增加了快速模式,其速度达400Kbit/S,再后来也增加了高速模式,其速度更达3.4Mbit/S。

二.功能和特点

I2C总线是一种用于IC器件之间连接的双向二线制总线,所谓总线它上面可以挂多少器件,并且通个两根线连接,占用空间非常的小,总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。

它的另一优点是多主控,只要能够进行接收和发送的设备都可以成为主控制器,当然多个主控不能同一时间工作。

I2C总线有两根信号线,一根为SDA(数据线),一根为SCL(时钟线)。

任何时候时钟信号都是由主控器件产生。

I2C总线在传送数据的过程中,主要有三种控制信号:

起始信号,结不信号,应答信号

起始信号:

当SCL为高电平时,SDA由高电平转为低电平时,开始传送数据

结束信号:

当SCL为高电平时,SDA由低电平转为高电平时,结束数据传送

应答信号:

接收数据的器件在接收到8bit数据后,向发送数据的器件发出低电平信号,表示已收到数据。

这个信号可以是主控器件发出,也可以是从动器件发出。

总之由接收数据的器件发出。

这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。

三.基本操作

下面我们以ATMEL公司的AT24C02来介绍I2C的基本操作

AT24C02是美国ATMEL公司的低功耗CMOS串行EEPROM,它是内含256×8bit存储空间,具有工作电压宽(2.5~5.5V)、擦写次数多(大于10000次)、写入速度快(小于10ms)等特点。

他在系统中始终为从动器件。

对AT24C02的操作主要有:

字节读,字节写,页面读,页面写

首先发送起始信号,如下图,起始信号后必须是控制字,

控制字格式如下,其中高四位为器件类型识别符(不同的芯片类型有不同的定义,EEPROM一般应为1010),接着三位为片选,也就是三个地址位,最后一位为读写控制位,当为1(Input)时为读操作,为0(Output)时为写操作。

控制字后就是相应的操作,读或写,一定不要结束,因为这个操作还没有完成,如果结束就等于放弃操作。

先来看写操作,写操作分为字节写和页面写两种操作,对于页面写根据芯片的一次装载的字节不同有所不同,AT24C02为8字节,每写一个字节后,地址自动加1。

关于页面写的地址、应答和数据传送的时序参见图3,字节写可以看成是只有一个字节的页面写,也就是写一个数据后停止。

注意:

写一次需要一定时间,一般为10ms,要等侍这个操作完成。

时序如下图:

说明:

对于AT24C02,在控制字后还必须写入地址,这个地址是以后读写的起始地址。

读操作有三种基本操作:

当前地址读、随机读和顺序读。

三种操作方法类似,只是读的数据个数不同,可连续读8个字节,图4给出的是顺序读的时序图,图中共读了四个数据,需要注意的是当前的地址,如果不是想要的,可以用写操作,重新写入地址。

非常重要的是,每读一个数据后,必须置低SDA,作为应答,否则,只能读一个数据,后面的数据,因为收到不应答信号,AT24C02就会认为出错,停止操作。

特别提醒的是,当SCL为低电平时,数据是可变的,因些只有SCL为高电平时,才能读数。

(相关时序,请看例程序的,读功能函数)

四.例程序(51汇编,测试单片机为AT89C51,12M晶振)

电路连接如图5,其中A0,A1,A2为地址线,本例中全部接地,因此全部为0。

由于SCL和SDA为漏极开路输出,所以在使用时,需加上拉电阻。

关于I2C总线的基本操作

软件实现I2C主模式通讯看似简单,但实际应用中最容易犯的错误就是对SCL和SDA总线上高电平的实现过程。

在硬件设计上,任意选择单片机的两个IO引脚分别指派为SCL和SDA,虽然不是必须的,但为方便软件编程一般设于同一个端口,并在其上外接上拉电阻,至于ESD保护电阻和抗干扰滤波电容则为可选件,不影响I2C总线通讯。

当器件占用总线时,需要在SCL或SDA引脚上输出低电平,软件就将PORT寄存器相关位设定为0的同时对应的TRIS寄存器位也设为0;当释放总线即总线上变为高电平时,注意不能直接从IO引脚上输出高电平,而是应该将TRIS位设为1,使引脚变成高阻输入状态,通过外接的上拉电阻得到高电平。

很多工程师没有遵循这种操作规范,尽管在特定的应用中也可以实现I2C通讯,但留有很多隐患,不可盲目照搬。

对于PIC单片机来说,I2C总线的控制基本上可以简化到对TRIS寄存器相关位的控制。

在初始化时先将数据端口寄存器PORTx和PORTx引脚设为0。

需要总线为0,则TRISx=0或TRISx=0;释放总线,则TRISx=1或TRISx=1。

当单片机需要从总线上读取从器件发出的数据和应答信号时,则直接读取PORTx引脚的输入电平。

由于PORTx和TRISx寄存器在不同的bank,在程序中可以利用FSR做间接寻址以减少bank切换。

MCS-51单片机模拟I2C软件包(V1.1)(c)

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

   MCS-51单片机模拟I2C软件包(V1.1)

   文件名:

VI2C_C51.C

   相关文件:

VI2C_C51.H,VI2C_C51.LIB

   功能说明:

本模拟I2C软件包包含了I2C操作的底层函数,如发送数据及接收

数据,应答位发送,并提供了几个直接面对器件的操作函数,它很方便的与用户程

序连接并扩展..... 

   注意:

函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作一定的

修改....(本软件包是1us机器周期,即晶振频率要小于12MHZ)

   总线时序符合I2C标准模式,100Kbit/S。

                                         更新时间:

2002.06.05

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

#include

#include

#define ucharunsignedchar /*宏定义*/

#define uint unsignedint

#define _Nop() _nop_()       /*定义空指令*/

sbitSDA=P3^4;            /*模拟I2C数据传送位*/

sbitSCL=P3^5;            /*模拟I2C时钟控制位*/

bitack;          /*应答标志位*/

  

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

                    起动总线函数              

函数原型:

void Start_I2c(); 

功能:

    启动I2C总线,即发送I2C起始条件. 

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

voidStart_I2c()

{

 SDA=1;   /*发送起始条件的数据信号*/

 _Nop();

 SCL=1;

 _Nop();    /*起始条件建立时间大于4.7us,延时*/

 _Nop();

 _Nop();

 _Nop();

 _Nop();   

 SDA=0;   /*发送起始信号*/

 _Nop();    /*起始条件锁定时间大于4μs*/

 _Nop();

 _Nop();

 _Nop();

 _Nop();      

 SCL=0;   /*钳住I2C总线,准备发送或接收数据*/

 _Nop();

 _Nop();

}

 

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

                     结束总线函数              

函数原型:

void Stop_I2c(); 

功能:

    结束I2C总线,即发送I2C结束条件. 

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

voidStop_I2c()

{

 SDA=0;  /*发送结束条件的数据信号*/

 _Nop();   /*发送结束条件的时钟信号*/

 SCL=1;  /*结束条件建立时间大于4μs*/

 _Nop();

 _Nop();

 _Nop();

 _Nop();

 _Nop();

 SDA=1;  /*发送I2C总线结束信号*/

 _Nop();

 _Nop();

 _Nop();

 _Nop();

}

 

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

                字节数据发送函数              

函数原型:

void SendByte(ucharc);

功能:

    将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对

         此状态位进行操作.(不应答或非应答都使ack=0)    

      发送数据正常,ack=1;ack=0表示被控器无应答或损坏。

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

void SendByte(ucharc)

{

 ucharBitCnt;

 

 for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/

   {

    if((c<

      else SDA=0;               

    _Nop();

    SCL=1;              /*置时钟线为高,通知被控器开始接收数据位*/

     _Nop();

     _Nop();            /*保证时钟高电平周期大于4μs*/

     _Nop();

     _Nop();

     _Nop();        

    SCL=0;

   }

   

   _Nop();

   _Nop();

   SDA=1;               /*8位发送完后释放数据线,准备接收应答位*/

   _Nop();

   _Nop();  

   SCL=1;

   _Nop();

   _Nop();

   _Nop();

   if(SDA==1)ack=0;    

      elseack=1;       /*判断是否接收到应答信号*/

   SCL=0;

   _Nop();

   _Nop();

}

 

 

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

                字节数据接收函数              

函数原型:

uchar RcvByte();

功能:

   用来接收从器件传来的数据,并判断总线错误(不发应答信号),

         发完后请用应答函数应答从机。

 

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

uchar RcvByte()

{

 ucharretc;

 ucharBitCnt;

 

 retc=0;

 SDA=1;              /*置数据线为输入方式*/

 for(BitCnt=0;BitCnt<8;BitCnt++)

     {

       _Nop();          

       SCL=0;                 /*置时钟线为低,准备接收数据位*/

       _Nop();

       _Nop();                /*时钟低电平周期大于4.7μs*/

       _Nop();

       _Nop();

       _Nop();

       SCL=1;                 /*置时钟线为高使数据线上数据有效*/

       _Nop();

       _Nop();

       retc=retc<<1;

       if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中*/

       _Nop();

       _Nop();

     }

 SCL=0;   

 _Nop();

 _Nop();

 return(retc);

}

 

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

                    应答子函数

函数原型:

 voidAck_I2c(bita);

功能:

     主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)

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

voidAck_I2c(bita)

{

 

 if(a==0)SDA=0;         /*在此发出应答或非应答信号*/

       elseSDA=1;

 _Nop();

 _Nop();

 _Nop();     

 SCL=1;

 _Nop();

 _Nop();                   /*时钟低电平周期大于4μs*/

 _Nop();

 _Nop();

 _Nop(); 

 SCL=0;                    /*清时钟线,钳住I2C总线以便继续接收*/

 _Nop();

 _Nop();   

}

 

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

                用户接口函数                                  

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

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

                向无子地址器件发送字节数据函数              

函数原型:

bit ISendByte(ucharsla,ucahrc); 

功能:

    从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.

         如果返回1表示操作成功,否则操作有误。

注意:

   使用前必须已结束总线。

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

bitISendByte(ucharsla,ucharc)

{

  Start_I2c();              /*启动总线*/

  SendByte(sla);            /*发送器件地址*/

  if(ack==0)return(0);

  SendByte(c);              /*发送数据*/

  if(ack==0)return(0);

  Stop_I2c();               /*结束总线*/

  return

(1);

}

 

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

                   向有子地址器件发送多字节数据函数              

函数原型:

bit ISendStr(ucharsla,ucharsuba,ucahr*s,ucharno); 

功能:

    从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件

         地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。

         如果返回1表示操作成功,否则操作有误。

注意:

   使用前必须已结束总线。

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

bitISendStr(ucharsla,ucharsuba,uchar*s,ucharno)

{

  uchari;

  Start_I2c();              /*启动总线*/

  SendByte(sla);            /*发送器件地址*/

  if(ack==0)return(0);

  SendByte(suba);           /*发送器件子地址*/

  if(ack==0)return(0);

  for(i=0;i

  {  

    SendByte(*s);           /*发送数据*/

    if(ack==0)return(0);

    s++;

  }

  Stop_I2c();               /*结束总线*/

  return

(1);

}

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

                   向无子地址器件发送多字节数据函数              

函数原型:

bit ISendStr(ucharsla,ucahr*s,ucharno); 

功能:

    从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件

         地址sla,发送内容是s指向的内容,发送no个字节。

         如果返回1表示操作成功,否则操作有误。

注意:

   使用前必须已结束总线。

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

bitISendStrExt(ucharsla,uchar*s,ucharno)

{

  uchari;

  Start_I2c();              /*启动总线*/

  SendByte(sla);            /*发送器件地址*/

  if(ack==0)return(0);

  for(i=0;i

  {  

    SendByte(*s);           /*发送数据*/

    if(ack==0)return(0);

    s++;

  }

  Stop_I2c();               /*结束总线*/

  return

(1);

}

 

 

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

                   向无子地址器件读字节数据函数              

函数原型:

bit IRcvByte(ucharsla,ucahr*c); 

功能:

    从启动总线到发送地址,读数据,结束总线的全过程,从器件地

         址sla,返回值在c.

          如果返回1表示操作成功,否则操作有误。

注意:

   使用前必须已结束总线。

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

bitIRcvByte(ucharsla,uchar*c)

{

  Start_I2c();               /*启动总线*/

  SendByte(sla+1);           /*发送器件地址*/

  if(ack==0)return(0);

  *c=RcvByte();              /*读取数据*/

  Ack_I2c

(1);                /*发送非就答位*/

  Stop_I2c();                /*结束总线*/

  return

(1);

}

 

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

                   向有子地址器件读取多字节数据函数              

函数原型:

bit ISendStr(ucharsla,ucharsuba,ucahr*s,ucharno); 

功能:

    从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件

         地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。

          如果返回1表示操作成功,否则操作有误。

注意:

   使用前必须已结束总线。

*********************************

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

当前位置:首页 > PPT模板 > 其它模板

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

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