SPI、I2C、UART的區別和聯繫

第一個區別當然是名字:
     SPI(Serial Peripheral Interface:串行外設接口);
     I2C(INTER IC BUS)
     UART(Universal Asynchronous Receiver Transmitter:通用異步收發器)

第二,區別在電氣信號線上:
     SPI總線由三條信號線組成:串行時鐘(SCLK)、串行數據輸出(SDO)、串行數據輸入(SDI)。SPI總線可以實現 多個SPI設備互相連接。提供SPI串行時鐘的SPI設備爲SPI主機或主設備(Master),其他設備爲SPI從機或從設備(Slave)。主從設備 間可以實現全雙工通信,當有多個從設備時,還可以增加一條從設備選擇線。
     如果用通用IO口模擬SPI總線,必須要有一個輸出口(SDO),一個輸入口(SDI),另一個口則視實現的設備類型而定,如果要實現主從設備,則需輸入輸出口,若只實現主設備,則需輸出口即可,若只實現從設備,則只需輸入口即可。

     I2C總線是雙向、兩線(SCL、SDA)、串行、多主控(multi-master)接口標準,具有總線仲裁機制,非常適合在器件之間進行近距離、非經常性的數據通信。在它的協議體系中,傳輸數據時都會帶上目的設備的設備地址,因此可以實現設備組網。
     如果用通用IO口模擬I2C總線,並實現雙向傳輸,則需一個輸入輸出口(SDA),另外還需一個輸出口(SCL)。(注:I2C資料瞭解得比較少,這裏的描述可能很不完備)

     UART總線是異步串口,因此一般比前兩種同步串口的結構要複雜很多,一般由波特率產生器(產生的波特率等於傳輸波特率的16倍)、UART接收器、UART發送器組成,硬件上由兩根線,一根用於發送,一根用於接收。
     顯然,如果用通用IO口模擬UART總線,則需一個輸入口,一個輸出口。

第三,從第二點明顯可以看出,SPI和UART可以實現全雙工,但I2C不行;

第四,看看牛人們的意見吧!
     wudanyu:I2C線更少,我覺得比UART、SPI更爲強大,但是技術上也更加麻煩些,因爲I2C需要有雙向IO的支持,而且使用上拉電阻,我覺得 抗干擾能力較弱,一般用於同一板卡上芯片之間的通信,較少用於遠距離通信。SPI實現要簡單一些,UART需要固定的波特率,就是說兩位數據的間隔要相 等,而SPI則無所謂,因爲它是有時鐘的協議。
     quickmouse:I2C的速度比SPI慢一點,協議比SPI複雜一點,但是連線也比標準的SPI要少。

posted @ 2009-02-22 23:00 陳廣強 閱讀(13) | 評論 (0) | 編輯
SPI總線簡介

同步外設接口(SPI)是由摩托羅拉公司開發的全雙工同步串行總線,該總線大量用在與EEPROM、ADC、FRAM和顯示驅動器之類的慢速外設器件通信。

SPI(Serial Peripheral Interface)是一種串行同步通訊協議由一個主設備和一個或多個從設備組成,主設備啓動一個與從設備的同步通訊,從而完成數據的交換。SPI 接口由SDI(串行數據輸入),SDO(串行數據輸出),SCK(串行移位時鐘),CS(從使能信號)四種信號構成,CS 決定了唯一的與主設備通信的從設備,如沒有CS 信號,則只能存在一個從設備,主設備通過產生移位時鐘來發起通訊。通訊時,數據由SDO 輸出,SDI 輸入,數據在時鐘的上升或下降沿由SDO 輸出,在緊接着的下降或上升沿由SDI 讀入,這樣經過8/16 次時鐘的改變,完成8/16 位數據的傳輸。

SPI通信

該總線通信基於主-從配置。它有以下4個信號:

MOSI:主出/從入

MISO:主入/從出

SCK:串行時鐘

SS:從屬選擇

芯片上“從屬選擇”(slave-select)的引腳數決定了可連到總線上的器件數量。

        在SPI傳輸中,數據是同步進行發送和接收的。數據傳輸的時鐘基於來自主處理器的時鐘脈衝,摩托羅拉沒有定義任何通用SPI的時鐘規範。然而,最常用的時鐘設置基於時鐘極性(CPOL)和時鐘相位(CPHA)兩個參數,CPOL定義SPI串行時鐘的活動狀態,而CPHA定義相對於SO-數據位的時鐘相位。CPOL和CPHA的設置決定了數據取樣的時鐘沿。

