|
我第一次知道I2C總線是1995年,項(xiàng)目中用到電視機(jī)高頻頭(也叫調(diào)諧器、Tuner),能夠方便買到的高頻頭要么是飛利浦(Philips)的,要么是日系廠商的,但日系廠商聯(lián)系起來比較費(fèi)勁。Tuner其實(shí)就是通過I2C總線送控制字來改變其本振頻率(LO)選擇你需要的頻段,當(dāng)時(shí)知道I2C的鼻祖就是飛利浦半導(dǎo)體(NXP-恩智浦半導(dǎo)體的前身),也是第一次使用MC34063這顆后來如同555一樣撲街的開關(guān)穩(wěn)壓芯片,用來產(chǎn)生高頻頭所需要的12V DC。 典型的電視機(jī)調(diào)諧器,采用I2C來進(jìn)行調(diào)諧 板子上的器件之間也需要Talk 器件和器件之間的也需要溝通信息,尤其是需要MCU/DSP等對其它外設(shè)進(jìn)行控制的時(shí)候。工程界的大神們基于MCU/DSP開發(fā)了一系列的協(xié)議比如UART、USART、SPI、I2C、CAN等. . . .每種協(xié)議都有各自擅長的地方,也有其局限性,因此要做系統(tǒng)設(shè)計(jì)的硬件工程師就應(yīng)該對每種接口協(xié)議有大概的認(rèn)識(即便沒有機(jī)會吃豬肉,也要知道各種豬是如何跑的),這樣才能夠幫助你在做方案選擇的時(shí)候能夠選用最合適的協(xié)議接口方式,這也是你需要閱讀我寫的文章的原因。 在同一個(gè)PCB板子上的不同器件之間進(jìn)行通信最常用的有三種形式 - SPI、I2C和UART,上篇文章我們簡單介紹了SPI,今天就來看看I2C,我們先看一下I2C最基本的一些特性,然后再跟其它的通信協(xié)議方式進(jìn)行一下比較。 兩條通過上拉電阻吊在電源的線,上面可以掛多個(gè)器件進(jìn)行通信 簡約而不簡單的I2C總線I2C來自于英文inter–integrated circuit,有時(shí)也寫為IIC,字面意思也可以理解為IC之間進(jìn)行交流用的,跟SPI對比,I2C沒有天生的主、從之分,也就是說掛在兩根線(數(shù)據(jù)線SDA和時(shí)鐘線SCL)上的所有器件都是生而平等的。這個(gè)協(xié)議最早由飛利浦半導(dǎo)體推出來,幾年后Intel又弄了一個(gè)SMBus(系統(tǒng)管理總線)協(xié)議,其實(shí)基本跟I2C一模一樣,算是其擴(kuò)展吧,一丟丟的差別而已。 I2C總線傳輸時(shí)序 有哲學(xué)家說 - 越是看起來簡單的東西,背后處理的問題越復(fù)雜。I2C其實(shí)也是如此,雖然我們看到的是2根線能掛起一大串的器件,但就像一個(gè)沒有了老師的課堂,沒有一個(gè)好的管理機(jī)制一定會出現(xiàn)亂哄哄的局面,要讓任何兩個(gè)同學(xué)之間進(jìn)行有序地交流,沒有明確的協(xié)議是肯定會亂掉的。 最簡單的情況就是在這個(gè)系統(tǒng)中有1主1仆,但如果有多個(gè)仆(從設(shè)備)呢?如果多個(gè)“從設(shè)備”不知道哪個(gè)是“主設(shè)備”呢?如果出現(xiàn)了多個(gè)“主設(shè)備”呢?如果一個(gè)“主設(shè)備”正由“從設(shè)備”獲取數(shù)據(jù),中途由于種種原因突然掛了怎么辦呢?一個(gè)“從設(shè)備”正發(fā)著數(shù)據(jù)掛掉了怎么辦呢?一個(gè)“主設(shè)備”獲取了總線使用權(quán)用以數(shù)據(jù)的發(fā)送,在釋放使用權(quán)之前崩潰了怎么辦呢? 這種看似非常簡單的結(jié)構(gòu)其實(shí)會遭遇各種可能 在實(shí)際的運(yùn)行環(huán)境中會有各種意外導(dǎo)致系統(tǒng)出現(xiàn)問題,我們在學(xué)習(xí)使用I2C的時(shí)候一定要做到心中有數(shù) - 簡單的架構(gòu)背后有著復(fù)雜的結(jié)構(gòu)來保證這個(gè)協(xié)議的順利執(zhí)行,才能讓其成為靈活、可擴(kuò)展、魯棒、極少管腳的串行通信方案。 示波器上捕捉到的I2C總線上的數(shù)據(jù)讀取 I2C協(xié)議概要以下是I2C的主要特征:
I2C協(xié)議中數(shù)據(jù)和時(shí)鐘的時(shí)序關(guān)系
同UART和SPI相比,I2C有何優(yōu)勢?I2C的主要優(yōu)勢如下:
當(dāng)然也有一些劣勢的地方:
由此可以看到I2C比較適合復(fù)雜、多樣化、需要通信設(shè)備靈活擴(kuò)展的場景;UART比較適合單點(diǎn)對單點(diǎn)的連接,因?yàn)閁ART沒有標(biāo)準(zhǔn)的方式來尋址不同的設(shè)備或共享管腳。SPI比較適合系統(tǒng)中有一個(gè)主設(shè)備和少量的從設(shè)備,而且每一個(gè)從設(shè)備都有一個(gè)單獨(dú)的“從設(shè)備選擇”信號,當(dāng)總線上有多個(gè)設(shè)備的時(shí)候會需要更多的管腳,布線的難度也會增加,當(dāng)你需要支持多個(gè)主設(shè)備的時(shí)候,SPI用起來也會非常尷尬。 如果你需要較高的傳輸速率,使用I2C就不太合適,SPI能夠支持更高的時(shí)鐘頻率,數(shù)據(jù)負(fù)載開銷也最小。如果你想使用FPGA從頭設(shè)計(jì)串行數(shù)據(jù)傳輸,SPI和UART的底層硬件設(shè)計(jì)要簡單得多,迫不得已再用I2C。 I2C硬件電路特色 I2C的一個(gè)特性是總線上的每個(gè)器件都必須通過漏極開路(或集電極開路)輸出驅(qū)動器連接時(shí)鐘信號(縮寫為SCL)和數(shù)據(jù)信號(縮寫為SDA)。這也就意味著:
有電阻R,就會有RC 由于漏極開路輸出驅(qū)動器存在著明顯的缺點(diǎn),并不是數(shù)字IC的標(biāo)準(zhǔn)配置。電壓的變化會受到與特定節(jié)點(diǎn)相關(guān)的電容充電或放電所需的時(shí)間的限制。 SCL和SDA上的上拉電阻限制了充電的電流量 - 也就是說,我們在RC時(shí)間常數(shù)中可以更多地通過R來控制從邏輯低到邏輯高的轉(zhuǎn)換。 輸出從低到高時(shí)向電容充電 輸出從高到低時(shí)由電容放電 從這個(gè)圖可以看出從低到高的轉(zhuǎn)換比從高到低的轉(zhuǎn)換要慢很多,導(dǎo)致出現(xiàn)常見的I2C鋸齒波形: 由I2C信號線上的上拉電阻以及節(jié)點(diǎn)電容引起的上升沿變緩 下圖為示波器上捕捉到的實(shí)際的時(shí)鐘信號波形 - 采用1k?的電阻做上拉,即便最小的電容效應(yīng)(總線上只有兩個(gè)器件,且很短的PCB走線)的時(shí)候I2C時(shí)鐘信號的低到高以及高到低的變化。
上拉電阻的值如何選擇?可見,上拉電阻限制了數(shù)據(jù)傳輸?shù)淖畲髸r(shí)鐘速率。實(shí)際上,電阻和電容都有影響,我們無法控制電容,因?yàn)樗饕Q于總線上有多少器件以及這些器件之間互連的方式。那問題來了,考慮到所需的數(shù)據(jù)傳輸速率要求以及可能帶來的功耗,使用多少值的上拉電阻才最合適?較低的電阻RC時(shí)間常數(shù)也比較低,但會通過上拉電阻增加從VDD流向地的電流(只要SCL或SDA為邏輯低電平)。 官方I2C規(guī)范(第9頁)規(guī)定,在達(dá)到VDD的70%之前,電壓不被視為“邏輯高”。 RC時(shí)間常數(shù)告訴我們電壓達(dá)到最終電壓的約63%需要多長時(shí)間。 因此,為簡單起見,我們假設(shè)R×C告訴我們信號從接地電壓附近上升到邏輯高電壓需要多長時(shí)間。 如何計(jì)算電容呢? 比較可行的方法是查找總線上每個(gè)器件的引腳電容進(jìn)行粗略估計(jì),然后再添加每英寸PCB走線3pF和每英尺同軸電纜30pF。 假設(shè)我們有50pF的總線電容,按照I2C“標(biāo)準(zhǔn)模式”規(guī)范規(guī)定 - 最大上升時(shí)間為1000ns。
也就是說上拉電阻可以定為20kΩ,這個(gè)值的功耗也比較低,速度如何呢?假設(shè)你希望時(shí)鐘高的時(shí)間至少是上升時(shí)間的三倍。
如果167 kHz不夠快,您可以降低電阻(以增加功耗為代價(jià)),直到達(dá)到所需的時(shí)鐘速度。 (實(shí)際上,“標(biāo)準(zhǔn)模式”將時(shí)鐘速度限制為100 kHz,但可以根據(jù)系統(tǒng)需要調(diào)整這些規(guī)格。) 當(dāng)然,這只是粗略的計(jì)算,具體的應(yīng)用中要根據(jù)掛在總線上的器件的數(shù)量以及電路設(shè)計(jì)來進(jìn)行估算,還可以配合示波器上實(shí)際的測量進(jìn)行調(diào)整,以滿足系統(tǒng)的綜合要求。 典型的數(shù)據(jù)傳輸下面的時(shí)序圖為一個(gè)典型的I2C傳輸時(shí)序。
可以看到以下幾點(diǎn):
以下為I2C數(shù)據(jù)傳輸?shù)捻樞颍?/p>
傳輸多少字節(jié)?每次傳輸都是以同樣的方式開始:起始位、地址、讀/寫、ACK/NACK。 之后,任何數(shù)量的字節(jié)都可以從“主設(shè)備”發(fā)送到“從設(shè)備”或從“從設(shè)備”發(fā)送到”主設(shè)備“,每個(gè)字節(jié)后跟ACK或NACK。 NACK可以用來表示“停止發(fā)送數(shù)據(jù)!”。例如,“主設(shè)備”可能希望從“從設(shè)備”(例如溫度傳感器)接收連續(xù)的數(shù)據(jù)流,每個(gè)字節(jié)后面都會有ACK,如果“主設(shè)備”需要處理其它事情,它可以用NACK告知”從設(shè)備“并在它準(zhǔn)備就緒時(shí)再開始新的傳輸。
由于篇幅限制,在此我們不做更詳細(xì)的介紹,有興趣的朋友可以閱讀Wikipedia中關(guān)于I2C的介紹以及該詞條下面的參考文章。對該總線的使用以及技術(shù)細(xì)節(jié)有一定程度的了解會幫助我們在實(shí)際的設(shè)計(jì)中更加有效地完成數(shù)據(jù)的傳輸設(shè)計(jì)以及有可能的問題定位。 一個(gè)應(yīng)用舉例 - 下面是我們用小腳丫FPGA做的計(jì)算器,我們通過FPGA邏輯實(shí)現(xiàn)了I2C的主控制功能,來操作掛在I2C總線上的觸摸按鍵控制器、掛在SPI總線上的LCD顯示屏。
小腳丫FPGA做成的計(jì)算器
計(jì)算器的功能框圖,3顆觸摸控制器掛在I2C總線上 |
|
|