天天看點

IIC總線介紹

I 2C 總線是一種用于IC 器件之間連接配接的二線制總線。它通過SDA(串行資料線)及SCL(串行時鐘線)兩根線在連到總線上的器件之間傳送資料,并根據位址識别每個器件:不管是單片機、存儲器、LCD 驅動器還是鍵盤接口。I2C 能用于替代标準的并行總線,能連接配接各種內建電路和功能子產品。支援IIC 的裝置有微控制器、ADC、DAC、儲存器、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 在确認時間内是低

Tx clock source selection [6]

IIC總線傳輸時間對于資源時間的分頻位

0 = IICCLK = fPCLK /16

1 = IICCLK = fPCLK /512

Tx/Rx Interrupt (note 5) [5]

IIC總線 Tx/Rx中斷使能/禁止位

0 = Disable, 1 = Enable

Interrupt pending flag (note 2), (note 3) [4]

IIC總線Tx/Rx中斷未決标志位.

該位不能被寫為1,當該位讀為1的時候,IICSCL信号為低并且IIC停止,要恢複操作,隻需将該位清零

0 = 1) 沒有中斷未決(讀)2)清除未決狀态 &恢複操作 (寫).

1 = 1) 中斷未決(讀)  2) N/A (寫)

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的中斷位清零之前寫入。

3.IICLK 由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

Arbitration status flag [3]

IIC總線過程仲裁狀态位

0 =總線仲裁成功

1 = 在連續I/O 中總線仲裁失敗

Address-as-slave status flag [2]

IIC總線從位址狀态标志位.

0 = 當START/STOP信号探測到時清零

1 =接收到的slave位址比對IICADD的值

Address zero status flag [1]

IIC總線位址零狀态标志位

0 =當START/STOP信号探測到時清零.

1 =接收到的從位址為 00000000b.

Last-received bit status flag [0]

IIC總線IIC-bus上一次接收到的狀态标志位.

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

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

位址寄存器(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 串行輸出允許為0,IICADD 為寫允許的時候
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 串行輸出允許為1,IICADD 為寫允許的時候
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;     

 }

}