IIC总线介绍


I 2C 总线是一种用于IC 器件之间连接的二线制总线。它通过SDA(串行数据线)及SCL(串行时钟线)两根线在连到总线上的器件之间传送数据,并根据地址识别每个器件:不管是单片机、存储器、LCD 驱动器还是键盘接口。I2C 能用于替代标准的并行总线,能连接各种集成电路和功能模块。支持IIC 的设备有微控制器、ADCDAC、储存器、LCD 控制器、LED 驱动器以及实时时钟等。采用I2C 总线标准的单片机或IC 器件,其内部不仅有I2C 接口电路,而且将内部各单元电路按功能划分为若干相对独立的模块,通过软件寻址实现片选,减少了器件片选线的连接。CPU 不仅能通过指令将某个功能单元挂靠或摘离总线,还可对该单元的工作状况进检测,从而实现对硬件系统简单而灵活的扩展与控制。I2C 总线接口电路结构如下图所示:

IIC 总线接口特性

1.单片机串行接口的发送和接收一般都各用一条线,如的TXD RXD,而I2C总线则根据器件的功能通过软件程序使其可工作于发送或接收方式。

2.当某个器件向总线上发送信息时,它就是发送器(也叫主器件),而当其从总线上接收信息时,又成为接收器(也叫从器件)

3.主器件用于启动总线上传送数据并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件。I2C 总线的控制完全由挂接在总线上的主器件送出的地址和数据决定。

 

4.总线上主和从(即发送和接收)的关系不是一成不变的,而是取决于此时数据传送的方向。

5.I2C 总线的数据传送速率在标准工作方式下为100kbit/s,快速方式下最高传送速率400kbit/s

6.I2C 总线上传送信息时的时钟同步信号是由挂接在SCL 时钟线上的所有器件的逻辑完成的。SCL 线上由高电平到低电平的跳变将影响到这些器件,一旦某个器件的时钟信号下跳为低电平,将使SCL 线一直保持低电平,使SCL线上的所有器件开始低电平期。

7.当所有器件的时钟信号都上跳为高电平时,低电平期结束,SCL 线被释放返回高电平,即所有的器件都同时开始它们的高电平期。其后,第一个结束高电平期的器件又将SCL 线拉成低电平。这样就在SCL 线上产生一个同步时钟。可见,时钟低电平时间由时钟低电平期最长的器件确定,而时钟高电平时间由时钟高电平期最短的器件确定。

8.I2C 总线技术规范中,开始和结束信号(也称启动和停止信号)的定义如下图所示。

9.当时钟线SCL 为高电平时,数据线SDA 由高电平跳变为低电平定义为开始信号;

10.SCL 线为高电平时,SDA 线发生低电平到高电平的跳变为结束信号。

11.开始和结束信号都是由主器件产生。

12.在开始信号以后,总线即被认为处于忙状态;在结束信号以后的一段时间内,总线被认为是空闲的。

 

IIC 总线数据传送格式

1.I2C 总线开始信号后,送出的第一个字节数据是用来选择从器件地址的。

(1) 其中前7 位为地址码;

(2) 8 位为方向位(R/W)。方向位为“0”表示发送,即主器件把信息写到所选择的从器件;方向位为“1”表示主器件将从从器件读信息。

