WinCE的I2C驱动程序设计
1 I2C 通信協(xié)議及S3C2410 芯片介紹
I2C(Inter Integrated Circuit) 總線是1980 年由Philips 公司推出的。 I2C 總線用兩條線(SDA 和SCL )在總線和裝置之間傳遞信息,在微控制器和外部設(shè)備之間進行串行通信或在主設(shè)備和從設(shè)備之間進行雙向數(shù)據(jù)傳送。兩條通信線通過上拉電阻被拉升至+5 V 。在控制系統(tǒng)中的每個集成電路可以通過一個CMOS 緩沖器來讀每一條線路,也可以通過一個柵極開路的FET 管將每一條線的電平下拉。因此,對每個芯片來 說,每條線既是輸入線,又是輸出線。
I2C 總線遵從同步串行傳輸協(xié)議,即各位串行(一位接一位)發(fā)送,由時鐘(clock )線指示讀數(shù)據(jù)(data )線的時刻。每個數(shù)據(jù)包前有一個地址,以指示由哪個器件來接收該數(shù)據(jù)。
S3C2410 是一款基于ARM920T 的16/32 位RISC 微處理器,主要用于手持設(shè)備,擁有高性價比,低功耗等特點,也是目前市面上出現(xiàn)較多的嵌入式開發(fā)板的處理器之一。芯片擁有16 KB 的指令和數(shù)據(jù)緩存器,有存儲管理單元(MMU )、LCD 控制器、3 個串口、4 路DMA 、4 個時鐘定時器、8 路10 位的A/D 轉(zhuǎn)換;支持I2C 、 I2S 、SPI 、主從USB 等接口以及SD/MMC 卡。
S3C2410 微處理器的I2C 總線可以處于下面4 種模式下:主接收模式、主發(fā)送模式、從接收模式和從發(fā)送模式。處理器對I2C 進行的操作,主要是對下面的幾個寄存器進行讀/ 寫:
◇ IIC 控制寄存器,IICCON (物理地址0X54000000 ,內(nèi)存映射后的虛擬地址);?
◇ IIC 控制/ 狀態(tài)寄存器,IICSTAT (物理地址0X54000004 );?
◇ IIC 數(shù)據(jù)寄存器,IICDS (物理地址0X54000008 );?
◇ IIC 地址寄存器,IICADD (物理地址0X5400000C )。
本設(shè)計主要是CPU 工作在主模式下與下面的I2C 接口設(shè)備進行通信。
2 Windows CE 系統(tǒng)驅(qū)動特點
Windows CE.net 驅(qū)動有兩種模型:本機設(shè)備驅(qū)動程序和流接口驅(qū)動程序。本機設(shè)備驅(qū)動適于集成到基于Windows CE.net 平臺的設(shè)備。這些設(shè)備驅(qū)動程序是一些硬件所必需的,是由原始設(shè)備制造商創(chuàng)建的,用以驅(qū)動如鍵盤、觸摸屏、音頻設(shè)備等,往往在設(shè)備售出后就不會再更換,如通用LED 驅(qū)動、電源驅(qū)動、鍵盤驅(qū)動和顯示驅(qū)動等都是本機設(shè)備驅(qū)動。對于本機設(shè)備驅(qū)動程序,Platform Builder 提供了一些驅(qū)動程序樣本,目的是為了方便開發(fā)人員快速開發(fā)出自己的驅(qū)動程序。當(dāng)Win CE 系統(tǒng)啟動時, 本地設(shè)備驅(qū)動程序?qū)⒈患虞d到系統(tǒng)的內(nèi)存中。本地驅(qū)動程序的開發(fā)分為分層驅(qū)動和單片驅(qū)動程序。分層驅(qū)動要利用微軟提供的與應(yīng)用程序通信的上層,稱為模塊驅(qū)動程序?qū)覯DD (Model Device Driver )。MDD 層通過設(shè)備驅(qū)動程序接口DDI (Device Driver Interface )與應(yīng)用程序通信,開發(fā)驅(qū)動程序通常不修改MDD 層,主要關(guān)心與具體硬件相關(guān)的下層,依賴平臺的設(shè)備驅(qū)動程序?qū)?PDD (Platform Dependent Driver ), PDD 層通過設(shè)備驅(qū)動服務(wù)接口(Device Driver Service Provider Interface )直接管理硬件。流接口設(shè)備驅(qū)動程序(指可安裝的啟動程序)可以由第三方生產(chǎn)商提供,以支持添加到系統(tǒng)中的設(shè)備。Windows CE 下的設(shè)備驅(qū)動程序在與應(yīng)用程序相同的保護級上工作。當(dāng)系統(tǒng)啟動時,大多數(shù)驅(qū)動程序是由設(shè)備管理進程(DEVICE.EXE )加載的,所有這些驅(qū)動程序 將共享同一個進程地址空間。
3 I2C 總線底層驅(qū)動設(shè)計
I2C 總線驅(qū)動是放在Windows CE 操作系統(tǒng)的內(nèi)核下層,位于OEM Adaptation Layer (OAL )層的一個真正的驅(qū)動。
3.1 初始化I2C 中斷和編寫ISR 例程
I2C 的通信是通過操作I2C 的寄存器進行的。在I2C 通信中主要對上面介紹的4 個寄存器進行讀寫。通過讀寫這些寄存器中的命令狀態(tài)字可以檢測和控制I2C 總線的行為。在Windows CE.net 下,首先要在文件oalintr.h 添加I2C 的中斷號的宏定義:
#defineSYSINTR_I2C(SYSINTR_FIRMWARE+19)
然后在文件cfw.c 的文件中添加I2C 中斷的初始化,禁止和復(fù)位。具體代碼如下:
在OEMInterruptEnable 函數(shù)中加入?
case SYSINTR_IIC:?
s2410INT->rSRCPND=BIT_IIC;?
if (s2410INT->rINTPND & BIT_IIC) s2410INT->rINTPND = BIT_IIC;?
s2410INT->rINTMSK&= ~BIT_IIC;?
break;?
在OEMInterruptDisable 函數(shù)中加入?
case SYSINTR_IIC:?
s2410INT->rINTMSK|= BIT_IIC;?
break;
在OEMInterruptDone 函數(shù)中加入?
case SYSINTR_IIC:?
s2410INT->rSRCPND=BIT_IIC;?
if (s2410INT->rINTPND & BIT_IIC) s2410INT->rINTPND = BIT_IIC;?
s2410INT->rINTMSK&= ~BIT_IIC;?
break;
在armint.c 文件中添加ISR 程序,處理中斷發(fā)生后返回定義的中斷號。具體代碼如下:?
在OEMInterruptHandler 函數(shù)中添加?
else if (IntPendVal == INTSRC_IIC) {?
s2410INT->rSRCPND= BIT_IIC; /* 清除中斷 */?
if (s2410INT->rINTPND & BIT_IIC) s2410INT->rINTPND= BIT_IIC;?
s2410INT->rINTMSK|= BIT_IIC; /* I2C 中斷禁止 */?
return (SYSINTR_RTC_ALARM);?
}
3.2 編寫流驅(qū)動程序
I2C 總線驅(qū)動程序采用的是Win CE 流驅(qū)動的標(biāo)準(zhǔn)形式。在IIC_Init 的函數(shù)中,首先通過函數(shù)VirtualAlloc ()和VirtualCopy (),把芯片中針對I2C 的物理 地址和操作系統(tǒng)的虛存空間聯(lián)系起來,對虛擬地址空間的操作就相當(dāng)于對芯片的物理地址進行操作。地址映射的代碼如下:
reg = (PVOID)VirtualAlloc(0, sz, MEM_RESERVE, PAGE_NOACCESS);?
if (reg) {?
if (!VirtualCopy(reg, addr, sz, PAGE_READWRITE | PAGE_NOCACHE )) {?
RETAILMSG( DEBUGMODE,( TEXT( "Initializing interrupt?\\n\\r" ) ) );?
VirtualFree(reg, sz, MEM_RELEASE);?
reg = NULL;?
}?
}
其中sz 是申請的長度,addr 是申請?zhí)摂M地址空間的實際物理地址在Win CE 中的映射地址。?
然后對申請到的虛擬地址進行操作,安裝Windows 中的流驅(qū)動的模型進行驅(qū)動的編寫,主要包括下面函數(shù)的編寫。
IIC_Init ()?
在函數(shù)中,主要是對I2C 的初始化,主要語句如下:?
v_pIICregs = ( volatile IICreg *)IIC_RegAlloc((PVOID)IIC_BASE, sizeof(IICreg));?
v_pIOPregs = ( volatile IOPreg *)IOP_RegAlloc((PVOID)IOP_BASE, sizeof(IOPreg));?
v_pIOPregs->rGPEUP|= 0xc000;?
v_pIOPregs->rGPECON |= 0xa00000;?
v_pIICregs->rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);?
v_pIICregs->rIICADD= 0x10;?
v_pIICregs->rIICSTAT = 0x10;?
VirtualFree( ( PVOID )v_pIOPregs,sizeof( IOPreg ),MEM_RELEASE );?
v_pIOPregs = NULL;?
if ( !StartDispatchThread( pIIcHead) )?
{ IIC_Deinit( pIIcHead );return ( NULL );} 在StartDispatchThread() 函數(shù)中, 主要是創(chuàng)建線程、關(guān)聯(lián)事件和中斷, 主要語句如下:?
InterruptInitialize( 36,pIicHead->hIicEvent,NULL,0 );// 關(guān)聯(lián)時間和中斷?
CreateThread( NULL,0,IicDispatchThread,pIicHead,0,NULL );// 創(chuàng)建線程等待時間?
在IicDispatchThread() 函數(shù)中, 主要是等待中斷的產(chǎn)生, 然后去執(zhí)行:WaitReturn = WaitForSingleObject( pIicHead->hIicEvent,INFINITE );?
IicEventHandler( pIicHead );// 事件處理函數(shù)?
InterruptDone( 36 );?
最后,在函數(shù)IIC_Open 、IIC_Read 、IIC_Write 中,對各個寄存器進行操作,進行數(shù)據(jù)的賦值, 得到I2C 讀取的數(shù)據(jù)和發(fā)送數(shù)據(jù)。
4 I2C 驅(qū)動的封裝和添加到Windows CE 中
通過上面的工作,能編譯一個DLL 函數(shù),但這還不能叫流接口驅(qū)動程序。因為它的接口函數(shù)還沒有導(dǎo)出,還需要告訴鏈接程序需要輸出什么樣的函數(shù),為此要建立一個自己的def 文件,可以用記事本建一個,取名mydrive.Def :
LIBRARY MyDriver?
EXPORTS?
IIC_Close?
IIC_Deinit?
IIC_Init?
IIC_IOControl?
IIC_Open?
IIC_PowerDown?
IIC_PowerUp?
IIC_Read?
IIC_Seek?
IIC_Write
然后同樣用記事本編寫一個注冊表文件,取名為mydrive.reg:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\STRINGS]?
"Index"=dword:1?
"Prefix"="IIC"?
"Dll"="MyDriver.dll"?
"Order"=dword:0
最后編寫自己的CEC 文件。主要是添加一個Build Method ,任務(wù)是復(fù)制注冊表到Win CE 的系統(tǒng)目錄下面。加一個Bib File ,其主要功能是把編譯的mydrive.dll 文件添加到系統(tǒng)內(nèi)核中去。保存寫好的CEC 文件。打開Platform Builder ,打開“File” 菜單,添加剛剛編寫的CEC 特征到系統(tǒng)選項中去。生成系統(tǒng)的時候,添加自己的CEC 特性,就可以包含剛剛編寫的I2C 驅(qū) 動了。?
以上介紹了Win CE 的驅(qū)動結(jié)構(gòu),并給出了基于Win CE 的 I2C 驅(qū)動程序部分源代碼。實驗證明該設(shè)計是可行的。
1.1???????? 初始化IIC 中斷和編寫ISR 例程
IIC 的通信是通過操作IIC 的寄存器進行的。在IIC 通信中主要對上面介紹的4 個寄存器進行讀寫。通過讀寫這些寄存器中的命令狀態(tài)字可以檢測和控制IIC 總線的行為。在Windows CE.NET 下,我們首先要在文件oalintr.h 添加IIC 的中斷號的宏定義:
#define?? SYSINTR_IIC??????? (SYSINTR_FIRMWARE+19)
然后在文件cfw.c 的文件中添加IIC 中斷的初始化,禁止和復(fù)位。
在OEMInterruptEnable 函數(shù)中,通過向中斷寄存器rSRCPND 的第27 位寫入1 表示IIC 中斷源有中斷請求產(chǎn)生。向中斷中斷寄存器rINTMSK 的第27 位寫入0 則將IIC 中斷標(biāo)記為可處理狀態(tài)。這樣就實現(xiàn)了IIC 中斷的初始化。在OEMInterruptDisable 函數(shù)中,通過向中斷寄存器rINTMSK 的第27 位寫入1 實現(xiàn)了IIC 中斷的禁止。
IIC 驅(qū)動程序需要建立一個事件,可以使用CreateEvent 函數(shù)實現(xiàn),然后調(diào)InterruptInitialize 將該事件與IIC 中斷號綁定,則使能該中斷,OAL 中的OEMInerrupteEnable 就會被調(diào)用,如果該函數(shù)不返回true 的話,InterruptInitialize 就會失敗。然后驅(qū)動程序中的IST 就可以使用WaitForSingleObject 函數(shù)來等待中斷的發(fā)生。
當(dāng)一個IIC 中斷發(fā)生之后,操作系統(tǒng)陷入異常,中斷向量指示進入CE 的異常處理程序,該異常處理程序然后調(diào)用OAL 的OEMInterruptHandler 函數(shù),該函數(shù)檢測硬件之后,將硬件中斷轉(zhuǎn)換為軟件的中斷號,返回給系統(tǒng)。該中斷號就是上面的InterruptInitialize 中使用的那個中斷號。系統(tǒng)得到該中斷號之后,就會找到該中斷號對應(yīng)的事件,并喚醒等待相應(yīng)事件的線程(IST) ,然后IST 就可以在用戶態(tài)進行中斷處理。處理完成之后,IST 需要調(diào)用InterruptDone 來告訴操作系統(tǒng)中斷處理結(jié)束,操作系統(tǒng)再次調(diào)用OAL 中的OEMInterruptDone 函數(shù),最后完成中斷的處理。
1.2??????????? 編寫流驅(qū)動程序
本IIC 驅(qū)動程序采用的是Windows CE 流驅(qū)動的標(biāo)準(zhǔn)形式編寫,在IIC_Init 的函數(shù)中,通過函數(shù)VirtualAlloc ()和VirtualCopy (),把芯片中針對IIC 的物理地址和操作系統(tǒng)的虛存地址空間聯(lián)系起來,對虛擬地址空間的操作就相當(dāng)于對芯片的物理地址進行操作。
然后對申請到的虛擬地址進行操作,安裝Windows 中的流驅(qū)動的模型進行驅(qū)動的編寫,主要包括下面的個幾個函數(shù)的編寫:
1 . IIC_Init( ) :對IIC 進行初始化,在設(shè)備管理器加載IIC 驅(qū)動后首先調(diào)用,用于初始化所需的變量,硬件設(shè)備等資源。該過程分配代表設(shè)備硬件實例的數(shù)據(jù)結(jié)構(gòu),并通過硬件抽象接口HWInit 初始化硬件。同時該函數(shù)會調(diào)用InterruptInitialize 為接收內(nèi)核中的邏輯中斷創(chuàng)建相應(yīng)事件并初始化臨界區(qū)。2 .StartDispatchThread( ) :主要是創(chuàng)建線程, 關(guān)聯(lián)事件和中斷, 主要語句如下:
InterruptInitialize( 36,pIicHead->hIicEvent,NULL,0 );// 關(guān)聯(lián)事件和中斷
CreateThread( NULL,0,IicDispatchThread,pIicHead,0,NULL );// 創(chuàng)建線程等待時間。
如果StartDispatchThread() 執(zhí)行后返回false, 則執(zhí)行 IIC_Deinit() 卸載IIC 驅(qū)動。
3 . IicDispatchThread( ) :主要是等待中斷的產(chǎn)生, 然后去執(zhí)行
WaitReturn = WaitForSingleObject( pIicHead->hIicEvent,INFINITE );
IicEventHandler( pIicHead );???? // 事件處理函數(shù)
InterruptDone( 36 );
最后,在函數(shù)IIC_Open ,IIC_Read ,IIC_Write 中,對各個寄存器進行操作,進行數(shù)據(jù)的賦值。得到IIC 讀取的數(shù)據(jù)和發(fā)送速據(jù)。
2??????????? IIC 驅(qū)動的封裝和添加到Windows CE 中
通過上面的工作,我們能編譯一個DLL 函數(shù),但是這個還不能叫流接口驅(qū)動程序,因為它的接口函數(shù)還沒有導(dǎo)出,我們還需要告訴鏈接程序需要輸出什么樣的函數(shù),為此要建立一個自己的def 文件,可以用記事本程序編輯一個文件名為“mydrive.Def” 的文件。該文件做的工作就是在EXPORTS 段后面列出要從DLL 中輸出的函數(shù)的名稱。在LIBRARY 后面必須加上要編譯文件的實際名,然后將這個文件添加到流接口驅(qū)動程序的工程里面。
然后同樣用記事本編寫一個注冊表文件,取名為“mydrive.reg” ,并保存到流接口驅(qū)動程序的目錄里,下面是這個注冊表文件的內(nèi)容。
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\STRINGS]
"Index"=dword:1
"Prefix"="IIC"
"Dll"="MyDriver.dll"
"Order"=dword:0
最后編寫自己的CEC 文件。主要任務(wù)是添加一個Build Method ,任務(wù)是copy 注冊表到Window CE 的系統(tǒng)目錄下面。接著添加一個Bib File ,其主要功能是把編譯的mydrive.dll 文件添加到系統(tǒng)內(nèi)核中去。然后保存寫好的CEC 文件。打開Platform Build ,打開“File” 菜單,添加剛剛編寫的CEC 特征到系統(tǒng)選項中去。最后生成系統(tǒng)的時候,添加自己的CEC 特性,就可以包含剛剛編寫的IIC 驅(qū)動了
本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/cfanlwn/archive/2009/12/04/4939786.aspx
I2C總線工作原理
總線的構(gòu)成及信號類型
I2C總線是由數(shù)據(jù)線SDA和時鐘SCL構(gòu)成的串行總線,可發(fā)送和接收數(shù)據(jù)。在CPU與被控IC之間、IC與IC之間進行雙向傳送,最高傳送速率100kbps。各種被控制電路均并聯(lián)在這條總線上,但就像電話機一樣只有撥通各自的號碼才能工作,所以每個電路和模塊都有唯一的地址,在信息的傳輸過程中,I2C總線上并接的每一模塊電路既是主控器(或被控器),又是發(fā)送器(或接收器),這取決于它所要完成的功能。CPU發(fā)出的控制信號分為地址碼和控制量兩部分,地址碼用來選址,即接通需要控制的電路,確定控制的種類;控制量決定該調(diào)整的類別(如對比度、亮度等)及需要調(diào)整的量。這樣,各控制電路雖然掛在同一條總線上,卻彼此獨立,互不相關(guān)。
I2C總線在傳送數(shù)據(jù)過程中共有三種類型信號, 它們分別是:開始信號、結(jié)束信號和應(yīng)答信號。
開始信號:SCL為高電平時,SDA由高電平向低電平跳變,開始傳送數(shù)據(jù)。
結(jié)束信號:SCL為高電平時,SDA由低電平向高電平跳變,結(jié)束傳送數(shù)據(jù)。
應(yīng)答信號:接收數(shù)據(jù)的IC在接收到8bit數(shù)據(jù)后,向發(fā)送數(shù)據(jù)的IC發(fā)出特定的低電平脈沖,表示已收到數(shù)據(jù)。CPU向受控單元發(fā)出一個信號后,等待受控單元發(fā)出一個應(yīng)答信號,CPU接收到應(yīng)答信號后,根據(jù)實際情況作出是否繼續(xù)傳遞信號的判斷。若未收到應(yīng)答信號,由判斷為受控單元出現(xiàn)故障。
這些信號中,起始信號是必需的,結(jié)束信號和應(yīng)答信號,都可以不要。
目前有很多半導(dǎo)體集成電路上都集成了I2C接口。帶有I2C接口的單片機有:CYGNAL的 C8051F0XX系列,PHILIPSP87LPC7XX系列,MICROCHIP的PIC16C6XX系列等。很多外圍器件如存儲器、監(jiān)控芯片等也提供I2C接口
I2C 總線是一種用于IC器件之間連接的雙向二線制總線,所謂總線它上面可以掛多個器件,并且通過兩根線連接,占用空間非常的小,總線的長度可長達25英尺,并且能夠以10Kbps的最大傳輸速率支持4個組件。它的另一優(yōu)點是多主控,只要能夠進行接收和發(fā)送的設(shè)備都可以成為主控制器,當(dāng)然多個主控不能同一時間 工作。
I2C總線有兩根信號線,一根為SDA(數(shù)據(jù)線),一根為SCL(時鐘線)。任何時候時鐘信號都是由主控器件產(chǎn)生。
I2C總線操作
I2C規(guī)程運用主/從雙向通訊。器件發(fā)送數(shù)據(jù)到總線上,則定義為發(fā)送器,器件接收數(shù)據(jù)則定義為接收器。主器件和從器件都可以工作于接收和發(fā)送狀態(tài)。 總線必須由主器件(通常為微控制器)控制,主器件產(chǎn)生串行時鐘(SCL)控制總線的傳輸方向,并產(chǎn)生起始和停止條件。SDA線上的數(shù)據(jù)狀態(tài)僅在SCL為低電平的期間才能改變,SCL為高電平的期間,SDA狀態(tài)的改變被用來表示起始和停止條件。
控制字節(jié)
在起始條件之后,必須是器件的控制字節(jié),其中高四位為器件類型識別符(不同的芯片類型有不同的定義,EEPROM一般應(yīng)為1010),接著三位為片選,最后一位為讀寫位,當(dāng)為1時為讀操作,為0時為寫操作。
寫操作
寫操作分為字節(jié)寫和頁面寫兩種操作,對于頁面寫根據(jù)芯片的一次裝載的字節(jié)不同有所不同。
讀操作
讀操作有三種基本操作:當(dāng)前地址讀、隨機讀和順序讀。圖4給出的是順序讀的時序圖。應(yīng)當(dāng)注意的是:最后一個讀操作的第9個時鐘周期不是“不關(guān)心”。為了結(jié)束讀操作,主機必須在第9個周期間發(fā)出停止條件或者在第9個時鐘周期內(nèi)保持SDA為高電平、然后發(fā)出停止條件。
在這里,我們可以用器件的i2c接口鏈接到i2c總線上,也可以用主控芯片的GPIO端口來模擬i2c接口。
I2C數(shù)據(jù)格式如下:
無數(shù)據(jù):SCL=1,SDA=1;
開始位(Start):當(dāng)SCL=1時,SDA由1向0跳變;
停止位(Stop):當(dāng)SCL=1時,SDA由0向1跳變;
數(shù)據(jù)位:當(dāng)SCL由0向1跳變時,由發(fā)送方控制SDA,此時SDA為有效數(shù)據(jù),不可隨意改變SDA;
當(dāng)SCL保持為0時,SDA上的數(shù)據(jù)可隨意改變;
地址位:定義同數(shù)據(jù)位,但只由Master發(fā)給Slave;
應(yīng)答位(ACK):當(dāng)發(fā)送方傳送完8位時,發(fā)送方釋放SDA,由接收方控制SDA,且SDA=0;
否應(yīng)答位(NACK):當(dāng)發(fā)送方傳送完8位時,發(fā)送方釋放SDA,由接收方控制SDA,且SDA=1。
當(dāng)數(shù)據(jù)為單字節(jié)傳送時,格式為:
開始位,8位地址位(含1位讀寫位),應(yīng)答,8位數(shù)據(jù),應(yīng)答,停止位。
當(dāng)數(shù)據(jù)為一串字節(jié)傳送時,格式為:
開始位,8位地址位(含1位讀寫位),應(yīng)答,8位數(shù)據(jù),應(yīng)答,8位數(shù)據(jù),應(yīng)答,……,8位數(shù)據(jù),應(yīng)答,停止位。
需要注意的是:
1,SCL一直由Master控制,SDA依照數(shù)據(jù)傳送的方向,讀數(shù)據(jù)時由Slave控制SDA,寫數(shù)據(jù)時由Master控制SDA。當(dāng)8位數(shù)據(jù)傳送完畢之后,應(yīng)答位或者否應(yīng)答位的SDA控制權(quán)與數(shù)據(jù)位傳送時相反。
2,開始位“Start”和停止位“Stop”,只能由Master來發(fā)出。
3,地址的8位傳送完畢后,成功配置地址的Slave設(shè)備必須發(fā)送“ACK”。否則否則一定時間之后Master視為超時,將放棄數(shù)據(jù)傳送,發(fā)送“Stop”。
4,當(dāng)寫數(shù)據(jù)的時候,Master每發(fā)送完8個數(shù)據(jù)位,Slave設(shè)備如果還有空間接受下一個字節(jié)應(yīng)該回答“ACK”,Slave設(shè)備如果沒有空間接受更多的字節(jié)應(yīng)該回答“NACK”,Master當(dāng)收到“NACK”或者一定時間之后沒收到任何數(shù)據(jù)將視為超時,此時Master放棄數(shù)據(jù)傳送,發(fā)送“Stop”。
5,當(dāng)讀數(shù)據(jù)的時候,Slave設(shè)備每發(fā)送完8個數(shù)據(jù)位,如果Master希望繼續(xù)讀下一個字節(jié),Master應(yīng)該回答“ACK”以提示Slave準(zhǔn)備下一個數(shù)據(jù),如果Master不希望讀取更多字節(jié),Master應(yīng)該回答“NACK”以提示Slave設(shè)備準(zhǔn)備接收Stop信號。
6,當(dāng)Master速度過快Slave端來不及處理時,Slave設(shè)備可以拉低SCL不放(SCL=0將發(fā)生“線與”)以阻止Master發(fā)送更多的數(shù)據(jù)。此時Master將視情況減慢或結(jié)束數(shù)據(jù)傳送。
在實際應(yīng)用中,并沒有強制規(guī)定數(shù)據(jù)接收方必須對于發(fā)送的8位數(shù)據(jù)做出回應(yīng),尤其是在Master和Slave端都是用GPIO軟件模擬的方法來實現(xiàn)的情況下,編程者可以事先約定數(shù)據(jù)傳送的長度,不發(fā)送ACK,有時可以起到減少系統(tǒng)開銷的效果。
總結(jié)
以上是生活随笔為你收集整理的WinCE的I2C驱动程序设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “第二大脑”来了 新一代苹果CarPla
- 下一篇: 苹果iOS 16正式发布 网友吐槽:安卓