日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WinCE的I2C驱动程序设计

發布時間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WinCE的I2C驱动程序设计 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 I2C 通信協議及S3C2410 芯片介紹

   I2C(Inter Integrated Circuit) 總線是1980 年由Philips 公司推出的。 I2C 總線用兩條線(SDA 和SCL )在總線和裝置之間傳遞信息,在微控制器和外部設備之間進行串行通信或在主設備和從設備之間進行雙向數據傳送。兩條通信線通過上拉電阻被拉升至+5 V 。在控制系統中的每個集成電路可以通過一個CMOS 緩沖器來讀每一條線路,也可以通過一個柵極開路的FET 管將每一條線的電平下拉。因此,對每個芯片來 說,每條線既是輸入線,又是輸出線。

  I2C 總線遵從同步串行傳輸協議,即各位串行(一位接一位)發送,由時鐘(clock )線指示讀數據(data )線的時刻。每個數據包前有一個地址,以指示由哪個器件來接收該數據。

   S3C2410 是一款基于ARM920T 的16/32 位RISC 微處理器,主要用于手持設備,擁有高性價比,低功耗等特點,也是目前市面上出現較多的嵌入式開發板的處理器之一。芯片擁有16 KB 的指令和數據緩存器,有存儲管理單元(MMU )、LCD 控制器、3 個串口、4 路DMA 、4 個時鐘定時器、8 路10 位的A/D 轉換;支持I2C 、 I2S 、SPI 、主從USB 等接口以及SD/MMC 卡。

  S3C2410 微處理器的I2C 總線可以處于下面4 種模式下:主接收模式、主發送模式、從接收模式和從發送模式。處理器對I2C 進行的操作,主要是對下面的幾個寄存器進行讀/ 寫:

  ◇ IIC 控制寄存器,IICCON (物理地址0X54000000 ,內存映射后的虛擬地址);?
   ◇ IIC 控制/ 狀態寄存器,IICSTAT (物理地址0X54000004 );?
   ◇ IIC 數據寄存器,IICDS (物理地址0X54000008 );?
   ◇ IIC 地址寄存器,IICADD (物理地址0X5400000C )。

   本設計主要是CPU 工作在主模式下與下面的I2C 接口設備進行通信。

2 Windows CE 系統驅動特點

   Windows CE.net 驅動有兩種模型:本機設備驅動程序和流接口驅動程序。本機設備驅動適于集成到基于Windows CE.net 平臺的設備。這些設備驅動程序是一些硬件所必需的,是由原始設備制造商創建的,用以驅動如鍵盤、觸摸屏、音頻設備等,往往在設備售出后就不會再更換,如通用LED 驅動、電源驅動、鍵盤驅動和顯示驅動等都是本機設備驅動。對于本機設備驅動程序,Platform Builder 提供了一些驅動程序樣本,目的是為了方便開發人員快速開發出自己的驅動程序。當Win CE 系統啟動時, 本地設備驅動程序將被加載到系統的內存中。本地驅動程序的開發分為分層驅動和單片驅動程序。分層驅動要利用微軟提供的與應用程序通信的上層,稱為模塊驅動程序層MDD (Model Device Driver )。MDD 層通過設備驅動程序接口DDI (Device Driver Interface )與應用程序通信,開發驅動程序通常不修改MDD 層,主要關心與具體硬件相關的下層,依賴平臺的設備驅動程序層 PDD (Platform Dependent Driver ), PDD 層通過設備驅動服務接口(Device Driver Service Provider Interface )直接管理硬件。流接口設備驅動程序(指可安裝的啟動程序)可以由第三方生產商提供,以支持添加到系統中的設備。Windows CE 下的設備驅動程序在與應用程序相同的保護級上工作。當系統啟動時,大多數驅動程序是由設備管理進程(DEVICE.EXE )加載的,所有這些驅動程序 將共享同一個進程地址空間。

3 I2C 總線底層驅動設計

  I2C 總線驅動是放在Windows CE 操作系統的內核下層,位于OEM Adaptation Layer (OAL )層的一個真正的驅動。

3.1 初始化I2C 中斷和編寫ISR 例程

  I2C 的通信是通過操作I2C 的寄存器進行的。在I2C 通信中主要對上面介紹的4 個寄存器進行讀寫。通過讀寫這些寄存器中的命令狀態字可以檢測和控制I2C 總線的行為。在Windows CE.net 下,首先要在文件oalintr.h 添加I2C 的中斷號的宏定義:

  #defineSYSINTR_I2C(SYSINTR_FIRMWARE+19)

