I2C 资料

I2C是英文“Inter   Integrated   Circuit”的缩写,中文意思是“集成电路之间”。总线(Bus)是用来传送 信息的公用线。I2C总线就是集成电路之间传送时钟脉冲与数据的公用线路。采用I2C总线控制就是将微处理器的SCL(串行时钟)、SDA(串行数据)用总线(一根时钟线与一根数据线)与其它集成电路或存储器连接起来,通过总线来交换信息,实行控制。这样可以减少印制板连接线;而且便于调试与测试;在开发新产品时,由于电路单元可直接在总线上接入和分离,可以很方便地在一个产品的基础上,完成一系列新产品的开发。

2C总线特点
I2C总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。I2C总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。
   
          I2C数据传输的格式是:启动条件   -->   从地址(7bit)   -->   读写(1bit)   -->   确认   -->   子地址(8bit)   -->   确认   -->   传输数据   [n(8bit+确认位)]   -->   停止条件  
        I2C总线传输数据首先要满足启动条件。启动条件是:时钟线(SCL)为高电位时数据线(SDA)由高电位转向低电位。启动条件通常由微处理器(MPU)产生。MPU产生启动条件后,接着传送7位二进制数(7bit)组成的“从地址”,所谓“从地址”(即从属地址)就是I2C总线所连接的各集成电路的编号(二进制数);例如TA8880CN的从地址是1000100、TA8776N的从地址是1000000,不同的集成电路有不同的从地址。MPU若传送从地址1000100,TA8880CN就接收数据,而TA8776N则不能接收数据。传送从地址之后,传送1bit的读写位;读写位如为“0”,表示MPU向其他集成电路发送数据,即写入数据;如为“1”表示MPU接收其他集成电路发送的数据,即读入数据。第9位是确认位,此时MPU发送的时钟脉冲SCL线为高电位,接收数据的集成电路必须把SDA线电位拉低到低电位,才确认接收数据,即传送的数据才有效。接着再传送8bit的“子地址”。所谓“子地址”,就是在被控制的集成电路中存放各种控制数据的存储单元的地址。例如TA8880CN子地址00000000存放白峰值限幅器及色饱和度控制数据。子地址00000001存放锐度调整开关与色调控制数据。子地址传送后同样要有确认位。然后一个字节接一个字节地传输数据,每一个字节是8bit长,后面都要跟随一个确认位,直到MPU发出停止条件为止。停止条件是:当SCL线在高电位时,SDA线由低电位变为高电位。
Demo:
#include   <reg51.h>  
   
  #include   <intrins.h>    
   
  #define   uchar   unsigned   char  
   
  #define   uint   unsigned   int  
   
  #define   AddWr   0xa0   /*器件地址选择及写标志*/  
   
  #define   AddRd   0xa1   /*器件地址选择及读标志*/  
   
  #define   Hidden   0x0e   /*显示器的消隐码*/  
   
  /*有关全局变量*/  
   
  sbit   Sda=   P3^7;   /*串行数据*/  
   
  sbit   Scl=   P3^6;   /*串行时钟*/  
   
  sbit   WP=   P3^5;   /*硬件写保护*/  
   
  void   mDelay(uchar   j)  
   
  {   uint   i;  
  for(;j>0;j--)  
  {   for(i=0;i<125;i--)  
  {;}  
  }  
  }  
   
  /*发送起始条件*/  
   
  void   Start(void)   /*起始条件*/  
   
  {  
   
  Sda=1;  
   
  Scl=1;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  Sda=0;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  }  
   
  void   Stop(void)   /*停止条件*/  
   
  {  
   
  Sda=0;  
   
  Scl=1;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  Sda=1;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  }  
   
  void   Ack(void)   /*应答位*/  
   
  {  
   
  Sda=0;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  Scl=1;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  Scl=0;  
   
  }  
   
  void   NoAck(void)   /*反向应答位*/  
   
  {  
   
  Sda=1;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  Scl=1;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  Scl=0;  
   
  }  
   
  void   Send(uchar   Data)   /*发送数据子程序,Data为要求发送的数据*/  
   
  {  
   
  uchar   BitCounter=8;   /*位数控制*/  
   
  uchar   temp;   /*中间变量控制*/  
   
  do  
   
  {  
   
  temp=Data;  
   
  Scl=0;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  if((temp&0x80)==0x80)/*   如果最高位是1*/  
   
  Sda=1;  
   
  else  
   
  Sda=0;  
   
  Scl=1;  
   
  temp=Data<<1;   /*RLC*/  
   
  Data=temp;  
   
  BitCounter--;  
   
  }while(BitCounter);  
   
  Scl=0;  
   
  }  
   
   
  uchar   Read(void)   /*读一个字节的数据,并返回该字节值*/  
   
  {  
   
  uchar   temp=0;  
   
  uchar   temp1=0;  
   
  uchar   BitCounter=8;  
   
  Sda=1;  
   
  do{  
   
  Scl=0;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  Scl=1;  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  _nop_   ();  
   
  if(Sda)   /*如果Sda=1;*/  
   
  temp=temp|0x01;   /*temp的最低位置1*/  
   
  else  
   
  temp=temp&0xfe;   /*否则temp的最低位清0*/  
   
  if(BitCounter-1)  
   
  {   temp1=temp<<1;  
   
  temp=temp1;  
   
  }  
   
  BitCounter--;  
   
  }while(BitCounter);  
   
  return(temp);  
   
  }  
   
   
  void   WrToROM(uchar   Data[],uchar   Address,uchar   Num)  
   
  {  
   
  uchar   i;  
   
  uchar   *PData;  
   
  PData=Data;  
   
  for(i=0;i<Num;i++)  
   
  {  
   
  Start();   /*发送启动信号*/  
   
  Send(0xa0);   /*发送SLA+W*/  
   
  Ack();  
   
  Send(Address+i);   /*发送地址*/  
   
  Ack();  
   
  Send(*(PData+i));  
   
  Ack();  
   
  Stop();  
   
  mDelay(20);  
   
  }  
   
  }  
   
  void   RdFromROM(uchar   Data[],uchar   Address,uchar   Num)  
   
  {  
   
  uchar   i;  
   
  uchar   *PData;  
   
  PData=Data;  
   
  for(i=0;i<Num;i++)  
   
  {  
   
  Start();  
   
  Send(0xa0);  
   
  Ack();  
   
  Send(Address+i);  
   
  Ack();  
   
  Start();  
   
  Send(0xa1);  
   
  Ack();  
   
  *(PData+i)=Read();  
   
  Scl=0;  
   
  NoAck();  
   
  Stop();  
   
  }  
   
  }  
   
  void   main()  
   
  {  
   
  uchar   Number[4]={1,2,3,4};  
   
  WP=   1;  
   
  WrToROM(Number,4,4);   /*将初始化后的数值写入EEPROM*/  
   
  mDelay(20);  
   
  Number[0]=0;  
   
  Number[1]=0;  
   
  Number[2]=0;  
   
  Number[3]=0;   /*将数组中的值清掉,以验证读出的数是否正确*/  
   
  RdFromROM(Number,4,4);  
   
  }  

你可能感兴趣的:(c)