數據方向和通信速度

        SPI傳輸串行數據時首先傳輸最高位。波特率可以高達5Mbps,具體速度大小取決於SPI硬件。例如,Xicor公司的SPI串行器件傳輸速度能達到5MHz。

SPI總線接口及時序

SPI總線包括1根串行同步時鐘信號線以及2根數據線。

SPI模塊爲了和外設進行數據交換,根據外設工作要求,其輸出串行同步時鐘極性和相位可以進行配置,時鐘極性(CPOL)對傳輸協議沒有重大的影響。如果CPOL=0,串行同步時鐘的空閒狀態爲低電平;如果CPOL=1,串行同步時鐘的空閒狀態爲高電平時鐘相位(CPHA)能夠配置用於選擇兩種不同的傳輸協議之一進行數據傳輸。如果CPHA=0,在串行同步時鐘的第一個跳變沿(上升或下降)數據被採樣;如果CPHA=1,在串行同步時鐘的第二個跳變沿(上升或下降)數據被採樣。SPI主模塊和與之通信的外設備時鐘相位和極性應該一致。SPI主模塊和與之通信的外設備時鐘相位和極性應該一致。個人理解這句話有2層意思:其一,主設備SPI時鐘和極性的配置應該由外設來決定;其二,二者的配置應該保持一致,即主設備的SDO同從設備的SDO配置一致,主設備的SDI同從設備的SDI配置一致。因爲主從設備是在SCLK的控制下,同時發送和接收數據,並通過2個雙向移位寄存器來交換數據。SPI接口時序如圖3、圖4所示。

 

SPI是一個環形總線結構,由ss(cs)、sck、sdi、sdo構成,其時序其實很簡單,主要是在sck的控制下,兩個雙向移位寄存器進行數據交換。
      假設下面的8位寄存器裝的是待發送的數據10101010,上升沿發送、下降沿接收、高位先發送。
      那麼第一個上升沿來的時候數據將會是sdo=1;寄存器=0101010x。下降沿到來的時候,sdi上的電平將所存到寄存器中去,那麼這時寄存器=0101010sdi,這樣在8個時鐘脈衝以後,兩個寄存器的內容互相交換一次。這樣就完成裏一個spi時序。
      例子:
      假設主機和從機初始化就緒:並且主機的sbuff=0xaa,從機的sbuff=0x55,下面將分步對spi的8個時鐘週期的數據情況演示一遍:假設上升沿發送數據

 

脈衝 主機sbuff 從機sbuff sdi sdo
0 10101010 01010101 0 0
1上 0101010x 1010101x 0 1
1下 01010100 10101011 0 1
2上 1010100x 0101011x 1 0
2下 10101001 01010110 1 0
3上 0101001x 1010110x 0 1
3下 01010010 10101101 0 1
4上 1010010x 0101101x 1 0
4下 10100101 01011010 1 0
5上 0100101x 1011010x 0 1
5下 01001010 10110101 0 1
6上 1001010x 0110101x 1 0
6下 10010101 01101010 1 0
7上 0010101x 1101010x 0 1
7下 00101010 11010101 0 1
8上 0101010x 1010101x 1 0
8下 01010101 10101010 1 0

這 樣就完成了兩個寄存器8位的交換,上面的上表示上升沿、下表示下降沿,sdi、sdo相對於主機而言的。其中ss引腳作爲主機的時候,從機可以把它拉底被 動選爲從機,作爲從機的是時候,可以作爲片選腳用。根據以上分析,一個完整的傳送週期是16位,即兩個字節,因爲,首先主機要發送命令過去,然後從機根據 主機的名準備數據,主機在下一個8位時鐘週期才把數據讀回來 

SPI 總線是Motorola公司推出的三線同步接口,同步串行3線方式進行通信:一條時鐘線SCK,一條數據輸入線MOSI,一條數據輸出線MISO;用於 CPU與各種外圍器件進行全雙工、同步串行通訊。SPI主要特點有:可以同時發出和接收串行數據;可以當作主機或從機工作;提供頻率可編程時鐘;發送結束 中斷標誌;寫衝突保護;總線競爭保護等。圖3示出SPI總線工作的四種方式,其中使用的最爲廣泛的是SPI0和SPI3方式(實線表示):

圖2   SPI總線四種工作方式