然后在文件cfw.c 的文件中添加I2C 中斷的初始化,禁止和復位。具體代碼如下:

在OEMInterruptEnable 函數中加入?
   case SYSINTR_IIC:?
     s2410INT->rSRCPND=BIT_IIC;?
     if (s2410INT->rINTPND & BIT_IIC) s2410INT->rINTPND = BIT_IIC;?
     s2410INT->rINTMSK&= ~BIT_IIC;?
     break;?
   在OEMInterruptDisable 函數中加入?
   case SYSINTR_IIC:?
     s2410INT->rINTMSK|= BIT_IIC;?
       break;

在OEMInterruptDone 函數中加入?
   case SYSINTR_IIC:?
     s2410INT->rSRCPND=BIT_IIC;?
     if (s2410INT->rINTPND & BIT_IIC) s2410INT->rINTPND = BIT_IIC;?
     s2410INT->rINTMSK&= ~BIT_IIC;?
     break;

在armint.c 文件中添加ISR 程序,處理中斷發生后返回定義的中斷號。具體代碼如下:?
   在OEMInterruptHandler 函數中添加?
   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 編寫流驅動程序

   I2C 總線驅動程序采用的是Win CE 流驅動的標準形式。在IIC_Init 的函數中,首先通過函數VirtualAlloc ()和VirtualCopy (),把芯片中針對I2C 的物理 地址和操作系統的虛存空間聯系起來,對虛擬地址空間的操作就相當于對芯片的物理地址進行操作。地址映射的代碼如下:

  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 是申請虛擬地址空間的實際物理地址在Win CE 中的映射地址。?
   然后對申請到的虛擬地址進行操作,安裝Windows 中的流驅動的模型進行驅動的編寫,主要包括下面函數的編寫。

  IIC_Init ()?
   在函數中,主要是對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() 函數中, 主要是創建線程、關聯事件和中斷, 主要語句如下:?
   InterruptInitialize( 36,pIicHead->hIicEvent,NULL,0 );// 關聯時間和中斷?
   CreateThread( NULL,0,IicDispatchThread,pIicHead,0,NULL );// 創建線程等待時間?
   在IicDispatchThread() 函數中, 主要是等待中斷的產生, 然后去執行:WaitReturn =        WaitForSingleObject( pIicHead->hIicEvent,INFINITE );?
   IicEventHandler( pIicHead );// 事件處理函數?
   InterruptDone( 36 );?
   最后,在函數IIC_Open 、IIC_Read 、IIC_Write 中,對各個寄存器進行操作,進行數據的賦值, 得到I2C 讀取的數據和發送數據。

4 I2C 驅動的封裝和添加到Windows CE 中

  通過上面的工作,能編譯一個DLL 函數,但這還不能叫流接口驅動程序。因為它的接口函數還沒有導出,還需要告訴鏈接程序需要輸出什么樣的函數,為此要建立一個自己的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 ,任務是復制注冊表到Win CE 的系統目錄下面。加一個Bib File ,其主要功能是把編譯的mydrive.dll 文件添加到系統內核中去。保存寫好的CEC 文件。打開Platform Builder ,打開“File” 菜單,添加剛剛編寫的CEC 特征到系統選項中去。生成系統的時候,添加自己的CEC 特性,就可以包含剛剛編寫的I2C 驅 動了。?
以上介紹了Win CE 的驅動結構,并給出了基于Win CE 的 I2C 驅動程序部分源代碼。實驗證明該設計是可行的。

1.1???????? 初始化IIC 中斷和編寫ISR 例程

IIC 的通信是通過操作IIC 的寄存器進行的。在IIC 通信中主要對上面介紹的4 個寄存器進行讀寫。通過讀寫這些寄存器中的命令狀態字可以檢測和控制IIC 總線的行為。在Windows CE.NET 下,我們首先要在文件oalintr.h 添加IIC 的中斷號的宏定義:

#define?? SYSINTR_IIC??????? (SYSINTR_FIRMWARE+19)

然后在文件cfw.c 的文件中添加IIC 中斷的初始化,禁止和復位。

