楊文鉑,邢鵬康
(河南工業(yè)職業(yè)技術(shù)學(xué)院,南陽 473000)
I2C總線作為一種接口標準最早由Philips公司提出,因其優(yōu)良的性能在電子工業(yè)中得到了廣泛的應(yīng)用。在嵌入式Linux系統(tǒng)下,標準的I2C驅(qū)動為分層架構(gòu),由上至下依次是設(shè)備層、核心層和適配器層。這種多層架構(gòu)有效滿足了Linux下多設(shè)備、多任務(wù)并行工作的要求,但同時也使I2C設(shè)備驅(qū)動的開發(fā)變得非常復(fù)雜。本文探討了一種在I2C設(shè)備串行工作的情況下,直接在適配器層實現(xiàn)的I2C驅(qū)動方法,這將有效簡化Linux下I2C設(shè)備驅(qū)動的開發(fā)。這里基于ARM9的S3C2440芯片和2.6.30核心的嵌入式Linux系統(tǒng)平臺進行分析。
I2C設(shè)備分為主機及從機。主機即主控芯片內(nèi)的I2C適配器,它完成基本的時序控制功能,如起始、傳輸數(shù)據(jù)、停止等。從機即外圍I2C芯片,它是被主機尋址的器件,接收主機發(fā)送的命令和數(shù)據(jù),返回相應(yīng)的數(shù)據(jù)。按數(shù)據(jù)流的方向又可將I2C設(shè)備分為發(fā)送器或接收器。常用的數(shù)據(jù)傳輸模式主要有兩種:主機發(fā)送模式,此時主機為發(fā)送器,從機為接收器;主機接收模式,此時主機為接收器,從機為發(fā)送器。一個設(shè)備是發(fā)送器還是接收器,取決于實際數(shù)據(jù)流的方向。一個完整的主機讀或?qū)戇^程稱為一個消息,每一個消息都必須有一個起始信號(S)來指示其開始,起始信號由主機發(fā)出。在SCL線是高電平時SDA線從高電平向低電平切換,這個情況表示起始條件。如果一個I2C通信過程是主機多個讀寫過程的組合,則要有多個消息,需重復(fù)發(fā)出起始信號。在每個消息中,主機發(fā)出起始信號后都要接著發(fā)送從機地址字節(jié),這個字節(jié)前7位代表從設(shè)備物理地址,最低位R/W決定了數(shù)據(jù)流的方向,如果是0,表示主機寫數(shù)據(jù)到從機,1表示主機向從機讀。發(fā)送到SDA總線上的數(shù)據(jù)必須是8位,但是每次發(fā)送的字節(jié)數(shù)不受限制。數(shù)據(jù)傳輸必須帶應(yīng)答(ACK),應(yīng)答脈沖由接收器產(chǎn)生,在應(yīng)答的時鐘脈沖期間,發(fā)送器釋放SDA線。通常被尋址的接收器在接收到每個字節(jié)后,必須產(chǎn)生一個應(yīng)答,才能正常通信。最后,需要由主機發(fā)出一個停止信號,結(jié)束整個通信過程,使總線回到空閑狀態(tài),當(dāng)SCL是高電平時SDA線由低電平向高電平切換表示停止條件?;綢2C總線時序如圖1所示。
圖1 基本I 2 C總線時序
S3C2440中I2C適配器中的寄存器主要有IICDS、ICSTAT、IICCON、IICADD等。IICDS寄存器為一個8位的移位寄存器,待發(fā)的數(shù)據(jù)先送至此寄存器,在起始信號發(fā)出后,將數(shù)據(jù)逐位發(fā)送到SDA總線上。
IICSTAT為狀態(tài)寄存器,主要實現(xiàn)I2C總線的信號發(fā)生功能,如下所示。其中第6、7位是模式選擇位,可決定4種模式,分別是主機發(fā)送、主機接收、從機發(fā)送、從機接收等。第5位是一個讀寫位,在讀時如果為0表明總線空閑,如果為1表明總線正忙。如果向其寫1,則主機將會發(fā)送開始信號,如果向其寫0,則主機將發(fā)送停止信號。
模式選擇忙、停止、起始狀態(tài)輸出允許 仲裁位 從片地址狀態(tài)地址零狀態(tài)最后接收位7∶6 5 4 3 2 1 0
IICCON為一個8位寄存器,主要實現(xiàn)I2C總線的一些配置功能,如下所示。應(yīng)答設(shè)置位控制是否應(yīng)答,低4位和第6位共同決定了發(fā)送時鐘的頻率。
應(yīng)答設(shè)置發(fā)送時鐘源選擇發(fā)送/接收中斷中斷掛起標志傳輸時鐘選擇7 6 5 4 3∶0
I2C的時序及操作模式都可通過配置主機適配器的方式實現(xiàn),I2C的基本時序包括起始信號、從機地址、發(fā)送數(shù)據(jù)、讀數(shù)據(jù)、應(yīng)答信號、停止信號等。操作模式主要包括主機讀、主機寫、從機讀、從機寫等。以此為基礎(chǔ),可以通過在總線上組合傳輸起始信號、地址信號、停止信號等,來實現(xiàn)任意復(fù)雜的I2C通信功能。
操作模式:通過寫IICSTAT寄存器的高兩位操作設(shè)置。
起始信號:向IICSTAT寄存器的第5位寫1后,將會在總線上發(fā)出一個起始信號。
從機地址:這個從機地址需要在發(fā)起始信號前寫入移位寄存器IICADD中去。IICADD物理地址為0x54000008,8位,高7位保存地址,最低位R/W為讀寫控制位。
應(yīng)答信號:由接收器在接到發(fā)送器發(fā)送的地址或有效數(shù)據(jù)后發(fā)出,如果接收器配置為允許應(yīng)答,則收到數(shù)據(jù)后將自動應(yīng)答,應(yīng)答設(shè)置位在IICCON的最高位,寫1為允許應(yīng)答,寫0為禁止應(yīng)答。
主機發(fā)送數(shù)據(jù):待發(fā)送的數(shù)據(jù)需事先寫入IICDS寄存器中,當(dāng)發(fā)送條件滿足后(起始信號發(fā)出,或TX/RX中斷標志位清除后等),IICDS中的數(shù)據(jù)將自動移位發(fā)送。
主機接收數(shù)據(jù):在收到總線上的一字節(jié)數(shù)據(jù)后,將存儲于IICDS中。主機可通過查詢IICCON中的中斷標志位來確定是否接收成功一個字節(jié)。如果主機不發(fā)送應(yīng)答信號,則從機將一直處于等待狀態(tài)。數(shù)據(jù)接收完畢后如果不清除中斷掛起位,I2C通信將進入暫停狀態(tài)。
停止信號:停止信號的發(fā)出由IICSTAT寄存器的第5位清零來實現(xiàn)。
下文結(jié)合LM75傳感器采集溫度的例子具體說明這種方法在Linux下的實現(xiàn)過程。
LM75為支持I2C協(xié)議的數(shù)字式溫度傳感器,可多達8個傳感器共享一根總線,可在環(huán)境超過設(shè)定溫度時通知主控制器,測溫精度為0.5℃,轉(zhuǎn)換后的溫度值用2字節(jié)保存。LM75的溫度字節(jié)讀取時序如圖2所示。
可以在Linux底層驅(qū)動中對I2C寄存器組進行直接操作,根據(jù)LM75的時序要求組合I2C基本時序,實現(xiàn)LM75的模式設(shè)置及溫度采集功能,程序流程如圖3所示。
以下是在適配器層的部分驅(qū)動函數(shù)代碼:
圖2 LM75的溫度字節(jié)讀取時序
圖3 LM75時序的底層實現(xiàn)流程
在驅(qū)動函數(shù)完成后還要在適配器層填充一個file_operations的數(shù)據(jù)結(jié)構(gòu),由于用戶空間不能直接調(diào)用適配器層中的函數(shù),驅(qū)動函數(shù)需要映射為應(yīng)用層的函數(shù),這個數(shù)據(jù)結(jié)構(gòu)提供了驅(qū)動層函數(shù)在應(yīng)用層的函數(shù)接口。
適配器層驅(qū)動函數(shù)iic_LM75_read被映射為應(yīng)用層的接口函數(shù)read,以為應(yīng)用層所調(diào)用。按上述方法構(gòu)建的I2C驅(qū)動在Linux下以普通設(shè)備驅(qū)動的形式加載,在加載的過程執(zhí)行初始化操作,通過 MKDEV()函數(shù)創(chuàng)建主設(shè)備節(jié)點并分配設(shè)備號,通過I2C_setup_dev()函數(shù)實現(xiàn)驅(qū)動層到應(yīng)用層函數(shù)的映射。在應(yīng)用層調(diào)用適配器層驅(qū)動時,須首先用open()函數(shù)打開dev中的主設(shè)備,在open過程中配置各個I2C功能寄存器,配置輸入/輸出端口,完成后,將獲得一個設(shè)備節(jié)點fd,以此節(jié)點作為驅(qū)動接口的設(shè)備參數(shù)傳入,便可調(diào)用底層的驅(qū)動函數(shù)。
實踐證明,在嵌入式Linux環(huán)境下,適配器層直接實現(xiàn)I2C設(shè)備驅(qū)動的方法,構(gòu)造簡單,可靠性高,占用資源少,對不同設(shè)備的適應(yīng)性強,可有效提高I2C設(shè)備驅(qū)動開發(fā)的效率。
[1]I2C 總線規(guī)范[OL].[2011-01].www.zlgmcu.com/download/down.asp?ID=780.
[2]Samsung Electronics.S3C2440 32-BIT CMOS Microcontroller User's Manual Revision 1,2004.
[3]安森美半導(dǎo)體.LM75-2線串行溫度傳感器和監(jiān)視器,2006.
[4]Jonathan Corbet,Alessandro Rubini,Greg Kroah-Hartman.Linux Device Drivers[M].3rd Edition.O'Reilly,2005.
[5]李俊.嵌入式Linux設(shè)備驅(qū)動開發(fā)詳解[M].北京:人民郵電出版社,2008.