2. I2C 总线上每次传送的数据字节数不限,但每一个字节必须为8 位,而且每个传送的字节后面必须跟一个认可位(第9 位),也叫应答位(ACK;

 

 

 

 

为了完成一个字节的传输,接收方应该向发送方发送一个ACK位。ACK应该发生在SCL线的第九个脉冲期间。当接受到ACK信号时,发送方应该释放SDA线使SDA线电平为高。接收方应该驱动SDA线为低在ACK脉冲过程中。因此,在第九个SCL脉冲的高电平期间SDA保持为低(因为信号是“与”的)。ACK的传输可以由软件通过IICSTAT寄存器控制是否禁止,但它仍然是需要产生的。

IIC 总线数据传送过程

1.每次都是先传最高位,通常从器件在接收到每个字节后都会做出响应,即释放SCL线返回高电平,准备接收下一个数据字节,主器件可继续传送。

2.如果从器件正在处理一个实时事件而不能接收数据时,(例如正在处理一个内部中断,在这个中断处理完之前就不能接收I2C 总线上的数据字节)可以使时钟SCL线保持低电平,从器件必须使SDA 保持高电平,此时主器件产生1 个结束信号,使传送异常结束,迫使主器件处于等待状态。当从器件处理完毕时将释放SCL 线,主器件继续传送

读写操作

在发送模式下,当一个数据传输时,IIC总线接口将等待直到IICDS寄存器收到一个新数据。在一个新数据写入IICDS寄存器前,SCL信号将保持为低。在数据被写入之后,信号线被释放(为高)。ARM需要保持中断信号来辨别当前数据发送完成。在ARM接到一个中断请求后,它将写一个新的数据到IICDS

在接收模式下,当一个数据接收时,IIC总线接口将等待直到IICDS寄存器数据被读出。在新数据被读出之前,SCL信号保持为低。在数据被读出后,信号线被释放(为高)。ARM应保持中断信号以辨别接收数据操作完成。在ARM收到一个中断请求时,它将从IICDS读出数据。

IIC 总线竞争和仲裁机制

1. 总线上可能挂接有多个器件,有时会发生两个或多个主器件同时想占用总线的情

况。

2. I2C 总线具有多主控能力,可以对发生在SDA 线上的总线竞争进行仲裁。

3. 其仲裁原则为:当多个主器件同时想占用总线时,如果某个主器件发送高电平,

而另一个主器件发送低电平,则发送电平与此时SDA 总线电平不符的那个器件将

自动关闭其输出级。

IIC 总线工作流程

开始:信号表明传输开始。

地址:主设备发送地址信息,包含7 位的从设备地址和1 位的指示位(表明读或者写,即数据流的方向)。

数据:根据指示位,数据在主设备和从设备之间传输。数据一般以8 位传输,最重要的位放在前面;具体能传输多少量的数据并没有限制。接收器上用一位的ACK 表明每一个字节都收到了。传输可以被终止和重新开始。

停止:信号结束传输。

S3C2410 IIC 总线控制器

S3C2410 处理器提供了一个I2C 串行总线,包括一个专门的串行数据线和串行时

钟线。它的操作模式有四种:

1.主设备发送模式

2.主设备接收模式

3.从设备发送模式

4.从设备接收模式

下图为S3C2410 IIC 功能框图:

 

发送和接收步骤

在任何IIC Tx/Rx 操作之前,下面的步骤必须被执行

1. 如果需要的话,向IICADD 寄存器写从器件地址

2. 设置IICCON 寄存器

a) 允许中断

b) 定义SCL 的时钟周期

3. 设置IICSTAT 来允许串行输出

IIC 总线控制相关寄存器

IIC 总线控制寄存器(IICCON

  

Register

Address

R/W

Description

Reset Value

IICCON

0x54000000

R/W

总线控制寄存器

0x0X

 

IICCON

Bit

Description

Initial State

Acknowledge generation (note 1)

[7]

IIC总线确认位使能

0 = 禁止, 1 =使能

Tx模式,IICSDA在确认时间内是任意的,在Rx 模式中= IICSDA 在确认时间内是低

0

Tx clock source selection

[6]

IIC总线传输时间对于资源时间的分频位

0 = IICCLK = fPCLK /16

1 = IICCLK = fPCLK /512

0

Tx/Rx Interrupt (note 5)

[5]

IIC总线 Tx/Rx中断使能/禁止位

0 = Disable, 1 = Enable

0

Interrupt pending flag (note 2), (note 3)

[4]

IIC总线Tx/Rx中断未决标志位.

该位不能被写为1,当该位读为1的时候,IICSCL信号为低并且IIC停止,要恢复操作,只需将该位清零

0 = 1) 没有中断未决(读)2)清除未决状态 &恢复操作 ().

1 = 1) 中断未决()  2) N/A ()

0

Transmit clock value (note 4)

[3:0]

IIC总线传输时钟预分频 IIC总线传输时钟频率由这个四位的值决定,由下列公式决定

Tx clock =IICCLK/(IICCON[3:0]+1).

未定义

 

 

 

注意:

1.下面的几种情况将产生一个IIC 中断:

1) 当一个字节传输或接受操作完成的时 ;

2) 一个普通调用或一个从地址匹配产生时;

3) 总线仲裁失败时;

2. 为了在IISSCL信号的上升沿之前调整IICSDA的设置时间,IICDS必须要在IIC的中断位清零之前写入。

3IICLK IICCON[6]决定;

   Tx时钟会因为SCL时间的转换而改变

IIC 状态寄存器(IICSTAT

 

 

 

 

 

 

 

 

Register

Address

R/W

Description

Reset Value

IICSTAT

0x54000004

R/W

IIC总线状态寄存器

0x0

 

IICSTAT

Bit

Description

Initial State

Mode selection

[7:6]

IIC总线主/ Tx/Rx模式选择位.

00: 从设备接受模式  01: 从设备发送模式

10: 主设备接受模式  11: 主设备发送模式

00

Busy signal status / START STOP condition

[5]

IIC总线忙信号状态位

0 = ) 空闲 ) STOP 信号产生

1 = )    ) START信号产生.

IICDS中的数据在START信号后自动传输

 

Serial output

[4]

IIC总线数据输出使能/禁止位

0 =禁止 Rx/Tx,  1 = 使能 Rx/Tx