在OEMInterruptEnable 函數中,通過向中斷寄存器rSRCPND 的第27 位寫入1 表示IIC 中斷源有中斷請求產生。向中斷中斷寄存器rINTMSK 的第27 位寫入0 則將IIC 中斷標記為可處理狀態。這樣就實現了IIC 中斷的初始化。在OEMInterruptDisable 函數中,通過向中斷寄存器rINTMSK 的第27 位寫入1 實現了IIC 中斷的禁止。

IIC 驅動程序需要建立一個事件,可以使用CreateEvent 函數實現,然后調InterruptInitialize 將該事件與IIC 中斷號綁定,則使能該中斷,OAL 中的OEMInerrupteEnable 就會被調用,如果該函數不返回true 的話,InterruptInitialize 就會失敗。然后驅動程序中的IST 就可以使用WaitForSingleObject 函數來等待中斷的發生。

當一個IIC 中斷發生之后,操作系統陷入異常,中斷向量指示進入CE 的異常處理程序,該異常處理程序然后調用OAL 的OEMInterruptHandler 函數,該函數檢測硬件之后,將硬件中斷轉換為軟件的中斷號,返回給系統。該中斷號就是上面的InterruptInitialize 中使用的那個中斷號。系統得到該中斷號之后,就會找到該中斷號對應的事件,并喚醒等待相應事件的線程(IST) ,然后IST 就可以在用戶態進行中斷處理。處理完成之后,IST 需要調用InterruptDone 來告訴操作系統中斷處理結束,操作系統再次調用OAL 中的OEMInterruptDone 函數,最后完成中斷的處理。

1.2??????????? 編寫流驅動程序

本IIC 驅動程序采用的是Windows CE 流驅動的標準形式編寫,在IIC_Init 的函數中,通過函數VirtualAlloc ()和VirtualCopy (),把芯片中針對IIC 的物理地址和操作系統的虛存地址空間聯系起來,對虛擬地址空間的操作就相當于對芯片的物理地址進行操作。

然后對申請到的虛擬地址進行操作,安裝Windows 中的流驅動的模型進行驅動的編寫,主要包括下面的個幾個函數的編寫:

1 . IIC_Init( ) :對IIC 進行初始化,在設備管理器加載IIC 驅動后首先調用,用于初始化所需的變量,硬件設備等資源。該過程分配代表設備硬件實例的數據結構,并通過硬件抽象接口HWInit 初始化硬件。同時該函數會調用InterruptInitialize 為接收內核中的邏輯中斷創建相應事件并初始化臨界區。2 .StartDispatchThread( ) :主要是創建線程, 關聯事件和中斷, 主要語句如下:

InterruptInitialize( 36,pIicHead->hIicEvent,NULL,0 );// 關聯事件和中斷

CreateThread( NULL,0,IicDispatchThread,pIicHead,0,NULL );// 創建線程等待時間。

如果StartDispatchThread() 執行后返回false, 則執行 IIC_Deinit() 卸載IIC 驅動。

3 . IicDispatchThread( ) :主要是等待中斷的產生, 然后去執行

WaitReturn = WaitForSingleObject( pIicHead->hIicEvent,INFINITE );

IicEventHandler( pIicHead );???? // 事件處理函數

InterruptDone( 36 );

最后,在函數IIC_Open ,IIC_Read ,IIC_Write 中,對各個寄存器進行操作,進行數據的賦值。得到IIC 讀取的數據和發送速據。

2??????????? IIC 驅動的封裝和添加到Windows CE 中

通過上面的工作,我們能編譯一個DLL 函數,但是這個還不能叫流接口驅動程序,因為它的接口函數還沒有導出,我們還需要告訴鏈接程序需要輸出什么樣的函數,為此要建立一個自己的def 文件,可以用記事本程序編輯一個文件名為“mydrive.Def” 的文件。該文件做的工作就是在EXPORTS 段后面列出要從DLL 中輸出的函數的名稱。在LIBRARY 后面必須加上要編譯文件的實際名,然后將這個文件添加到流接口驅動程序的工程里面。

然后同樣用記事本編寫一個注冊表文件,取名為“mydrive.reg” ,并保存到流接口驅動程序的目錄里,下面是這個注冊表文件的內容。

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\STRINGS]

"Index"=dword:1

"Prefix"="IIC"

"Dll"="MyDriver.dll"