SPI 模塊爲了和外設進行數據交換,根據外設工作要求,其輸出串行同步時鐘極性和相位可以進行配置,時鐘極性(CPOL)對傳輸協議沒有重大的影響。如果 CPOL=0,串行同步時鐘的空閒狀態爲低電平;如果CPOL=1,串行同步時鐘的空閒狀態爲高電平。時鐘相位(CPHA)能夠配置用於選擇兩種不同的傳 輸協議之一進行數據傳輸。如果CPHA=0,在串行同步時鐘的第一個跳變沿(上升或下降)數據被採樣;如果CPHA=1,在串行同步時鐘的第二個跳變沿 (上升或下降)數據被採樣。SPI主模塊和與之通信的外設音時鐘相位和極性應該一致。SPI接口時序如圖3、圖4所示。

二,.SPI功能模塊的設計

根據功能定義及SPI的工作原理,將整個IP Core分爲8個子模塊:uC接口模塊、時鐘分頻模塊、發送數據FIFO模塊、接收數據FIFO模塊、狀態機模塊、發送數據邏輯模塊、接收數據邏輯模塊以及中斷形式模塊。

深入分析SPI的四種傳輸協議可以發現,根據一種協議,只要對串行同步時鐘進行轉換,就能得到其餘的三種協議。爲了簡化設計規定,如果要連續傳輸多個數據,在兩個數據傳輸之間插入一個串行時鐘的空閒等待,這樣狀態機只需兩種狀態(空閒和工作)就能正確工作。

SPI協議心得

SPI接口時鐘配置心得:
在主設備這邊配置SPI接口時鐘的時候一定要弄清楚從設備的時鐘要求,因爲主設備這邊的時鐘極性和相位都是以從設備爲基準的。因此在時鐘極性的配置上一定 要搞清楚從設備是在時鐘的上升沿還是下降沿接收數據,是在時鐘的下降沿還是上升沿輸出數據。但要注意的是,由於主設備的SDO連接從設備的SDI,從設備 的SDO連接主設備的SDI,從設備SDI接收的數據是主設備的SDO發送過來的,主設備SDI接收的數據是從設備SDO發送過來的,所以主設備這邊 SPI時鐘極性的配置(即SDO的配置)跟從設備的SDI接收數據的極性是相反的,跟從設備SDO發送數據的極性是相同的。下面這段話是Sychip Wlan8100 Module Spec上說的,充分說明了時鐘極性是如何配置的:
The 81xx module will always input data bits at the rising edge of the clock, and the host will always output data bits on the falling edge of the clock.
意思是:主設備在時鐘的下降沿發送數據,從設備在時鐘的上升沿接收數據。因此主設備這邊SPI時鐘極性應該配置爲下降沿有效。
又如,下面這段話是摘自LCD Driver IC SSD1289:
SDI is shifted into 8-bit shift register on every rising edge of SCK in the order of data bit 7, data bit 6 …… data bit 0.
意思是:從設備SSD1289在時鐘的上升沿接收數據,而且是按照從高位到地位的順序接收數據的。因此主設備的SPI時鐘極性同樣應該配置爲下降沿有效。
時鐘極性和相位配置正確後,數據才能夠被準確的發送和接收。因此應該對照從設備的SPI接口時序或者Spec文檔說明來正確配置主設備的時鐘。

posted @ 2009-02-22 22:51 陳廣強 閱讀(24) | 評論 (0) | 編輯

IIC

型號     容量      器件/業面尋址字節                   可尋址位       模塊

24C01   128B      (1010)(A2)(A1)(A0)(0或1)     3            128B
24C02   256B      (1010)(A2)(A1)(A0)(0或1)     3            256B
24C04   512B      (1010)(A2)(A1)(P0)(0或1)     2            2X256B
24C08  1024B      (1010)(A2)(P1)(P0)(0或1)     1            4X256B
24C16  2048B      (1010)(P2)(P1)(P0)(0或1)     0            8X256B


解析:IIC總線接口器件24C系列非易失性存儲器與89C51接口採用軟件模擬IIC。24C系列
存儲器器件地址統一爲1010XXXX,不要問爲什麼,這是廠家出廠的時候規定好的了。至
於24C的引腳功能和89C51的接口我就不多說了,本文的重點主要是如何應用。
  上面說了,器件的地址字節的高位是1010,那麼低4位呢?先說最後一位吧,最後一
