葉敬昌
(珠海格力電器股份有限公司 廣東珠海 519070)
I2C總線只要求2條雙向通信線路SDA(串行數(shù)據(jù))和SCL(串行時鐘)。每個器件都有一個唯一的地址,而且都可以作為一個發(fā)送器或接收器。如常用的存儲器既可以接收又可以發(fā)送數(shù)據(jù)。除了發(fā)送器和接收器外器件在執(zhí)行數(shù)據(jù)傳輸時也可以被看作是主機(jī)或從機(jī)。主機(jī)初始化總線的數(shù)據(jù)傳輸并產(chǎn)生允許傳輸?shù)臅r鐘信號,此時任何被尋址的器件都被認(rèn)為是從機(jī)。
I2C總線是一個多主機(jī)的總線,這就意味著可以連接多個能控制總線的器件到總線。SDA和SCL都是雙向線路,都通過一個電流源或上拉電阻連接到正的電源電壓,因此當(dāng)總線空閑時,SDA和SCL都是高電平,同時連接到總線的器件輸出級必須是漏極開路或集電極開路。I2C總線上數(shù)據(jù)的傳輸速率在標(biāo)準(zhǔn)模式下可達(dá)100kbit/s,在快速模式下可達(dá)400kbit/s,在高速模式下可達(dá)3.4Mbit/s,但總線電容不能超過400pF。
SDA為數(shù)據(jù)信號(數(shù)據(jù)口)、SCL為時鐘信號(高電平有效)。每次時鐘信號SCL有效(高電平)時,表示此時數(shù)據(jù)信號有效,從機(jī)可以讀取SDA數(shù)據(jù)信號;當(dāng)時鐘信號SCL無效(低電平)時,SDA數(shù)據(jù)信號無效,此時數(shù)據(jù)口(SDA)可以翻轉(zhuǎn)電平、改變IO口(輸入輸出翻轉(zhuǎn)等)等。見圖1。
數(shù)據(jù)通信需要有起始位(S)和結(jié)束位(P)。I2C規(guī)定:在時鐘有效時(高電平)數(shù)據(jù)口產(chǎn)生上升沿表示停止位(P位),產(chǎn)生下降沿表示開始位(S位)或重復(fù)開始(Sr位)。見圖2。
I2C規(guī)定:通信以字節(jié)為單位,即一次通信需要發(fā)送8位數(shù)據(jù),從機(jī)每收到一個字節(jié)數(shù)據(jù)后需要反饋一個低電平應(yīng)答信號ACK;若主機(jī)需要改變原來的主從關(guān)系、讀取關(guān)系,則必須由新主機(jī)產(chǎn)生一個開始位(S)或重復(fù)開始位(Sr)。下面以連續(xù)通信數(shù)據(jù)包為例解析一下I2C標(biāo)準(zhǔn)協(xié)議,見圖3。
通信開始,由主機(jī)置位數(shù)據(jù)口、時鐘口,在時鐘信號有效時,數(shù)據(jù)口產(chǎn)生一個下降沿,表示通信開始(S位)。之后在時鐘信號有效期間主機(jī)連續(xù)發(fā)送8位數(shù)據(jù),這8位數(shù)據(jù)中前7位表示選中的從機(jī)地址,第8位表示操作指令。至此主機(jī)翻轉(zhuǎn)數(shù)據(jù)口(由輸出口翻轉(zhuǎn)為輸入口),準(zhǔn)備讀取被選中的從機(jī)的應(yīng)答信號ACK。從機(jī)收到8位數(shù)據(jù)后,在下一個時鐘信號有效前(從機(jī)輸出),翻轉(zhuǎn)IO口(由輸入口翻轉(zhuǎn)為輸出口)輸出一個低電平應(yīng)答信號ACK,并輸出有效的時鐘信號給主機(jī),表示一切就緒,準(zhǔn)備好了下一字節(jié)的數(shù)據(jù)發(fā)送或接收。至此通信信道建立,以后主機(jī)可以和該選中的從機(jī)連續(xù)通信,直到主機(jī)產(chǎn)生一個停止位(P位)。
當(dāng)通信過程中需要改變通信的方向,如,主機(jī)向從機(jī)寫數(shù)據(jù)后,需要讀取從機(jī)的數(shù)據(jù),則需要在主機(jī)向從機(jī)寫完數(shù)據(jù)后,在停止位(P位)之前,再產(chǎn)生一個開始位(此S位叫Sr重復(fù)開始位)。從機(jī)接收到Sr位后釋放總線等待指令,這時主機(jī)就可以重新尋址并發(fā)送操作指令(讀或?qū)懀?。尋址過程中可以選擇不同的從機(jī)也可以選著同一個從機(jī),通信直到主機(jī)發(fā)送停止位(P位)后所有從機(jī)結(jié)束本次通信。
為了規(guī)范通信格式,I2C協(xié)議詳細(xì)規(guī)定了:高低電平保持時間、上升、下降沿斜率等時間要求及其在不同通信速率下的標(biāo)準(zhǔn)值。如:在普通模式下(100K速率以下),開始位的下降沿,必須在時鐘信號有效4uS之后產(chǎn)生才有效;在快速模式下為(400K速率)0.6uS;高速模式下(3.4M速率)為160nS。
在家電領(lǐng)域,使用到I2C協(xié)議的地方很多,如:傳感器通信、數(shù)據(jù)存儲等。但對于低成本產(chǎn)品來說,由于使用的MCU等器件受成本限制,不會含有太多片上資源,IO口復(fù)用成為這些低成本產(chǎn)品的首先,因而不依賴芯片硬件資源,通過普通IO口用軟件模擬I2C協(xié)議通信是軟件工程師必修的一門課程。
下面以MCU和記憶芯片通信為例,簡要說明一下,軟件模擬I2C的應(yīng)用及使用中的注意事項。
普通MCU和記憶芯片數(shù)據(jù)交換的通信電路,如圖4所示(為了方便說明這里以IC24C02記憶芯片為例且強(qiáng)制其地址拉地,即地址為“1010000X”,其中X代表操作指令,“0”為寫指令,“1”為讀指令)。
通信過程如下:
(1)主機(jī)(MCU)發(fā)送第一個字節(jié)A0H,表示選擇記憶芯片,操作為寫;
(2)主機(jī)讀取從機(jī)(記憶芯片)發(fā)送的應(yīng)答信號ACK;
(3)主機(jī)發(fā)送第二個字節(jié)00H,告訴記憶芯片將要操作內(nèi)部00H的存儲地址;
(4)主機(jī)讀取從機(jī)發(fā)送的應(yīng)答信號ACK;
(5)主機(jī)發(fā)送第三個字節(jié)A1H,表示選擇記憶芯片,操作為讀,(讀取的起始地址為上一字節(jié)的00H)。
(6)從機(jī)發(fā)送一個字節(jié)數(shù)據(jù)后,等待主機(jī)的應(yīng)答信號ACK;
(7)主機(jī)讀取一個字節(jié)數(shù)據(jù)后,發(fā)送應(yīng)答信號ACK給從機(jī);
(8)從機(jī)收到主機(jī)的應(yīng)答信號后,發(fā)送下一個字節(jié)數(shù)據(jù);
(9)重復(fù)(6)、(7)、(8)通信,直到通信結(jié)束,主機(jī)發(fā)送停止位P;
(10)從機(jī)收到停止位P后,結(jié)束通信。
在這個通信過程中,特別要注意主機(jī)使用軟件模擬I2C協(xié)議,讀取應(yīng)答信號ACK時需要翻轉(zhuǎn)IO口(由輸出口變?yōu)檩斎肟冢?,翻轉(zhuǎn)IO口過程中輸入、輸出寄存器必須先清零,同時需要在時鐘信號SCL無效時翻轉(zhuǎn),否則將出現(xiàn)莫名的高電平,如圖5所示。
究其原因,是主機(jī)翻轉(zhuǎn)IO口為輸入口讀取從機(jī)應(yīng)答信號后再次翻轉(zhuǎn)為輸出口準(zhǔn)備下一字節(jié)數(shù)據(jù)發(fā)送時,輸出寄存器沒有清零(輸出高電平“1”),因而,主機(jī)發(fā)送了一個莫名的高電平,經(jīng)電阻分壓后,就如圖5所示的波形。
軟件模擬I2C通信協(xié)議時,時序問題尤為重要,按照I2C標(biāo)準(zhǔn)協(xié)議,數(shù)據(jù)要在時鐘信號無效時才能改變。若在時鐘為高電平時產(chǎn)生上升沿則表示停止,產(chǎn)生下降沿表示開始(或重新開始)。
操作的流程為:開始(下降沿)——發(fā)送A0H(表示選擇記憶芯片,操作為寫)——讀取應(yīng)答信號ACK——發(fā)送00H(告訴記憶芯片將要操作內(nèi)部00H的存儲地址)——讀取應(yīng)答信號ACK——重新開始(改變操作)——發(fā)送A1H(表示選擇記憶芯片,操作為讀,讀取的起始地址為上一字節(jié)的00H)。
但在“重新開始”的操作過程中,由于時序操作不當(dāng),產(chǎn)生了一個不應(yīng)該的停止位,也就表示了前面的通信結(jié)束。將導(dǎo)致后面發(fā)送A1H,讀取操作的時候,究竟讀取記憶芯片存儲器的哪個地址?是00H開始讀還是11H開始讀?I2C協(xié)議沒有規(guī)定,將導(dǎo)致后面讀取操作失敗。如圖6所示。
反應(yīng)在源代碼上就是程序先使時鐘有效“PEEClock = 1”經(jīng)延時“nop_1()”后IO口才輸出高電平“PEEDataOut = 1”,這樣就在時鐘有效的前提下產(chǎn)生了一個上升沿,也就是停止位。
數(shù)據(jù)通信的高低電平,需要保持一定的時間,目的在于輸入方能可靠檢測到相應(yīng)的電平,這就用到了軟件上的延時,但延時并不是越長越好。如圖7所示的通信波形,將導(dǎo)致通信失敗。
主機(jī)向從機(jī)寫入一個字節(jié)數(shù)據(jù)后,從機(jī)發(fā)送應(yīng)答信號ACK(從機(jī)拉低數(shù)據(jù)口),主機(jī)讀取應(yīng)答信號后,準(zhǔn)備繼續(xù)寫下一個字節(jié)數(shù)據(jù)。但在此時,從機(jī)已經(jīng)釋放了總線,并翻轉(zhuǎn)為輸入口,SDA數(shù)據(jù)被上拉電阻拉高,而時鐘信號由于主機(jī)輸出延時過長,導(dǎo)致從機(jī)接收到了一個停止位,后面主機(jī)發(fā)送的數(shù)據(jù),從機(jī)不再響應(yīng),因此通信失敗。
I2C協(xié)議是一種靈活的、簡單易用的、占用系統(tǒng)資源少的通信協(xié)議,因而受到廣大工程師的喜好,應(yīng)用非常廣泛。即使使用片上的硬件資源實現(xiàn)I2C通信,時序上的配合、數(shù)據(jù)接收和發(fā)送,都需要和相關(guān)從機(jī)密切關(guān)聯(lián),切不可一刀切,因為各種從機(jī)對時序的要求、速率的要求均或多或少的有差別,因而不能一概而論。
使用軟件模擬I2C協(xié)議,則更需要時序上的配合,IO的翻轉(zhuǎn)、寄存器的操作、時鐘信號保持的時間等等都需要通盤考慮,多一個NOP或許將導(dǎo)致整個通信失敗。
[1]Philips.I2C Peripherals [J].Holand,2000.