"Order"=dword:0

最后編寫自己的CEC 文件。主要任務是添加一個Build Method ,任務是copy 注冊表到Window CE 的系統目錄下面。接著添加一個Bib File ,其主要功能是把編譯的mydrive.dll 文件添加到系統內核中去。然后保存寫好的CEC 文件。打開Platform Build ,打開“File” 菜單,添加剛剛編寫的CEC 特征到系統選項中去。最后生成系統的時候,添加自己的CEC 特性,就可以包含剛剛編寫的IIC 驅動了

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/cfanlwn/archive/2009/12/04/4939786.aspx

I2C總線工作原理

  總線的構成及信號類型

  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 總線是一種用于IC器件之間連接的雙向二線制總線,所謂總線它上面可以掛多個器件,并且通過兩根線連接,占用空間非常的小,總線的長度可長達25英尺,并且能夠以10Kbps的最大傳輸速率支持4個組件。它的另一優點是多主控,只要能夠進行接收和發送的設備都可以成為主控制器,當然多個主控不能同一時間 工作。

  I2C總線有兩根信號線,一根為SDA(數據線),一根為SCL(時鐘線)。任何時候時鐘信號都是由主控器件產生。

I2C總線操作

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

  控制字節

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

  寫操作

  寫操作分為字節寫和頁面寫兩種操作,對于頁面寫根據芯片的一次裝載的字節不同有所不同。

  讀操作

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

在這里,我們可以用器件的i2c接口鏈接到i2c總線上,也可以用主控芯片的GPIO端口來模擬i2c接口。

I2C數據格式如下:
無數據:SCL=1,SDA=1;
開始位(Start):當SCL=1時,SDA由1向0跳變;
停止位(Stop):當SCL=1時,SDA由0向1跳變;
數據位:當SCL由0向1跳變時,由發送方控制SDA,此時SDA為有效數據,不可隨意改變SDA;
當SCL保持為0時,SDA上的數據可隨意改變;
地址位:定義同數據位,但只由Master發給Slave;
應答位(ACK):當發送方傳送完8位時,發送方釋放SDA,由接收方控制SDA,且SDA=0;
否應答位(NACK):當發送方傳送完8位時,發送方釋放SDA,由接收方控制SDA,且SDA=1。
當數據為單字節傳送時,格式為:
開始位,8位地址位(含1位讀寫位),應答,8位數據,應答,停止位。
當數據為一串字節傳送時,格式為:
開始位,8位地址位(含1位讀寫位),應答,8位數據,應答,8位數據,應答,……,8位數據,應答,停止位。
需要注意的是:
1,SCL一直由Master控制,SDA依照數據傳送的方向,讀數據時由Slave控制SDA,寫數據時由Master控制SDA。當8位數據傳送完畢之后,應答位或者否應答位的SDA控制權與數據位傳送時相反。
2,開始位“Start”和停止位“Stop”,只能由Master來發出。
3,地址的8位傳送完畢后,成功配置地址的Slave設備必須發送“ACK”。否則否則一定時間之后Master視為超時,將放棄數據傳送,發送“Stop”。
4,當寫數據的時候,Master每發送完8個數據位,Slave設備如果還有空間接受下一個字節應該回答“ACK”,Slave設備如果沒有空間接受更多的字節應該回答“NACK”,Master當收到“NACK”或者一定時間之后沒收到任何數據將視為超時,此時Master放棄數據傳送,發送“Stop”。
5,當讀數據的時候,Slave設備每發送完8個數據位,如果Master希望繼續讀下一個字節,Master應該回答“ACK”以提示Slave準備下一個數據,如果Master不希望讀取更多字節,Master應該回答“NACK”以提示Slave設備準備接收Stop信號。
6,當Master速度過快Slave端來不及處理時,Slave設備可以拉低SCL不放(SCL=0將發生“線與”)以阻止Master發送更多的數據。此時Master將視情況減慢或結束數據傳送。


在實際應用中,并沒有強制規定數據接收方必須對于發送的8位數據做出回應,尤其是在Master和Slave端都是用GPIO軟件模擬的方法來實現的情況下,編程者可以事先約定數據傳送的長度,不發送ACK,有時可以起到減少系統開銷的效果。

總結

以上是生活随笔為你收集整理的WinCE的I2C驱动程序设计的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。