位爲0的時候表示89C51要寫數據入存儲器,1的時候表示要從存儲器讀數據。還剩下中
三位A2,A1和A0。它們的高低電平取決於24C的A2,A1,A0是接高電平還是接地。A2,
A1 和A0有8個組合,因此可以擴展8個相同的器件,根據A2、A1、A0的不同,一樣的器件
也會有不同的地址。那麼是不是每一個24C都可以擴展8個呢?不是的。注意上表,24C01
有三個可尋址位,A2,A1,A0,所以可以擴展8個,24C02也一樣。而04則只可以擴展4個
08只可以擴展2個,16就沒有擴展了,只可以掛一片24C16。爲什麼呢?因爲訪問24C系列
除了訪問器件地址外,還要訪問器件內的字節的地址。例如24C01,要對其操作,就先選
選中它的地址,然後操作第一個字節或其他字節,這些字節也是有地址的,分模塊,用
一個字節表示,最多可以操作256個字節。24C01和24C02不大於256個字節,對其操作就
簡單得多了。但24C04,08和16呢?他們都大於256個字節,怎麼辦?分模塊。注意到上
表的P0,P1,P3沒有?把04分成兩個模塊,2X256B,08四個模塊,16就八個模塊。究竟
怎麼
模塊操作呢?拿24C08爲例,有A2 P1 P0。A2只可以0或1,所以只能擴展2個24C08,其
內有4個256字節的模塊,要操作哪個模塊取決於P1,P0的組合。例如,24C08的地址字節
爲1010000X第一個字節地址爲0,第256個地址爲255,如果地址字節是1010001X,那麼第
256個字節的地址爲0,第512個字節的地址爲255。就如此。
    再用24C08舉例說明如何擴展,當兩個24C08的A2腳分別接高電平和地的時候,就可
以了,這樣就擴展了,他們的器件地址分別是1010000X和1010100X。當要讀第一個(A2
接地)
   24C08的的第一個模塊的數據時候,單片機先發送地址字節10100001;當要把數據寫
進第二個(A2接高電平)24C08的第二個模塊的時候,應發送10101010地址字節。
    不再說了,再說我瘋了,看程序吧。這是對24C16操作的例子。*/
複製內容到剪貼板
代碼:
#include <reg51.h>
/* 全局符號定義 */
#define WRITE 0xA0                        /* 定義24C016的器件地址SLA和方向位W */
#define READ  0xA1                        /* 定義24C04的器件地址SLA和方向位R */
#define BLOCK_SIZE    100                  /* 定義指定字節個數 */
#define uchar unsigned char
#define HIGH 1
#define LOW 0
#define FALSE 0
#define TRUE ~FALSE

sbit SCL                =P3^4;  //T0        
sbit SDA                =P3^5;  //T1        

uchar xdata EAROMImage[BLOCK_SIZE]={0}; /* 在外部RAM中定義發送存儲映象單元 */


void delayi2c( void ) {
        ;
}


void I_start( void ) {
        SCL = HIGH ;
        delayi2c() ;
        SDA = LOW ;
        delayi2c() ;
        SCL = LOW ;
        delayi2c() ;
}


void I_stop( void ) {
        SDA = LOW ;
        delayi2c() ;
        SCL = HIGH ;
        delayi2c() ;
        SDA = HIGH ;
        delayi2c() ;
        SCL = LOW ;
        delayi2c() ;
}

//初始化
void I_init( void ) {
        SCL = LOW ;
        I_stop() ;
}


bit I_clock( void ) {
        bit sample ;
        SCL = HIGH ;
        delayi2c() ;
        sample = SDA ;
        SCL = LOW ;
        delayi2c() ;
        return ( sample ) ;
}


//發送8位數據
bit I_send( uchar I_data ) {
        uchar i ;
        /* 發送8位數據 */
        for ( i=0 ; i<8 ; i++ ) {
                SDA = (bit)( I_data & 0x80 ) ;
                I_data = I_data << 1 ;
                I_clock() ;
        }
        /* 請求應答信號ACK */
        SDA = HIGH ;
        return ( ~I_clock() );
  }

//接受8位數據
uchar I_receive( void ) {
        uchar I_data = 0 ;
        register uchar i ;
        for ( i=0 ; i<8 ; i++ ) {
                I_data *= 2 ;
                if (I_clock()) I_data++ ;
        }
        return ( I_data ) ;
}

//應答
void I_Ack( void ) {
        SDA = LOW;
        I_clock();
        SDA = HIGH;
}



void wait_5ms( void ) {
        int i ;
        for ( i=0 ; i<1000 ; i++ ) 
    {
                ;
        }
}

//向24C04寫入器件地址和一個指定的字節地址。
bit E_address(uchar page ,uchar Address ) 
   {
        I_start() ;
        if ( I_send( WRITE +page) )
                return ( I_send( Address ) ) ;
        else
                return ( FALSE ) ;
   }