0

Arbitration status flag

[3]

IIC总线过程仲裁状态位

0 =总线仲裁成功

1 = 在连续I/O 中总线仲裁失败

0

Address-as-slave status flag

[2]

IIC总线从地址状态标志位.

0 = START/STOP信号探测到时清零

1 =接收到的slave地址匹配IICADD的值

0

Address zero status flag

[1]

IIC总线地址零状态标志位

0 =START/STOP信号探测到时清零.

1 =接收到的从地址为 00000000b.

0

Last-received bit status flag

[0]

IIC总线IIC-bus上一次接收到的状态标志位.

0 =上一次接收到的位是0 (ACK was received).

1 =上一次接收到的位是1 (ACK was not received).

0

 

 

地址寄存器(IICADD

 

Register

Address

R/W

Description

Reset Value

IICADD

0x54000008

R/W

IIC总线地址寄存器

0xXX

 

IICADD

Bit

Description

Initial State

Slave address

[7:0]

7位从地址,IIC总线中锁存

XXXXXXXX

 

 

IICSTAT 串行输出允许为0IICADD 为写允许的时候

 

 

 

IICADD的值可以在任何时候被读取, 而不用管当前串行

 

 

 

输出允许位(IICSTAT)的设置

 

 

 

从地址     = [7:1]

 

 

 

Not mapped = [0]

 

 

 

移位数据寄存器(IICDS

 

Register

Address

R/W

Description

Reset Value

IICDS

0x5400000C

R/W

IIC总线移位数据寄存器

0xXX

 

IICDS

Bit

Description

Initial State

Data shift

[7:0]

IIC总线Tx/Rx 操作的8位移位寄存器

XXXXXXXX

 

 

IICSTAT 串行输出允许为1IICADD 为写允许的时候

 

 

 

IICDS的值可以在任何时候被读取, 而不用管当前串行输

 

 

 

出允许位(IICSTAT)的设置.

 

源代码:

 #include <string.h>
#include "2440addr.h"
#include "2440lib.h"
#include "def.h"

#define WRDATA      (1)
#define POLLACK     (2)
#define RDDATA      (3)
#define SETRDADDR   (4)

#define IICBUFSIZE 0x20
static U8 iicData[IICBUFSIZE];
static volatile int iicDataCount;
static volatile int iicStatus;
static volatile int iicMode;
static int iicPt;
  
void Wr24C02(U32 slvAddr,U32 addr,U8 data);  
void Rd24C02(U32 slvAddr,U32 addr,U8 *data); 

void IicPoll(void);
void Run_IicPoll(void);


void Main(void)
{
 unsigned int i,j;
 static U8 data[256]; //用于存储AT24C02读出的数据
 
 SelectFclk(2);  //设置系统时钟 400M    
 ChangeClockDivider(2, 1);      //设置分频 1:4:8
 CalcBusClk();           //计算总线频率
 
 rGPHCON &=~((3<<4)|(3<<6));  
    rGPHCON |=(2<<4)|(2<<6);    //GPH2--TXD[0];GPH3--RXD[0]  
     
    rGPHUP=0x00;        //使能上拉功能
     
    Uart_Init(0,115200);
    Uart_Select(0);
   
 Uart_Printf("[ IIC Test(Polling) using AT24C020 ]\n");

 rGPEUP  |= 0xc000;                 //关上拉
 
 rGPECON &= ~0xf0000000;
 rGPECON |= 0xa0000000;       //GPE15:IICSDA , GPE14:IICSCL   

 //使能应答, IIC总线时钟IICCLK=PCLK/16, 使能中断, 发送时钟IICCLK/16
 rIICCON  = (1<<7) | (0<<6) | (1<<5) | (0xf);

 rIICADD  = 0x10;            //2440 从机地址 = [7:1]
 rIICSTAT = 0x10;            //IIC总线数据输出使能(Rx/Tx)
 
 Uart_Printf("Write test data into AT24C02\n");

 for(i=0;i<256;i++)
  Wr24C02(0xa0,(U8)i,i);//写入数据到AT24C02
  
 for(i=0;i<256;i++) //数组数据清零
  data[i] = 0;

 Uart_Printf("Read test data from AT24C02\n");
 for(i=0;i<256;i++)
  Rd24C02(0xa0,(U8)i,&(data[i]));//读取AT24C02的数据放入data数组中

 for(i=0;i<16;i++)
 {
  for(j=0;j<16;j++)
   Uart_Printf("%2x ",data[i*16+j]); //打印从AT24C02读出的数据
  Uart_Printf("\n");
 }  
}

void Wr24C02(U32 slvAddr,U32 addr,U8 data) // slvAddr 为从地址
            //addr为字节地址,data为写入的数据
 iicMode      = WRDATA;  //写数据模式 
 iicPt        = 0;
 iicData[0]   = (U8)addr;
 iicData[1]   = data;
 iicDataCount = 2; //根据AT24C02字节写的发式,要写从地址和字节地址
   
 rIICDS = slvAddr;    //把0xa0地址写入到数据移位寄存器IICDS
 //Master Tx mode, Start(Write), IIC-bus data output enable
 //Bus arbitration sucessful, Address as slave status flag Cleared,
 //Address zero status flag cleared, Last received bit is 0
 rIICSTAT      = 0xf0; //    
 //Clearing the pending bit isn't needed because the pending bit has been cleared.
 while(iicDataCount!=-1)
  Run_IicPoll();

 iicMode = POLLACK;

 while(1)
 {
  rIICDS     = slvAddr;
  iicStatus = 0x100;             //To check if _iicStatus is changed
  rIICSTAT   = 0xf0;              //Master Tx, Start, Output Enable, Sucessful, Cleared, Cleared, 0
  rIICCON    = 0xaf;              //Resumes IIC operation.
  while(iicStatus==0x100) 
   Run_IicPoll();
             
  if(!(iicStatus & 0x1))
   break;                      //When ACK is received
 }
 rIICSTAT = 0xd0;                    //Master Tx condition, Stop(Write), Output Enable
 rIICCON  = 0xaf;                    //Resumes IIC operation.
 Delay(1);                           //Wait until stop condtion is in effect.
 //Write is completed.
}
       
//************************[ _Rd24C02 ]********************************
void Rd24C02(U32 slvAddr,U32 addr,U8 *data)
{
 iicMode      = SETRDADDR; //设置要从从机读取数据的从地址
 iicPt        = 0;
 iicData[0]   = (U8)addr;
 iicDataCount = 1;  //写从地址

 rIICDS   = slvAddr;
 rIICSTAT = 0xf0;                    //MasTx,Start 
 //Clearing the pending bit isn't needed because the pending bit has been cleared.
 while(iicDataCount!=-1)
  Run_IicPoll();

 iicMode      = RDDATA; //读数据模式
 iicPt        = 0;
 iicDataCount = 1; //
   
 rIICDS   = slvAddr;
 rIICSTAT = 0xb0;                    //Master Rx,Start
 rIICCON  = 0xaf;                    //Resumes IIC operation.  
 while(iicDataCount!=-1)
  Run_IicPoll();

 *data = iicData[1];
}

void Run_IicPoll(void)
{
 if(rIICCON & 0x10)     // Tx/Rx 中断使能
  IicPoll();
     
  
void IicPoll(void)
{
 U32 iicSt,i;
   
 iicSt = rIICSTAT;  //ICC状态寄存器
 if(iicSt & 0x8){}   //总线仲裁失败 
 if(iicSt & 0x4){}   //从地址与ICCADD地址匹配
 if(iicSt & 0x2){}   //从地址为00000000b             
 if(iicSt & 0x1){}   //未收到ACK               

 switch(iicMode)
 {
  case POLLACK:
   iicStatus = iicSt;
   break;

  case RDDATA: //从从机中读取数据
   if((iicDataCount--)==0)
   {
    iicData[iicPt++] = rIICDS;
           
    rIICSTAT = 0x90;                //Stop MasRx condition
    rIICCON  = 0xaf;                //Resumes IIC operation.
    Delay(1);                       //Wait until stop condtion is in effect.
                                                //Too long time...
                                                //The pending bit will not be set after issuing stop condition.
    break;   
       
   iicData[iicPt++] = rIICDS;
       //The last data has to be read with no ack.
   if((iicDataCount)==0)
    rIICCON = 0x2f;                 //Resumes IIC operation with NOACK. 
   else
    rIICCON = 0xaf;                 //Resumes IIC operation with ACK
   break;

  case WRDATA: //写数据到从机
   if((iicDataCount--)==0)
   {
    rIICSTAT = 0xd0;                //stop MasTx condition
    rIICCON  = 0xaf;                //resumes IIC operation.
    Delay(1);                       //wait until stop condtion is in effect.
    //The pending bit will not be set after issuing stop condition.
    break;   
   }
   rIICDS = iicData[iicPt++];        //iicData[0] has dummy.
   for(i=0;i<10;i++);                  //for setup time until rising edge of IICSCL
   rIICCON = 0xaf;                     //resumes IIC operation.
   break;

  case SETRDADDR: //设置要从从机机读取数据的从机地址
   if((iicDataCount--)==0)
   {
    break;                  //IIC operation is stopped because of IICCON[4]   
   }
   rIICDS = iicData[iicPt++];
   for(i=0;i<10;i++);          //for setup time until rising edge of IICSCL
   rIICCON = 0xaf;             //resumes IIC operation.
   break;

  default:
   break;     
 }
}


  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值