//參數的含義:從第幾個模塊(不超過3),模塊中第幾個字節(不超過255)
//            寫到RAM映象的第幾個字節和讀的長度
bit E_read_block(uchar page, uchar addr,uchar arraypoint,uchar longth)
   {
        uchar i ;
        /* 從地址0開始讀取數據 */
        if ( E_address(page, addr ) ) {
                /* 發送重複啓動信號 */
                I_start() ;
                if ( I_send( READ+page ) ) {
                        for ( i=0; i<=longth ;i++ ) 
               {
                  EAROMImage[arraypoint+i] =I_receive();
                                if ( i != longth ) I_Ack() ;
                                else {
                                        I_clock() ;
                                        I_stop() ;
                                }
                        }
                        return ( TRUE ) ;
                }
                else {
                        I_stop() ;
                        return ( FALSE ) ;
                }
        }
        else
                I_stop() ;
                return ( FALSE ) ;
}

bit E_write_block(uchar page,uchar addr,uchar arraypoint,uchar longth) {
        uchar i ;
        for ( i=addr; i<=addr+longth ; i++ ) {
                if ( E_address(page,i) && I_send( EAROMImage[arraypoint+i-addr] ) ) {
                        I_stop() ;
                        wait_5ms();
                }
                else
                        return ( FALSE ) ;
        }
        return ( TRUE ) ;
}

//test
void  main() {
        EAROMImage[39]=0xfe;
    SCON = 0x5a;        
    TMOD = 0x20;  
    TCON = 0x69;  
    TH1 =  0xfd; 
        I_init();                        //  I2C 總線初始化 
        P1=0xFF;
        
        if (E_write_block(0,8,39,1))
                 P1=0xFE;//p10
        else
                 {}

        if (E_read_block(0,8,55,1))
                {} 
        else
                P1=P1&0xFD;
        
        if(EAROMImage[55]==0xfe) 
        P1=P1&0x0FB; 
    while(1);

}
posted @ 2009-02-22 22:41 陳廣強 閱讀(18) | 評論 (0) | 編輯

I2C(Inter-Integrated Circuit)總線是一種由PHILIPS公司開發的兩線式串行總線,用於連接微控制器及其外圍設備。I2C總線產生於在80年代,最初爲音頻和視頻設 備開發,如今主要在服務器管理中使用,其中包括單個組件狀態的通信。例如管理員可對各個組件進行查詢,以管理系統的配置或掌握組件的功能狀態,如電源和系 統風扇。可隨時監控內存、硬盤、網絡、系統溫度等多個參數,增加了系統的安全性,方便了管理。 
1 I2C總線特點 
I2C總線最主要的優點是其簡單性和有效性。由於接口直接在組件之上,因此I2C總線佔用的空間非常小,減少了電路板的空間和芯片管腳的數量,降低了互聯成本。總線的長度可高達25英尺,並且能夠以10Kbps的最大傳輸速率支持40個組件。I2C總線的另一個優點是,它支持多主控(multimastering), 其中任何能夠進行發送和接收的設備都可以成爲主總線。一個主控能夠控制信號的傳輸和時鐘頻率。當然,在任何時間點上只能有一個主控。 
2 I2C總線工作原理 
2.1 總線的構成及信號類型 
I2C總線是由數據線SDA時鐘SCL構成的串行總線,可發送和接收數據。在CPU與被控IC之間、IC與IC之間進行雙向傳送,最高傳送速率100kbps。各種被控制電路均並聯在這條總線上,但就像電話機一樣只有撥通各自的號碼才能工作,所以每個電路和模塊都有唯一的地址,在信息的傳輸過程中,I2C總線上並接的每一模塊電路既是主控器(或被控器),又是發送器(或接收器),這取決於它所要完成的功能。CPU發出的控制信號分爲地址碼和控制量兩部分,地址碼用來選址,即接通需要控制的電路,確定控制的種類;控制量決定該調整的類別(如對比度、亮度等)及需要調整的量。這樣,各控制電路雖然掛在同一條總線上,卻彼此獨立,互不相關。 
I2C總線在傳送數據過程中共有三種類型信號, 它們分別是:開始信號、結束信號和應答信號
開始信號:SCL爲高電平時,SDA由高電平向低電平跳變,開始傳送數據。
結束信號:SCL爲低電平時,SDA由低電平向高電平跳變,結束傳送數據。 
應答信號:接收數據的IC在接收到8bit數據後,向發送數 據的IC發出特定的低電平脈衝,表示已收到數據。CPU向受控單元發出一個信號後,等待受控單元發出一個應答信號,CPU接收到應答信號後,根據實際情況 作出是否繼續傳遞信號的判斷。若未收到應答信號,由判斷爲受控單元出現故障。 
目前有很多半導體集成電路上都集成了I2C接口。帶有I2C接口的單片機有:CYGNAL的 C8051F0XX系列,PHILIPSP87LPC7XX系列,MICROCHIP的PIC16C6XX系列等。很多外圍器件如存儲器、監控芯片等也提供I2C接口。

I2C總線的時鐘信號

    在I2C總線上傳送信息時的時鐘同步信號是由掛接在SCL時鐘線上的所有器件的邏輯“與”完成的。SCL線上由高電平到低電平的跳變將影響到這些器件,一旦某個器件的時鐘信號變爲低電平,將使SCL線上所有器件開始並保護低電平期。此時,低電平週期短的器件的時鐘由低至高的跳變並不影響SCL線的狀態,這些器件將進入高電平等待的狀態。

    當所有器件的時鐘信號都變爲高電平時,低電平期結 束,SCL線被釋放返回高電平,即所有的器件都同時開始它們的高電平期。其後,第一個結束高電平期的器件又將SCL線拉成低電平。這樣就在SCL線上產生 一個同步時鐘。可見,時鐘低電平時間由時鐘低電平期最長的器件決定,而時鐘高電平時間由時鐘高電平期最短的器件決定。

I2C總線的傳輸協議與數據傳送

起始和停止條件

在數據傳送過程中,必須確認數據傳送的開始和結束。在I2C總線技術規範中,開始和結束信號(也稱啓動和停止信號)的定義如圖3所示。

開始信號:當時鍾總線SCL爲高電平時,數據線SDA由高電平向低電平跳變,開始傳送數據。

結束信號:當SCL線爲高電平時,SDA線從低電平向高電平跳變,結束傳送數據。

開始和結束信號都是由主器件產生。在開始信號以後,總線即被認爲處於忙狀態,其它器件不能再產生開始信號。主器件在結束信號以後退出主器件角色,經過一段時間過,總線被認爲是空閒的。

圖3超始和停止信號圖

數據格式

    I2C總線數據傳送採用時鐘脈衝逐位串行傳送方式,在SCL的低電平期間,SDA線上高、低電平能變化,在高電平期間,SDA上數據必須保護穩定,以便接收器採樣接收,時序如圖4所示。

圖4 數據傳送時序圖

    I2C總線發送器送到SDA線上的每個字節必須爲8位長,傳送時高位在前,低位在後。與之對應,主 器件在SCL線上產生8個脈衝;第9個脈衝低電平期間,發送器釋放SDA線,接收器把SDA線拉低,以給出一個接收確認位;第9個脈衝高電平期間,發送器 收到這個確認位然後開始下一字節的傳送,下一個字節的第一個脈衝低電平期間接收器釋放SDA。每個字節需要9個脈衝,每次傳送的字節數是不受限制的。

    I2C總線的數據傳送格式是在I2C總線開始信號後,送出的第一字節數據是用來選擇從器件地址的,其中前7位爲地址碼,第8位爲方 向位(R/W)。方向位爲“0”表示發送,即主器件把信息寫到所選擇的從器件中;方向位爲“1”表示主器件將從從器件讀信息。格式如下:

1

0

1

0

A2

A1

A0

R/W

注:前四位固定爲1010。

    開始信號後,系統中的各個器件將自己的地址和主器件送到總線上的地址進行比較,如果與主器件發送到總線上的地址一致,則該器件即被主器件尋址的器件,其接收信息還是發送信息則由第8位(R/W)決定。發送完第一個字節後再開始發數據信號。

響應

    數據傳輸必須帶響應。相關的響應時鐘脈衝由主機產生,當主器件發送完一字節的數據後,接着發出對應於SCL線上的一個時鐘 (ACK)認可位,此時鐘內主器件釋放SDA線,一字節傳送結束,而從器件的響應信號將SDA線拉成低電平,使SDA在該時鐘的高電平期間爲穩定的低電 平。從器件的響應信號結束後,SDA線返回高電平,進入下一個傳送週期。

    通常被尋址的接收器在接收到的每個字節後必須產生一個響應。當從機不能響應從機地址時,從機必須使數 據線保持高電平,主機然後產生一個停止條件終止傳輸或者產生重複起始條件開始新的傳輸。如果從機接收器響應了從機地址但是在傳輸了一段時間後不能接收更多 數據字節,主機必須再一次終止傳輸。這個情況用從機在第一個字節後沒有產生響應來表示。從機使數據線保持高電平主機產生一個停止或重複起始條件。完整的數 據傳送過程如圖5所示。

圖5 完整的數據傳送過程

    I2C總線還具有廣播呼叫地址用於尋址總線上所有器件的功能。若一個器件不需要廣播呼叫尋址中所提供的任何數據,則可以忽咯該地址不作響應。如果該器件需要廣播呼叫尋址中按需提供的數據,則應對地址作出響應,其表現爲一個接收器。

 

3 總線基本操作 
I2C規程運用主/從雙向通訊。器件發送數據到總線上,則定義爲發送器,器件接收數據則定義爲接收器。主器件和從器件都 可以工作於接收和發送狀態。 總線必須由主器件(通常爲微控制器)控制,主器件產生串行時鐘(SCL)控制總線的傳輸方向,併產生起始和停止條件。SDA線上的數據狀態僅在SCL爲低 電平的期間才能改變,SCL爲高電平的期間,SDA狀態的改變被用來表示起始和停止條件。參見圖1。

圖1 串行總線上的數據傳送順序


3.1 控制字節 
在起始條件之後,必須是器件的控制字節,其中高四位爲器件類型識別符(不同的芯片類型有不同的定義,EEPROM一般應爲1010),接着三位爲片選,最後一位爲讀寫位,當爲1時爲讀操作,爲0時爲寫操作。如圖2所示。 

圖2 控制字節配置

3.2 寫操作 寫操作分爲字節寫和頁面寫兩種操作,對於頁面寫根據芯片的一次裝載的字節不同有所不同。關於頁面寫的地址、應答和數據傳送的時序參見圖3。 

圖3 頁面寫

3.3 讀操作讀操作有三種基本操作:當前地址讀、隨機讀和順序讀。圖4給出的是順序讀的時序圖。應當注意的是:最後一個讀操作的第9個時鐘週期不是“不關心”。 爲了結束讀操作,主機必須在第9個週期間發出停止條件或者在第9個時鐘週期內保持SDA爲高電平、然後發出停止條件。

圖4 順序讀

4 實例:X24C04與MCS-51單片機軟硬件的實現X24C04是XICOR公司的CMOS 4096位串行EEPROM,內部組織成512×8位。16字節頁面寫。與MCS-51單片機接口如圖5所示。由於SDA是漏極開路輸出,且可以與任何數 目的漏極開路或集電極 開路輸出“線或”(wire-Ored)連接。上拉電阻的選擇可參考X24C04的數據  手冊。下面是通過I2C接口對X24C04進行單字節寫操作的例程。流程圖及源程序如 下:                                                                                                

 

圖5 X24C04與51單片機接口

;名稱:BSENT 
;描述:寫字節 
;功能:寫一個字節 
;調用程序:無 
;輸入參數:A 
;輸出參數:無 
      BSEND: MOV R2,#08H ;1字節8位

SENDA: CLR P3.2    ; 
        RLC A              ;左移一位 
     MOV P3.3,C         ;寫一位

SETB P3.2 
DJNZ R2,SENDA      ;寫完8個字節? 
CLR P3.2           ;應答信號 
SETB P3.3 
SETB P3.2 
RET

 

圖6 流程圖

5  結束語 

 在I2C總線的應用中應注意的事項總結爲以下幾點 : 
  1) 嚴格按照時序圖的要求進行操作, 
  2) 若與口線上帶內部上拉電阻的單片機接口連接,可以不外加上拉電阻。 
  3) 程序中爲配合相應的傳輸速率,在對口線操作的指令後可用NOP指令加一定的延時。 
  4) 爲了減少意外的干擾信號將EEPROM內的數據改寫可用外部寫保護引腳(如果有),或者在EEPROM內部沒有用的空間寫入標誌字,每次上電時或復位時做一次檢測,判斷EEPROM是否被意外改寫。

                                                                      關於IIC總線的操作注意事項

1、對IIC總線的一次操作完之後,需要等待一段時間才能進行第二次操作。否則是啓動不了總線的:)
2、在時鐘線(SCL)爲高電平的時候,一定不能動數據線(SDA)狀態,除非是啓動或者結束總線

posted @ 2009-02-22 22:19 陳廣強 閱讀(14) | 評論 (0) | 編輯

      我們先來說說集電極開路輸出的結構。集電極開路輸出的結構如圖1所示,右邊的那個三極管集電極什麼都不接,所以叫做集電極開路(左邊的三極管爲反相之用, 使輸入爲"0"時,輸出也爲"0")。對於圖1,當左端的輸入爲“0”時,前面的三極管截止(即集電極C跟發射極E之間相當於斷開),所以5V電源通過 1K電阻加到右邊的三極管上,右邊的三極管導通(即相當於一個開關閉合);當左端的輸入爲“1”時,前面的三極管導通,而後面的三極管截止(相當於開關斷 開)。

  我們將圖1簡化成圖2的樣子。圖2中的開關受軟件控制,“1”時斷開,“0”時閉合。很明顯可以看出,當開關閉合時,輸出直接接地,所以輸出電平爲0。而當開關斷開時,則輸出端懸空了,即高阻態這時電平狀態未知,如果後面一個電阻負載(即使很輕的負載)到地,那麼輸出端的電平就被這個負載拉到低電平了,所以這個電路是不能輸出高電平的。 
  再看圖三。圖三中那個1K的電阻即是上拉電阻。如果開關閉合,則有電流從1K電阻及開關上流過,但由於開關閉和時電阻爲0(方便我們的 討論,實際情況中開關電阻不爲0,另外對於三極管還存在飽和壓降),所以在開關上的電壓爲0,即輸出電平爲0。如果開關斷開,則由於開關電阻爲無窮大(同 上,不考慮實際中的漏電流),所以流過的電流爲0,因此在1K電阻上的壓降也爲0,所以輸出端的電壓就是5V了,這樣就能輸出高電平了。但 是這個輸出的內阻是比較大的(即1KΩ),如果接一個電阻爲R的負載,通過分壓計算,就可以算得最後的輸出電壓爲5*R/(R+1000)伏,即5 /(1+1000/R)伏。所以,如果要達到一定的電壓的話,R就不能太小。如果R真的太小,而導致輸出電壓不夠的話,那我們只有通過減小那個1K的上拉 電阻來增加驅動能力。但是,上拉電阻又不能取得太小,因爲當開關閉合時,將產生電流,由於開關能流過的電流是有限的,因此限制了上拉電阻的取值,另外還需 要考慮到,當輸出低電平時,負載可能還會給提供一部分電流從開關流過,因此要綜合這些電流考慮來選擇合適的上拉電阻。 
  如果我們將一個讀數據用的輸入端接在輸出端,這樣就是一個IO口了(51的IO口就是這樣的結構,其中P0口內部不帶上拉,而其它三個口帶內部上拉),當我們要使用輸入功能時,只要將輸出口設置爲1即可,這樣就相當於那個開關斷開,而對於P0口來說,就是高阻態了。 
什麼是漏極開路(OD)?
  對於漏極開路(OD)輸出,跟集電極開路輸出是十分類似的。將上面的三極管換成場效應管即可。這樣集電極就變成了漏極,OC就變成了OD,原理分析是一樣的。 
  另一種輸出結構是推輓輸出。推輓輸出的結構就是把上面的上拉電阻也換成一個開關,當要輸出高電平時,上面的開關通,下面的開關斷;而要輸出低電平時,則剛好相反。比起OC或者OD來說,這樣的推輓結構高、低電平驅動能力都很強。 如果兩個輸出不同電平的輸出口接在一起的話,就會產生很大的電流,有可能將輸出口燒壞。而上面說的OC或OD輸出則不會有這樣的情況,因爲上拉電阻提供的 電流比較小。如果是推輓輸出的要設置爲高阻態時,則兩個開關必須同時斷開(或者在輸出口上使用一個傳輸門),這樣可作爲輸入狀態,AVR單片機的一些IO 口就是這種結構。



1、i2c是雙線單工總線,由一條時鐘線scl和一條數據線sda實現, 加上從機的data ready(interrupt)線的話是3條線實現。好處是需要的io口少,壞處是單工收發慢。

2、spi是四線雙工總線,加上從機的data ready(interrupt)線的話是5條線實現。好處是雙工吞吐率大,壞處是線數較多。

3、以上兩種都是非對等主從總線,需要由主機發起數據讀寫時鐘。而uart是雙工對等總線,沒有主從之分。優劣在於:

a,非對等總線可以掛載多個設備,每個設備都能收發數據。對等總線由於沒有仲裁機制,所以只能掛載兩個同時收發數據的設備,或者一個發送設備與多個接收設備,又或者自己在應用層實現仲裁(不過這就失去uart的優勢和意義了)。

b,由於在非對等總線中必須由主機發起時鐘,數據發送比對等總線要複雜得多,特別是當你想實現一些比較複雜的通信協議時,幾乎只能使用同步邏輯來實現,這樣就造成cpu的運算速度被數據總線速度嚴重限制。而uart天生就是一個異步總線,通過dma可以幾乎不佔用cpu時間。



作者:Tom Zhu
鏈接:http://www.zhihu.com/question/22079830/answer/22164383
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章