首先是wince驅(qū)動的分類問題。按照書上講的說CE下驅(qū)動分成單體驅(qū)動和分層驅(qū)動,而看到另一種說法是本機驅(qū)動和流式驅(qū)動。經(jīng)過microsun大哥的指點,把這兩種分類法分開了。在這里引用一下:
“單體與分層只是從代碼的形式上做的分類.分層驅(qū)動代碼上分為PDD與MDD,一般的微軟已經(jīng)實現(xiàn)了MDD,可能也實現(xiàn)了PDD,我們只需要對PDD做些修改就能使用,比如音頻的驅(qū)動,顯示的驅(qū)動。單層驅(qū)動是把PDD與MDD寫在一起,沒有做嚴(yán)格的區(qū)分,通常這種驅(qū)動比較簡單,比如:ATADISK。
嵌入式 嵌入式開發(fā) 嵌入式系統(tǒng) wince驅(qū)動開發(fā)
至于本地驅(qū)動和流式驅(qū)動是從驅(qū)動與系統(tǒng)其它模塊(調(diào)用者)的接口形式上做的分類.其實,本地驅(qū)動這個名稱不大恰當(dāng),可能叫專用驅(qū)動或其它名字更為合適.它是指調(diào)用它的模塊給它有特定的接口,比如電源驅(qū)動和通用LED驅(qū)動。而串口,網(wǎng)卡等就是流接口驅(qū)動程序.
所以,一個驅(qū)動程序可以是單體的流式驅(qū)動,例如:ATADISK.也可以是分層的流式: 如OHCI ”
按照我的理解,單體和分層是驅(qū)動實現(xiàn)方式上的分類,而本地和流式則是驅(qū)動模型上的分類,所謂本地驅(qū)動就是操作系統(tǒng)有保留專門的接口,所謂流式是指編寫的DLL文件里可以導(dǎo)出各種流式接口函數(shù)。
第二點:驅(qū)動的功能屬性。設(shè)備驅(qū)動程序是操作系統(tǒng)內(nèi)核和硬件的接口,操作系統(tǒng)定義了一組標(biāo)準(zhǔn)的接口,編寫驅(qū)動的過程也就是實現(xiàn)這些接口。從應(yīng)用程序到具體硬件間有如下這些環(huán)節(jié)起作用:應(yīng)用程序-調(diào)用OS函數(shù)-操作系統(tǒng)-驅(qū)動接口-驅(qū)動程序-硬件操作函數(shù)-硬件。在wince里驅(qū)動都以用戶態(tài)的DLL存在,需要通過進程加載到slot里。共有三類系統(tǒng)進程用來加載:Device.exe,GWES.exe,FileSys.exe.絕大多數(shù)設(shè)備驅(qū)動都是通過Device.exe加載的。需要注意的是,不同的OS保留的設(shè)備驅(qū)動接口是不一樣的,如桌面windows和wince就不同。
第三點:wince下設(shè)備的初始化分為兩個階段:Device.exe的初始化;外設(shè)的枚舉和加載。其流程是:上電-啟動bootloader-啟動NK-啟動注冊表init鍵(Device.exe啟動)-初始化數(shù)據(jù)結(jié)構(gòu),I/O,電源管理等-加載BusEnum.dll(總線枚舉器)-枚舉注冊表下Driver/buildin的所有子鍵。這里的枚舉過程就是循環(huán)調(diào)用ActivateDeviceEx()函數(shù)加載驅(qū)動的過程。在OS啟動完畢后,我們可以用PB的Remote Registry Tool查看H_L_M/drivers/active包含的子鍵,看哪些驅(qū)動隨啟動而加載 。
第四點:流接口驅(qū)動的概念。暴露流式接口函數(shù)的驅(qū)動即是流驅(qū)動,它把外設(shè)抽象成一個文件。過程是:應(yīng)用程序使用文件API對設(shè)備進行訪問,OS接受API調(diào)用FileSys.exe,轉(zhuǎn)到device.exe,調(diào)用流接口,與硬件交互。所謂流接口函數(shù)有十個,包括XXX_Init、XXX_Deinit、XXX_Open、XXX_Close、XXX_Read、XXX_Write、XXX_PowerUp、XXX_PowerDown、XXX_Seek、XXX_IOControl,在wince5.0中增加le了XXX_PreClose,XXX_PreDeinit.而我們在應(yīng)用程序里對應(yīng)的文件API有CreateFile、DeviceIoControl、 ReadFile、 WriteFile,CloseHandle,SetFilePointer.
第五點:編寫流驅(qū)動的步驟。有兩種實現(xiàn)途徑:1。寫DLL,做成Project,加入到OS里。2。改BSP,把驅(qū)動寫在BSP里,再選擇那個BSP做OS。第一種方法步驟是在PB中新建一個DLL項目,編寫一些輸入函數(shù),寄存器,外設(shè)的聲明,寫DLLENTRY函數(shù);實現(xiàn)流接口函數(shù);編寫DLL的導(dǎo)出函數(shù)文件.DEF;為驅(qū)動程序?qū)懭胱员眄棧需要修改bib文件。 第二種方法就是在platform/BSP/drivers下新建一個目錄,然后在drivers目錄中的dirs文件中加入新建的目錄名。在新建的目錄下,新建你的源代碼文件,在其中實現(xiàn)DLL函數(shù)。新建名稱分別為sources, makefile, ***.def的文件;修改platform.reg和platform.bib文件
]]>1、 對象存儲(object store)
對象存儲是Windows CE默認(rèn)的數(shù)據(jù)存儲機制。任何新創(chuàng)建的內(nèi)核中都默認(rèn)包含對象存儲器。對象存儲的實質(zhì)是在RAM中創(chuàng)建一個文件系統(tǒng),將文件保存在RAM中,這些文件來源于ROM。當(dāng)設(shè)備啟動時,引導(dǎo)程序?qū)OM中的內(nèi)核文件解壓并存放在RAM中。"\windows"目錄就是基于對象存儲的。對象存儲的特點是文件可以壓縮、支持事務(wù)機制(和數(shù)據(jù)庫中的事務(wù)機制相似)、數(shù)據(jù)I/O相對較快。
A、對象存儲中的對象類型包括文件、目錄、數(shù)據(jù)庫、記錄、數(shù)據(jù)庫卷。CE為每個對象分配一個對象ID(CEOID)。訪問或者操作任何對象的前提是得到該對象ID。
B、CE能夠自動壓縮所有對象存儲中的文件(CE提供了一個選項供OEM設(shè)置是否能夠自動壓縮文件)。所以文件沒有壓縮或不壓縮的標(biāo)志,但是有一個標(biāo)志,標(biāo)明此文件存在于ROM還是RAM中。一個文件最大長度可達到4 GB。
C、CE提供了三種文件系統(tǒng):基于ROM的文件系統(tǒng)、基于RAM的文件系統(tǒng)、FAT文件系統(tǒng)。
2、 注冊表(registry)
CE下注冊表和其它windows操作系統(tǒng)中注冊表概念和結(jié)構(gòu)基本相同。
A、CE下注冊表限制:鍵名最大長度255個字符; 數(shù)據(jù)最大 4KB;子鍵深度最大值 16層。
B、根鍵有HKEY_CLASSES_ROOT、HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、HKEY_USERS。
C、操作注冊表函數(shù):
i. 打開RegOpenKeyEx 和創(chuàng)建RegCreateKeyEx
ii. 讀RegQueryValueEx寫RegSetValueEx
iii. 枚舉入口或子鍵RegEnumValue、RegEnumKeyEx
iv. 刪除入口或子鍵RegDeleteValue、RegDeleteKey
v. 關(guān)閉RegCloseKey
3、CE下注冊表類型
分為基于RAM的注冊表和基于HIVE的注冊表。
A、基于RAM的注冊表,也叫基于對象存儲(oject storage)的注冊表。用于將注冊表數(shù)據(jù)全部保存在RAM中。
i. 從CE v1.0開始到CE .NET之前,僅采用此技術(shù)來保存注冊表。每個新創(chuàng)建的內(nèi)核都默認(rèn)采用此技術(shù)來保存注冊表。
ii. 適合頻繁熱啟動而不冷啟動的設(shè)備。系統(tǒng)關(guān)閉時提供低電源給RAM。如果斷電,重新啟動設(shè)備后,系統(tǒng)將從內(nèi)核中重新讀取注冊表數(shù)據(jù)到RAM。當(dāng)然以前保存的用戶數(shù)據(jù)已經(jīng)丟失。
iii. 基于RAM的注冊表也能夠永久保存注冊標(biāo)數(shù)據(jù)。CE提供了兩個機制。
1) 第一種機制的設(shè)計思路是在設(shè)備關(guān)閉前調(diào)用RegCopyFile函數(shù)將整個注冊表數(shù)據(jù)以文件形式保存到永久存儲器上。重新啟動設(shè)備時,調(diào)用RegRestoreFile函數(shù)將文件全部讀出到RAM中。但是這時必須一次熱啟動才能使恢復(fù)的注冊表數(shù)據(jù)有效。所以每次啟動就多出一次熱啟動。好在熱啟動非常快,幾秒鐘的時間。
2) 另一種機制可以避免前一種機制的需要兩次啟動的缺點。但也有它的缺點。OEM(原始設(shè)備制造商)可以在OAL層編寫WriteRegistryToOEM and ReadRegistryFromOEM兩個函數(shù),內(nèi)核在啟動時會自動調(diào)用ReadRegistryFromOEM函數(shù)來讀注冊表數(shù)據(jù)。而應(yīng)用程序調(diào)用RegFlushKey函數(shù)時,這個函數(shù)用調(diào)用WriteRegistryToOEM函數(shù)寫注冊表數(shù)據(jù)到永久存儲器上。這個機制避免了兩次啟動的缺陷。但問題出現(xiàn)在內(nèi)核啟動時,調(diào)用ReadRegistryFromOEM之前文件系統(tǒng)驅(qū)動程序還沒加載,那就無法打開、讀取文件。CE幫助文件中說解決辦法是將從永久存儲器中讀取數(shù)據(jù)的代碼加到ReadRegistryFromOEM中。幫助中說的意思可不是調(diào)用ReadFile這么簡單的,因為文件系統(tǒng)驅(qū)動程 序還沒加載。
3) 個人建議:如果要采用基于RAM的注冊表保存機制,而且要求永久保存注冊表數(shù)據(jù),使用第一種機制比較容易。
B、 基于HIVE的注冊表。用于將注冊表數(shù)據(jù)全部或部分保存到永久存儲器上。
i.它是從CE.NET開始采用的新技術(shù)。適合經(jīng)常冷啟動而不熱啟動的設(shè)備。
ii.支持多用戶信息分別保存。當(dāng)一個用戶登錄時,加載這個用戶的注冊表數(shù)據(jù),注銷時卸載這個用戶的注冊表數(shù)據(jù)。
iii. HIVE是指一組鍵,包括子鍵、鍵值、數(shù)據(jù)。是保存或者加載注冊表數(shù)據(jù)的單位。分為系統(tǒng)HIVE(system hive)、用戶HIVE(uer hive)、引導(dǎo)HIVE(boot hive)。
1) 系統(tǒng)HIVE包含了關(guān)于系統(tǒng)的設(shè)置信息。具體保存注冊表中HKEY_LOCAL_MACHINE、HKEY_CLASSES_ROOT、HKEY_USERS鍵下所有數(shù)據(jù)。保存系統(tǒng)HIVE的文件的路徑在【HKEY_LOCAL_MACHINE\init\BootVars】下,鍵名為"systemhive",鍵值為文件的路徑。默認(rèn)為"\Documents and Settings\system.hv"。
2) 用戶HIVE包含了一個用戶的信息。具體保存注冊表中HKEY_CURRENT_USER鍵下所有數(shù)據(jù)。保存用戶HIVE的文件的路徑同樣為【HKEY_LOCAL_MACHINE\init\BootVars】下,鍵名為"profiledir",鍵值為所有用戶HIVE的共同目錄。默認(rèn)為"\Documents and Settings",在這個目錄下包含了以每個用戶名命名的子目錄。子目錄里含有一個文件,默認(rèn)文件名為user.hv。
3) 引導(dǎo)HIVE保存在ROM(內(nèi)核)中。具體保存內(nèi)容同系統(tǒng)HIVE一樣。當(dāng)解壓內(nèi)核并加載注冊表時,系統(tǒng)先將引導(dǎo)HIVE數(shù)據(jù)讀出,引導(dǎo)HIVE包含了永久存儲器的驅(qū)動程序和文件系統(tǒng)的驅(qū)動程序,這些驅(qū)動加載后,系統(tǒng)HIVE被加載,然后引導(dǎo)HIVE被釋放。因為引導(dǎo)HIVE被包含在內(nèi)核中,所以存在一種情況:如果重新做了一個新內(nèi)核,引導(dǎo)HIVE中的數(shù)據(jù)同系統(tǒng)HIVE可能不相同。那么系統(tǒng)該加載哪個版本好呢?為此,CE在生成每個內(nèi)核時都做了一個標(biāo)志。而系統(tǒng)HIVE也存在這樣一個標(biāo)志,當(dāng)加載引導(dǎo)HIVE時,如果引導(dǎo)HIVE和系統(tǒng)HIVE的標(biāo)志不相同,系統(tǒng)會刪除系統(tǒng)HIVE文件,然后重新創(chuàng)建一個文件并從引導(dǎo)HIVE復(fù)制數(shù)據(jù)。
iv. 永久保存注冊表數(shù)據(jù)
Windows CE.NET采用新的注冊表保存技術(shù)――基于HIVE的注冊表,的確讓人很興奮,在這之前基于Windows CE的設(shè)備,大多數(shù)采用給RAM供電方式來保存注冊表數(shù)據(jù),雖然也可以通過RegCopyFile函數(shù)永久保存,但畢竟啟動時還要再熱啟動一次,有了基于HIVE的技術(shù),啟動時系統(tǒng)會自動加載數(shù)據(jù),免去了熱啟動的麻煩,而且當(dāng)內(nèi)核更新升級時,你不用擔(dān)心保存在永久存儲器上的系統(tǒng)HIVE文件影響你新的內(nèi)核,系統(tǒng)會自動判斷并刪除過時的系統(tǒng)HIVE文件。只有擁有了這樣的技術(shù),基于CE的產(chǎn)品才算是一個真正的電腦。
注:關(guān)于基于HIVE的注冊表的實現(xiàn),暫不講解。
下面簡單說明 RegCopyFile和RegRestoreFile的用法。
///使用基于RAM的注冊表,利用RegCopyFile和RegRestoreFile
///實現(xiàn)永久保存注冊表數(shù)據(jù)。
#include <Pkfuncs.h>
#include <winbase.h>
CString strRegBackup = L"\\hard disk\\RegBackup.reg";
CString strTmp = L"\\windows\\temp.reg";
////////導(dǎo)出。在系統(tǒng)關(guān)閉前。
if(! RegCopyFile(strTmp)) ///導(dǎo)出注冊表,用temp.reg做緩沖用。
{
return FALSE;
}
if(! CopyFile(strTmp, strRegBackup, FALSE)) ///把temp.reg再復(fù)制到RegBackup.reg
{
return FALSE;
}
/////////導(dǎo)入。在系統(tǒng)啟動時。
if(! CopyFile(strRegBackup, strTmp, FALSE))
{
return FALSE;
}
if(! RegRestoreFile(strTmp)) ///恢復(fù)注冊表
{
return FALSE;
}
if(! KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL)) ///重新啟動
{
return FALSE;
}
本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/ymzhou117/archive/2009/11/11/4799873.aspx
以下內(nèi)容含腳本,或可能導(dǎo)致頁面不正常的代碼 |
---|
說明:上面顯示的是代碼內(nèi)容。您可以先檢查過代碼沒問題,或修改之后再運行. |
unsigned char CSStab2[256]=
{
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x09,0x08,0x0b,0x0a,0x0d,0x0c,0x0f,0x0e,
0x12,0x13,0x10,0x11,0x16,0x17,0x14,0x15,0x1b,0x1a,0x19,0x18,0x1f,0x1e,0x1d,0x1c,
0x24,0x25,0x26,0x27,0x20,0x21,0x22,0x23,0x2d,0x2c,0x2f,0x2e,0x29,0x28,0x2b,0x2a,
0x36,0x37,0x34,0x35,0x32,0x33,0x30,0x31,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,
0x49,0x48,0x4b,0x4a,0x4d,0x4c,0x4f,0x4e,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
0x5b,0x5a,0x59,0x58,0x5f,0x5e,0x5d,0x5c,0x52,0x53,0x50,0x51,0x56,0x57,0x54,0x55,
0x6d,0x6c,0x6f,0x6e,0x69,0x68,0x6b,0x6a,0x64,0x65,0x66,0x67,0x60,0x61,0x62,0x63,
0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x76,0x77,0x74,0x75,0x72,0x73,0x70,0x71,
0x92,0x93,0x90,0x91,0x96,0x97,0x94,0x95,0x9b,0x9a,0x99,0x98,0x9f,0x9e,0x9d,0x9c,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x89,0x88,0x8b,0x8a,0x8d,0x8c,0x8f,0x8e,
0xb6,0xb7,0xb4,0xb5,0xb2,0xb3,0xb0,0xb1,0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,
0xa4,0xa5,0xa6,0xa7,0xa0,0xa1,0xa2,0xa3,0xad,0xac,0xaf,0xae,0xa9,0xa8,0xab,0xaa,
0xdb,0xda,0xd9,0xd8,0xdf,0xde,0xdd,0xdc,0xd2,0xd3,0xd0,0xd1,0xd6,0xd7,0xd4,0xd5,
0xc9,0xc8,0xcb,0xca,0xcd,0xcc,0xcf,0xce,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,
0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf6,0xf7,0xf4,0xf5,0xf2,0xf3,0xf0,0xf1,
0xed,0xec,0xef,0xee,0xe9,0xe8,0xeb,0xea,0xe4,0xe5,0xe6,0xe7,0xe0,0xe1,0xe2,0xe3
};
unsigned char CSStab3[512]=
{
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff
};
unsigned char CSStab4[256]=
{
0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,
0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,
0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,
0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2,
0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,
0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,
0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,
0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,
0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9,
0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,
0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,
0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,
0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb,
0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7,
0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
};
unsigned char CSStab5[256]=
{
0xff,0x7f,0xbf,0x3f,0xdf,0x5f,0x9f,0x1f,0xef,0x6f,0xaf,0x2f,0xcf,0x4f,0x8f,0x0f,
0xf7,0x77,0xb7,0x37,0xd7,0x57,0x97,0x17,0xe7,0x67,0xa7,0x27,0xc7,0x47,0x87,0x07,
0xfb,0x7b,0xbb,0x3b,0xdb,0x5b,0x9b,0x1b,0xeb,0x6b,0xab,0x2b,0xcb,0x4b,0x8b,0x0b,
0xf3,0x73,0xb3,0x33,0xd3,0x53,0x93,0x13,0xe3,0x63,0xa3,0x23,0xc3,0x43,0x83,0x03,
0xfd,0x7d,0xbd,0x3d,0xdd,0x5d,0x9d,0x1d,0xed,0x6d,0xad,0x2d,0xcd,0x4d,0x8d,0x0d,
0xf5,0x75,0xb5,0x35,0xd5,0x55,0x95,0x15,0xe5,0x65,0xa5,0x25,0xc5,0x45,0x85,0x05,
0xf9,0x79,0xb9,0x39,0xd9,0x59,0x99,0x19,0xe9,0x69,0xa9,0x29,0xc9,0x49,0x89,0x09,
0xf1,0x71,0xb1,0x31,0xd1,0x51,0x91,0x11,0xe1,0x61,0xa1,0x21,0xc1,0x41,0x81,0x01,
0xfe,0x7e,0xbe,0x3e,0xde,0x5e,0x9e,0x1e,0xee,0x6e,0xae,0x2e,0xce,0x4e,0x8e,0x0e,
0xf6,0x76,0xb6,0x36,0xd6,0x56,0x96,0x16,0xe6,0x66,0xa6,0x26,0xc6,0x46,0x86,0x06,
0xfa,0x7a,0xba,0x3a,0xda,0x5a,0x9a,0x1a,0xea,0x6a,0xaa,0x2a,0xca,0x4a,0x8a,0x0a,
0xf2,0x72,0xb2,0x32,0xd2,0x52,0x92,0x12,0xe2,0x62,0xa2,0x22,0xc2,0x42,0x82,0x02,
0xfc,0x7c,0xbc,0x3c,0xdc,0x5c,0x9c,0x1c,0xec,0x6c,0xac,0x2c,0xcc,0x4c,0x8c,0x0c,
0xf4,0x74,0xb4,0x34,0xd4,0x54,0x94,0x14,0xe4,0x64,0xa4,0x24,0xc4,0x44,0x84,0x04,
0xf8,0x78,0xb8,0x38,0xd8,0x58,0x98,0x18,0xe8,0x68,0xa8,0x28,0xc8,0x48,0x88,0x08,
0xf0,0x70,0xb0,0x30,0xd0,0x50,0x90,0x10,0xe0,0x60,0xa0,0x20,0xc0,0x40,0x80,0x00
};
void CSSdescramble(unsigned char *sec,unsigned char *key)
{
unsigned int t1,t2,t3,t4,t5,t6;
unsigned char *end=sec+0x800;
t1=key[0]^sec[0x54]|0x100;
t2=key[1]^sec[0x55];
t3=(*((unsigned int *)(key+2)))^(*((unsigned int *)(sec+0x56)));
t4=t3&7;
t3=t3*2+8-t4;
sec+=0x80;
t5=0;
while(sec!=end)
{
t4=CSStab2[t2]^CSStab3[t1];
t2=t1>>1;
t1=((t1&1)<<8)^t4;
t4=CSStab5[t4];
t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
t3=(t3<<8)|t6;
t6=CSStab4[t6];
t5+=t6+t4;
*sec++=CSStab1[*sec]^(t5&0xff);
t5>>=8;
}
}
void CSStitlekey1(unsigned char *key,unsigned char *im)
{
unsigned int t1,t2,t3,t4,t5,t6;
unsigned char k[5];
int i;
t1=im[0]|0x100;
t2=im[1];
t3=*((unsigned int *)(im+2));
t4=t3&7;
t3=t3*2+8-t4;
t5=0;
for(i=0;i<5;i++)
{
t4=CSStab2[t2]^CSStab3[t1];
t2=t1>>1;
t1=((t1&1)<<8)^t4;
t4=CSStab4[t4];
t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
t3=(t3<<8)|t6;
t6=CSStab4[t6];
t5+=t6+t4;
k=t5&0xff;
t5>>=8;
}
for(i=9;i>=0;i--)
key[CSStab0[i+1]]=k[CSStab0[i+1]]^CSStab1[key[CSStab0[i+1]]]^key[CSStab0];
}
void CSStitlekey2(unsigned char *key,unsigned char *im)
{
unsigned int t1,t2,t3,t4,t5,t6;
unsigned char k[5];
int i;
t1=im[0]|0x100;
t2=im[1];
t3=*((unsigned int *)(im+2));
t4=t3&7;
t3=t3*2+8-t4;
t5=0;
for(i=0;i<5;i++)
{
t4=CSStab2[t2]^CSStab3[t1];
t2=t1>>1;
t1=((t1&1)<<8)^t4;
t4=CSStab4[t4];
t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
t3=(t3<<8)|t6;
t6=CSStab5[t6];
t5+=t6+t4;
k=t5&0xff;
t5>>=8;
}
for(i=9;i>=0;i--)
key[CSStab0[i+1]]=k[CSStab0[i+1]]^CSStab1[key[CSStab0[i+1]]]^key[CSStab0];
}
void CSSdecrypttitlekey(unsigned char *tkey,unsigned char *dkey)
{
int i;
unsigned char im1[6];
unsigned char im2[6]={0x51,0x67,0x67,0xc5,0xe0,0x00};
for(i=0;i<6;i++)
im1=dkey;
CSStitlekey1(im1,im2);
CSStitlekey2(tkey,im1);
本文轉(zhuǎn)貼自 【 浮游城 - Castle in the Sky | 開放邀請注冊,PS|SS|WII|DC下載研究中心 】 ,原文地址:http://bbs.chinaemu.org/read-htm-tid-93244.html
本方案設(shè)計CAN驅(qū)動是放在Windows CE操作系統(tǒng)的內(nèi)核下層,位于OEM adaptation layer(OAL)層的一個真正的驅(qū)動,而不是在主程序中的串口操作。在Windows CE的設(shè)備管理器可以看到CAN1和CAN2兩個端口,并且可以查看其工作的正常與否和對其進行配置。如:中斷號和I/O地址。
2.1 CAN卡寄存器讀寫函數(shù)
CAN卡的通信是通過操作CAN卡上的CAN控制器進行的。在CAN控制器中有很多寄存器,如控制寄存器、命令寄存器、狀態(tài)寄存器、中斷寄存器等,通過讀寫這些寄存器中的命令狀態(tài)字可以檢測和控制CAN卡的行為。在Windows CE.NET下,通過調(diào)用DOK中的API函數(shù)HalTranslateBusAddress,將CAN卡分配的物理地址映射為邏輯地址。這樣各個寄存器對應(yīng)的就是CAN卡基地址的偏移地址,因此,對寄存器的讀寫就轉(zhuǎn)化為對內(nèi)存地址的讀寫。下面是CAN卡寄存器的讀寫函數(shù):
*在偏移量為off的地址讀取一個字節(jié)的數(shù)據(jù)inline BYTE CANR(LPCAN_HW_OPEN_INFO hCan,DWORD off)
{
return hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off];
*將一個字節(jié)數(shù)據(jù)寫到偏移量為off的地址中inline VOID CANW(LPCAN_HW_OPEN_INFO hCan,DWORD off,BYTE val)
{
hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off]=val;
}
參數(shù)LPCAN_HW_OPEN_INFO定義的是CAN卡的數(shù)據(jù)結(jié)構(gòu),其中成員lpMappeBaseAddr[0]表示的是映射后基地址,lpMappedBaseAddr[1]就是基地址+1的地址,對應(yīng)CAN卡的寄存器是命令寄存器。通過上述兩個函數(shù)可操作CAN卡上的所有寄存器。
2.2 CAN卡初始化
CAN卡的控制器比較復(fù)雜,在通信前必須確認(rèn)硬件信息正確性、初始化各寄存器。初始化函數(shù)的基本流程如圖3所示。
第一步,檢查端口號和硬件信息的正確性,主要是CAN卡中斷號是否有效。
第二卡,設(shè)置CAN卡默認(rèn)參數(shù):
CanCardConfigInfo CAN_DEFAULT_SETTING=
{0X00,0XFF,0X03,0X1C};/*設(shè)置默認(rèn)波特率為125Kbps*/
DWORD dwThreadID =0;
PHYSICAL_ADDRESS phyAddr={hwInfo->dwIOBaseAddr *16,0 };
第三卡,用WinCE API函數(shù)LocalAlloc為CAN卡驅(qū)動中用到的數(shù)據(jù)結(jié)構(gòu)分配緩沖區(qū);通過HalTranslateBusAddress和MmMapIoSpace函數(shù)映射I/O地址,提供直接訪問設(shè)備的虛擬地址:
if(!HalTranslateBusAddress(Isa,0,phyAddr,0,&phyAddr))
goto _ExitInit;
hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr=
(LPBYTE)MmMapIoSpace(phyAddr,CANCARDADDRLEN,FALSE);
if(!hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr)
goto _ExitInit;
如果分配內(nèi)存或映射邏輯地址失敗,則退出初始化程序,CAN卡初始化失敗。
第四步,初始化讀寫屬性、共享模式、讀超時時間和第二個CAN口的基地址。
第五步,創(chuàng)建CAN卡事件和數(shù)據(jù)接收事件:hCan->lpCanHWInfo->hCanEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
hCan->lpCanHWInfo->hRecvMsgEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
第六步,初始化中斷,如果CAN卡有復(fù)位請求就退出初始化程序。設(shè)置好中斷后啟動數(shù)據(jù)接收線程,設(shè)置線程優(yōu)先級繼續(xù)線程處理;最后配置CAN卡參數(shù),進入正常運行狀態(tài)。
2.3 CAN卡信息發(fā)送
CAN卡的信息發(fā)送分為兩個步驟。在對CAN卡基本信息進行檢查后,首先設(shè)置發(fā)送緩沖的ID號。CAN標(biāo)準(zhǔn)模式的ID號為11位,偏移地址10中存放的是ID號的高8位,偏移地址11的高3位存放的是ID號的低3位,剩下5位分別是RTR位(遠程傳送請求位)和數(shù)據(jù)長度。通過CANW函數(shù)將處理后的數(shù)據(jù)寫入到相應(yīng)的偏移地址,設(shè)置完相應(yīng)的地址數(shù)據(jù)后,通過循環(huán)將偏移地址12~19的數(shù)據(jù)采集回來存到數(shù)組中。然后,設(shè)置CAN卡的傳輸請求為允許并不斷偵測狀態(tài)寄存器的變化,當(dāng)傳輸緩沖滿標(biāo)志或傳輸結(jié)束標(biāo)志為1時通出程序,完成一次數(shù)據(jù)采集。傳輸緩沖區(qū)的寄存器如表1所列。
表1
ID號 | 10 | ID.10 | ID.9 | ID.8 | ID.7 | ID.6 | ID.5 | ID.4 | ID.3 |
RTR,數(shù)據(jù)長度碼 | 11 | ID.2 | ID.1 | ID.0 | RTR | DLC.3 | DLC.2 | DLC.1 | DLC.0 |
數(shù)據(jù)1~8 | 12~19 | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) |
表2
ID號 | 20 | ID.10 | ID.9 | ID.8 | ID.7 | ID.6 | ID.5 | ID.4 | ID.3 |
RTR,數(shù)據(jù)長度碼 | 21 | ID.2 | ID.1 | ID.0 | RTR | DLC.3 | DLC.2 | DLC.1 | DLC.0 |
數(shù)據(jù)1~8 | 22~29 | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) | 數(shù)據(jù) |
CAN消息發(fā)送函數(shù)的實現(xiàn)如下:
BOOL CAN_SendMessage(LPCAN_HW_OPEN_INFO hCan,LPCanCardMessageBuflpMsg)
{
BOOL bSuc=FALSE;
ASSERT(hCan && lpMsg && lpMsg->dwMessageLen <=8); /*防錯處理*/
if(0= =(hCan->dwAccessCode & GENERIC_WRITE))
return FALSE;
:: EnterCriticalSection(&hCan->lpCanHWInfo->
TransmitCritSec); /*進入臨界區(qū)*/
BYTE byV=static_cast<BYTE>(1pMsg->dwMsgID>>3);
CANW(hCan,10,byV); /*設(shè)置ID值高8位*/
byV=static_cast<BYTE>=((lpMsg->dwMsgID & 7)<<5);
if(lpMsg->bRTR) byV|=0x10;
byV+=static_cast<BYTE>(lpMsg->dwMessageLen);
CANW(hCan,11,byV);/*設(shè)置ID值低3位、RTR及數(shù)據(jù)長度*/
for(UINT i=0;<lpMsg->dwMessageLen;++i)
{
CANW(hCan,12+i,lpMsg->byMsg[i]);
} /*采集數(shù)據(jù)*/
CANW(hCan,1,1);/*重置傳輸請求*/
while(TRUE)
{byV=CANR(hCan,2);
if(byV & 0X40) /*傳輸緩沖區(qū)滿,退出*/
{break;}
if(byV & 0X8){ /*傳輸結(jié)束,正確返回退出*/
bSuc = TRUE;
break;}
}
::LeaveCriticalSection(&hCan->lpCanHWInfo->TransmitCritSec); /*離開臨界區(qū)*/
return bSuc;
}
2.4 CAN卡信息接收
CAN卡的信息接收是發(fā)送的逆過程,當(dāng)接收緩沖區(qū)標(biāo)志為1時,表示緩沖區(qū)已滿可以接收數(shù)據(jù),將數(shù)據(jù)接收到數(shù)組后釋放接收緩沖區(qū),然后對接收到的數(shù)據(jù)進行分解并存儲到CAN卡信息緩沖區(qū)的結(jié)構(gòu)體。接收緩沖區(qū)的寄存器結(jié)構(gòu)如表2所列。
CAN消息接收函數(shù)的實現(xiàn)如下:
BOOL CAN_RecvRecvMessage(LPCAN_HW_OPEN_INFO
HCan,OUT LPCanCardMessageBuflpMsg)
{……
if(CANR(hCan,2)&1){ /*判斷接收緩沖區(qū)是否已滿*/
for(UINT i=0;i<10;++i)
recvBuf[i]=CANR(hCan,20+i);/*將數(shù)據(jù)暫存到臨時緩沖區(qū)*/
CANW(hCan,1,4); /*釋放接收緩沖區(qū)*/
LpMsg->dwMsgID=recvBuf[0]<<3; /*取出ID的高8位*/
BYTE byV =recvBuf[1];
LpMsg->dwMsgID+=byV >>5;/*取出ID低3位,然后和高8位合并*/
LpMsg->bRTR =byV &0x10?TRUE:/*返回RTR狀態(tài)*/
LpMsg->dwMessageLen = byV &0XF; /*返回數(shù)據(jù)長度*/
……
}
else
{++hCan->lpCanHWInfo->dwErrorMsgCount;}/*沒有收到數(shù)據(jù),錯誤計數(shù)加1*/
::LeaveCriticalSection(&hCan->lpCanHWInfo->
ReceiveCritSec); /*離開臨界區(qū)*/
Return bSuc;
}
2.5 CAN卡事件處理
CAN卡事件處理函數(shù)是CAN卡驅(qū)動程序中很重要的部分。驅(qū)動設(shè)計要求具有消息通知的功能,當(dāng)事件發(fā)生時及時捕獲事件并進行消息處理。
下面是事件處理函數(shù)的實現(xiàn):
staric DWORD WINAPI CAN_EventHanle(LPVOID lpParam)
{
ASSERT(lpParam);
LPCAN_HW_OPEN_INFO hCan=(LPCAN_HW_OPEN_INFO)lpParam;
CanCardMessageBuf bufMsg;
while(TEUE)
{ /*循環(huán)等待CAN卡消息產(chǎn)生,然后進行處理*/
::WaitForSingleObject(hCan->lpCanHWInfo->hCanEvent,0XFFFFFFFF);
if(hCan->lpCanHWInfo->bKillCanThread) break; /*若CAN線程已關(guān)閉則中斷*/
if(CAN_RecvMessage(hCan,&hufMsg)){ /*正確接收數(shù)據(jù)后*/
CAN_RecvBufPush(hCan,&bufMsg);} /*將數(shù)據(jù)壓入緩沖*/
BYTE byV=CANR(hCan,3); /*將3號寄存器讀出然后立即寫入*/
CANW(hCan,3,byV);/*能夠獲取每次中斷*/
InterruptDone(hCan->lpCanHWInfo->lpCanObj->dwSysIrqt);
} /*本次中斷結(jié)束,等待下次中斷*/
return 0;
}
2.6 其它函數(shù)
為了提供更多的功能和更方便地使用CAN卡進行通信,在CAN卡驅(qū)動程序中還設(shè)計了一些函數(shù)如CAN_Config用CAN卡信息配置、CAN_RecvBufPop用于處理接收緩沖區(qū)、CAN_Reset用于復(fù)位CAN卡、CheckHWInfo用于硬件信息檢查等。這些函數(shù)提供了對CAN通信卡的設(shè)置、檢查等功能,在這里不再詳述了。
3 CAN卡驅(qū)動封裝設(shè)計
CAN卡底層驅(qū)動函數(shù)雖然功能完整,但是對于用戶使用比較復(fù)雜并且一般用戶不需要了解底層實現(xiàn)的機制。為了便于使用,最后對CAN卡的驅(qū)動進行了封裝,提供CanOpenFile、CanSendMsg等五個函數(shù)用于CAN總線的通信,以動態(tài)連接庫(DLL)的形式提供給用戶調(diào)用。封裝函數(shù)及功能如下:
*CanOpenFile;初始化并打開CAN卡的一個端口。
*CanCloseFile;關(guān)閉由CanOpenFile打開的CAN卡端口。
*CanRecvMsg;接收CAN卡數(shù)據(jù),打開CAN卡時必須具有GENERIC_READ權(quán)限。
*CanSendMsg;通過CAN卡發(fā)送數(shù)據(jù)。打開CAN卡時必須具有GENERIC_WRITE權(quán)限。
*CanIOControl;設(shè)置或獲取CAN卡I/O參數(shù)支持的I/O控制包括:IOCTL_CAN_CONFIG,IOCTL_CAN_RESET,IOCTL_CAN_TIMEOUT,IOCTL_CAN_SENDREADY,IOCTL_CAN_RECVREADY。
下面是CanSendMsg函數(shù)實現(xiàn)的代碼:
BOOL CanSendMSg(
HANDLE hCan,
LPCanCardMessageBuflpMsg)
{
if(!hCan||INVALID_HANDLE_VALUE= =hCan||
!lpMsg||lpMsg->dwMessageLen>8)return FALSE;
return CAN_SendMessage(LPCAN_HW_OPEN_INFO)
hCan,lpMsg);
該函數(shù)就是通過封裝CAN卡的底層驅(qū)動函數(shù)SendMessage來實現(xiàn)的,這樣將功能集中的五個函數(shù)更方便了用戶使用。
結(jié)語
程序開發(fā)的上位機是普通的PC機,軟件環(huán)境是:Windows2000 Professional、Embedded Visual C++4.0、與下位機中WinCE.NET對應(yīng)的SDK,該SDK是在用Platform Builder 4.0定制WinCE時編譯生成的。下位機使用的硬件是研華的嵌入式PC104主板PCM3346N,操作系統(tǒng)為WinCE.ENT。
本文設(shè)計開發(fā)的驅(qū)動已經(jīng)在北京懷柔的變電站項目中得到成功的應(yīng)用,CAN卡通信穩(wěn)定,系統(tǒng)在WINCE.NET下運行可靠,保證了項目的順利實施。
]]>以下內(nèi)容含腳本,或可能導(dǎo)致頁面不正常的代碼 |
---|
說明:上面顯示的是代碼內(nèi)容。您可以先檢查過代碼沒問題,或修改之后再運行. |
數(shù)字視頻監(jiān)控系統(tǒng)是以計算機或嵌入式系統(tǒng)為中心、視頻處理技術(shù)為基礎(chǔ)組建的的一種新型監(jiān)控系統(tǒng),系統(tǒng)采用符合圖像數(shù)據(jù)壓縮的國際標(biāo)準(zhǔn),綜合利用圖像傳感器、計算機網(wǎng)絡(luò)、自動控制和人工智能等技術(shù)。由于數(shù)字視頻監(jiān)控系統(tǒng)對視頻圖像進行了數(shù)字化,所以與傳統(tǒng)的模擬監(jiān)控系統(tǒng)相比,數(shù)字監(jiān)控具有許多優(yōu)點。數(shù)字化的視頻系統(tǒng)可以充分利用計算機的快速處理能力,對其進行壓縮、分析、存儲和顯示。數(shù)字化視頻處理技術(shù)提高了圖像的質(zhì)量與監(jiān)控效率,使系統(tǒng)易于管理和維護。整個系統(tǒng)是模塊化結(jié)構(gòu),體積小,易于安裝、使用和維護。正是由于數(shù)字視頻監(jiān)控技術(shù)具有傳統(tǒng)模擬監(jiān)控技術(shù)無法比擬的優(yōu)點,而且符合當(dāng)前信息社會中數(shù)字化、網(wǎng)絡(luò)化和智能化的發(fā)展趨勢,所以數(shù)字視頻監(jiān)控技術(shù)正在逐步取代模擬監(jiān)控技術(shù),廣泛應(yīng)用于各行各業(yè)。嵌入式系統(tǒng)以體積小、實時性強、性價比高、穩(wěn)定性好等特點在社會的各個領(lǐng)域中得到了廣泛應(yīng)用。筆者設(shè)計的一種嵌入式系統(tǒng),以WinCE操作系統(tǒng)和ARM硬件平臺為核心實現(xiàn)了對現(xiàn)場的實時監(jiān)控,并通過無線網(wǎng)絡(luò)把視頻圖像傳輸?shù)街鳈C端,以實現(xiàn)分析、存儲和顯示等功能。
1系統(tǒng)設(shè)計
本系統(tǒng)主要由操作系統(tǒng)定制、視頻圖像采集、視頻圖像無線傳輸三部分組成。系統(tǒng)的核心芯片選用基于ARM920T內(nèi)核的S3C2410嵌入式微處理器,軟件環(huán)境選用MicrosoftWindowsCE操作系統(tǒng)。系統(tǒng)首先通過USB攝像頭采集現(xiàn)場實時視頻信息,并對其進行壓縮。然后,使用兩塊無線網(wǎng)卡在ARM開發(fā)板與上位機之間構(gòu)建一個無線局域網(wǎng)絡(luò),從而將壓縮的視頻數(shù)據(jù)傳輸?shù)街鳈C端,終端用戶即可在主機端通過流媒體播放程序查看遠程視頻影像。視頻監(jiān)控系統(tǒng)總體結(jié)構(gòu)框圖如圖l所示。
圖l、視頻監(jiān)控系統(tǒng)總體結(jié)構(gòu)框圖
2操作系統(tǒng)的定制
系統(tǒng)硬件平臺的核心芯片選用了S3C2410處理器,最高頻率可達203MHz。S3C2410處理器是Samsung公司基于ARM公司的ARM920T處理器核,采用O.18μm制造工藝的32位微控制器。該處理器具有較高的集成度,簡化了應(yīng)用系統(tǒng)的硬件設(shè)計,提高了系統(tǒng)的可靠性。開發(fā)扳上還擴展了4MB的NORFlash、64MB的NANDFlash和64MB的DRAM。
系統(tǒng)選用了MicrosoftWilldowsCE(簡稱“WinCE”)操作系統(tǒng)。WinCE是一個緊湊的、高效且可擴展的32位操作系統(tǒng),適用于各種嵌入式系統(tǒng)和產(chǎn)品。它擁有多線程、多任務(wù)和確定性的實時、完全搶占式優(yōu)先級的操作系統(tǒng)環(huán)境,專門面向只有有限資源的硬件系統(tǒng);同時,它的模塊化設(shè)計方式使得系統(tǒng)開發(fā)人員和應(yīng)用開發(fā)人員能夠為多種多樣的產(chǎn)品來定制它,可以選擇、組合和配置WinCE的模塊和組件來創(chuàng)建用戶版的操作系統(tǒng)。
在WinCE產(chǎn)品開發(fā)中,主要有內(nèi)核定制和應(yīng)用程序開發(fā)兩項非常重要的工作。微軟在兩方面都提供了良好的開發(fā)工具,即內(nèi)核定制工具PlatformBuilder(簡稱“PB”)和應(yīng)用程序開發(fā)工具EmbeddedVisualC++(簡稱“EVC”)。
在系統(tǒng)定制過程中,各部分的關(guān)系如圖2所示。
3視頻圖像采集
3.1攝像頭驅(qū)動
圖像采集模塊的硬件資源選用了當(dāng)前市面上應(yīng)用最廣泛的USB接口的中星微攝像頭。該款攝像頭造價低廉,成像效果好,用于本系統(tǒng)中體現(xiàn)出了較高的性價比。系統(tǒng)在進行視頻采集前,首先要檢測設(shè)定視頻源。系統(tǒng)啟動后,WinCE操作系統(tǒng)會自動檢測攝像頭是否連接好。本系統(tǒng)在定制WinCE操作系統(tǒng)時,通過修改操作系統(tǒng)配置和注冊表。可以使系統(tǒng)自動加載攝像頭在WinCE下的驅(qū)動程序ZC030x.dll。
系統(tǒng)自動加載驅(qū)動程序時,首先要將驅(qū)動程序復(fù)制到\WINDOWS文件夾下,然后向注冊表中寫入攝像頭的驅(qū)動信息:
其中,prefix為設(shè)備文件名,D11為驅(qū)動的文件名,Order為設(shè)備文件名索引。硬件配置完成后啟動操作系統(tǒng),就可以自動加載驅(qū)動,運行應(yīng)用程序進行圖像采集了。
3.2圖像采集程序
中星微攝像頭采用了中星微301PLUS快速主控芯片。該芯片是一款高性能圖像壓縮芯片,輸出MIPEG視頻流數(shù)據(jù)。MIPEG(MotionJPEG)主要是基于靜態(tài)視頻壓縮發(fā)展起來的技術(shù),特點是基本不考慮視頻流中不同幀之間的變化,只單獨對某一幀進行壓縮,通常可達到6:1的壓縮率。它的誤差穩(wěn)定性非常好,可以獲取清晰度很高的視頻圖像,而且還可以靈活設(shè)置各路視頻清晰度,壓縮幀數(shù)。
本系統(tǒng)直接從攝像頭驅(qū)動中獲取MJPEG視頻流數(shù)據(jù),圖像采集流程如圖3所示。
圖像采集模塊用到的主要函數(shù)有:
capInitCamera()用來初始化視頻設(shè)備,并獲取當(dāng)前可用的視頻設(shè)備數(shù)目;
capSetVideoFormat()設(shè)置視頻格式和分辨率。本系統(tǒng)使用的視頻格式為RGB24,分辨率為320×240像素;
capGrabFrsme()從驅(qū)動中抓取1幀圖像,并存儲在緩存lpFrameBuffer中;
capGetLastJpeg()將抓取的MJPEG格式的圖像轉(zhuǎn)換成JPEG格式,送到無線發(fā)送模塊。
capCloseCamera()關(guān)閉視頻設(shè)備;
視頻采集部分還有查詢視頻采集格式、設(shè)置明暗度、設(shè)置對比度等相關(guān)函數(shù),不再詳述。
4視頻傳輸部分
4.1配置無線網(wǎng)卡
圖像傳輸模塊主要是通過USB接口的無線網(wǎng)卡來實現(xiàn)的。該無線網(wǎng)卡可與S3C2410集成的USB主機接口直接相連,工作在2.4GHz的ISM頻段,采用直接序列擴頻通信方式,遵從802.11g協(xié)議,傳輸速度可達54Mbps,室內(nèi)有效距離為100m,能夠滿足局域網(wǎng)內(nèi)視頻傳輸?shù)囊蟆1鞠到y(tǒng)通過開發(fā)板和主機之間的無線網(wǎng)卡構(gòu)建無線局域網(wǎng)絡(luò),能夠?qū)崿F(xiàn)點對點的無縫連接,用戶通過此無線網(wǎng)絡(luò)可以實現(xiàn)文件傳輸、視頻通信等應(yīng)用。
開發(fā)板端的無線網(wǎng)卡也需要加載驅(qū)動才能運行。本系統(tǒng)在定制WinCE操作系統(tǒng)時,首先將無線網(wǎng)卡的驅(qū)動程序復(fù)制到\WINDOWS文件夾下,然后向注冊表中寫入無線網(wǎng)卡的驅(qū)動信息。WinCE操作系統(tǒng)啟動后會自動檢測無線網(wǎng)卡是否連接好,并加載驅(qū)動程序,此時,就可以通過應(yīng)用程序調(diào)用此無線網(wǎng)卡了。在無線傳輸時,注意要把開發(fā)板和主機設(shè)置在同一IP網(wǎng)段。
4.2傳輸視頻數(shù)據(jù)
實時傳輸協(xié)議RTP(RealtimeTransportProtocol)是一種實時流式傳輸協(xié)議,能夠保證媒體信號帶寬與當(dāng)前網(wǎng)絡(luò)狀況相匹配,在一對一(umcast,單播)或者一對多(multicast,多播)的網(wǎng)絡(luò)環(huán)境中實現(xiàn)流媒體數(shù)據(jù)的實時傳輸。RTP通常使用UDP來進行多媒體數(shù)據(jù)的傳輸。整個RTP協(xié)議由兩個密切相關(guān)的部分組成:RTP數(shù)據(jù)協(xié)議和RTCP控制協(xié)議。
WinCE中的GWES模塊負(fù)責(zé)加載和管理Touch Panel驅(qū)動,Touch Panel的MDD層向上提供DDI接口,PDD層是針對硬件的實現(xiàn),對MDD層提供DDSI接口。
1 Touch Panel驅(qū)動中的數(shù)據(jù)結(jié)構(gòu)
(1) TOUCH_PANEL_SAMPLE_FLAGS
用于描述一個采樣點的信息,這些信息被定義在一個枚舉結(jié)構(gòu)中:
enum enumTouchPanelSampleFlags {
TouchSampleValidFlag = 0x01,
TouchSampleDownFlag = 0x02,
TouchSampleIsCalibratedFlag = 0x04,
TouchSamplePreviousDownFlag = 0x08,
TouchSampleIgnore = 0x10,
TouchSampleMouse = 0x40000000
};
TouchSampleValidFlag:一個有效的采樣值
TouchSampleDownFlag:第一次按觸摸屏?xí)r,返回該flag
TouchSampleIsCalibratedFlag:采樣的x和y坐標(biāo)值不需要再被校驗了
TouchSamplePreviousDownFlag:表示上一次采樣狀態(tài)是按在觸摸屏上
TouchSampleIgnore:忽略這次采樣值
TouchSampleMouse:預(yù)留
(2) TPDC_CALIBRATION_POINT
用于描述一個校驗點的相關(guān)信息,結(jié)構(gòu)如下:
struct TPDC_CALIBRATION_POINT {
INT PointNumber;
INT cDisplayWidth;
INT cDisplayHeight;
INT CalibrationX;
INT CalibrationY;
};
PointNumber:校驗點索引值,用于描述校驗點在LCD上的位置
0:中間
1:左上
2:左下
3:右下
4:右上
cDisplayWidth:顯示的寬度
cDisplayHeight:顯示的高度
CalibrationX:校驗點的x坐標(biāo)值
CalibrationY:校驗點的y坐標(biāo)值
(3) TPDC_CALIBRATION_POINT_COUNT
用于描述需要校驗的點的個數(shù),結(jié)構(gòu)如下:
struct TPDC_CALIBRATION_POINT_COUNT {
DDI_TOUCH_PANEL_CALIBRATION_FLAGS flags;
INT cCalibrationPoints;
};
flags:一般為0
cCalibrationPoints:需要校驗的點的個數(shù),一般是5
(4) gIntrTouch和gIntrTouchChanged
這是兩個被MDD層用到的中斷,需要在PDD層中定義,如下:
DWORD gIntrTouch = SYSINTR_NOP;
DWORD gIntrTouchChanged = SYSINTR_NOP;
gIntrTouch用于描述觸摸屏中斷,要和硬件的觸摸屏中斷相關(guān)聯(lián)。
gIntrTouchChanged用于在觸摸屏按下后,每隔一段時間進行一次采樣,應(yīng)該和硬件的一個定時器中斷相關(guān)聯(lián)。
這兩個值應(yīng)該在DdsiTouchPanelEnable(..)函數(shù)中和硬件中斷關(guān)聯(lián),并在函數(shù)DdsiTouchPanelGetPoint(..)中根據(jù)情況清除相應(yīng)的中斷。
2 MDD層API
MDD為上層導(dǎo)出所需的Touch Panel驅(qū)動接口函數(shù),上層通過這些函數(shù)可以完成對Touch Panel的操作,下面會介紹這些函數(shù)的功能。
(1) BOOL TouchPanelEnable(PFN_TOUCH_PANEL_CALLBACK pfnCallback):
使能Touch Panel設(shè)備,用于初始化Touch Panel。
pfnCallback:指向處理Touch Panel事件的回調(diào)函數(shù)
(2) Void TouchPanelDisable(void):
禁用Touch Panel設(shè)備。
(3) BOOL TouchPanelGetDeviceCaps(INT iIndex, LPVOID lpOutput ):
獲得Touch Panel設(shè)備的相關(guān)信息。
iIndex:索引值
TPDC_SAMPLE_RATE_ID:采樣率信息
TPDC_CALIBRATION_POINT_COUNT_ID:采樣點個數(shù)信息
TPDC_CALIBRATION_POINT_ID:采樣點坐標(biāo)信息
lpOutput:指向一個內(nèi)存區(qū)域,用于存放獲得的相關(guān)信息
(4) VOID TouchPanelCalibrateAPoint(INT32 UncalX, INT32 UncalY, INT32* pCalX, INT32* pCalY):
將輸入的未經(jīng)過校驗的坐標(biāo)信息轉(zhuǎn)換成校驗后的坐標(biāo)信息。
UncalX:輸入的X坐標(biāo)
UncalY:輸入的Y坐標(biāo)
pCalX:校驗后的X坐標(biāo)
pCalY: 校驗后的Y坐標(biāo)
(5) VOID TouchPanelPowerHandler(BOOL bOff):
Touch Panel的電源控制函數(shù)。
bOff:TRUE表示關(guān)閉電源,F(xiàn)ALSE表示打開電源
(6) BOOL TouchPanelReadCalibrationPoint(INT* pRawX, INT* pRawY):
獲得Touch Panel的坐標(biāo)。
pRawX:觸摸屏的X坐標(biāo)
PRawY:觸摸屏的Y坐標(biāo)
(7) VOID TouchPanelReadCalibrationAbort(void):
終止當(dāng)前的校驗。
(8) VOID TouchPanelSetCalibration(INT32 cCalibrationPoints, INT32* pScreenXBuffer, INT32* pScreenYBuffer, INT32* pUncalXBuffer, INT32* pUncalYBuffer):
]]>由于嵌入式設(shè)備硬件平臺的多樣性,CPU芯片的快速更新,嵌入式操作系統(tǒng)要求支持常用的嵌入式CPU,如X86, ARM, MIPS, POWERPC等,并具有良好的可移植性。另外還需要支持種類繁多的外部設(shè)備。Linux支持以上幾乎所有的主流芯片,并且還在不斷的被移植到新的芯片上。而在這方面,WinCE顯然差得很遠。
2.占有較少的硬件資源
由于多數(shù)嵌入式系統(tǒng)具有成本敏感性,處理器速度較低 ,存儲器空間較少,這要求嵌入式OS體積小,速度快。Linux體系結(jié)構(gòu)比較靈活,易于裁減,可以小到2M flash,4M RAM。而WinCE對資源的要求更高。
3.高可定制性
由于不同的嵌入式應(yīng)用對系統(tǒng)要求各不相同,這要求嵌入式OS具備高可定制性,能夠根據(jù)需要方便的增加和減少各項功能模塊。這一點對于嵌入式領(lǐng)域至關(guān)重要,而Linux由于圖形系統(tǒng)不在內(nèi)核中,且支持模塊機制,內(nèi)核可根據(jù)需要加入或去掉功能。其外圍工具擁有眾多選擇,更由于可以自由修改源代碼,具有極強的可定制性。而WinCE/Windows根本無法做到這一點。
4.具有實時處理能力
]]>在事隔Windows Embedded CE 5.0推出兩年后,微軟新版Windows Embedded CE 6.0反應(yīng)這個嵌入式操作系統(tǒng)后起之秀加緊腳步的決心。 其一的最大作為就是迎擊Linux、Wind River陣營長期以來對其定制化不足的攻擊。
微軟臺灣營銷經(jīng)理許妙華表示,Win CE 6.0的核心源代碼將悉數(shù)開放予硬件合作伙伴,供其修改源代碼開發(fā)客制化的文件系統(tǒng)、設(shè)備驅(qū)動程序與其他元件,而不需分享他們的最終設(shè)計給微軟或第三方。
另外,加快產(chǎn)品開發(fā)時程也是Win CE 6.0的一大躍進。許妙華指出,Visual Studio Visual Studio 2005專業(yè)版將包含在Win CE 6.0的開發(fā)工具中。
而Platform Builder成為Visual Studio 2005專業(yè)版的外掛程序(plug-in),協(xié)助設(shè)計人員完成從嵌入式操作系統(tǒng)客制化到應(yīng)用程序開發(fā)等所有工作,縮短產(chǎn)品開發(fā)的上市時程。
WinCE 6.0現(xiàn)已開始提供合作伙伴下載。根據(jù)微軟所述,許多廠商將在本季推出基于新的WinCE 6.0的應(yīng)用產(chǎn)品,臺灣地區(qū)的合作伙伴包括了精技電腦、研華科技、威盛電子等。產(chǎn)品內(nèi)容則涵蓋了便攜式導(dǎo)航設(shè)備、媒體播放器、遠端監(jiān)視設(shè)備、IP網(wǎng)絡(luò)電話與游戲機等。
WinCE是微軟針對嵌入式系統(tǒng)產(chǎn)品開發(fā)的精簡型操作系統(tǒng)。微軟約在十年前進入這個領(lǐng)域。所謂的嵌入式產(chǎn)品包括了智能手機、PDA、機頂盒(Set- top-box)等具有運算能力的設(shè)備。
在智能手機領(lǐng)域里,微軟的競爭對手包含了Symbian和Linux;在其他嵌入式設(shè)備市場,Linux亦和微軟有所角力。
雖然微軟穩(wěn)坐桌面操作系統(tǒng)龍頭寶座,但是相較其在嵌入式系統(tǒng)市場所遭遇到的對手——Linux和Wind River,微軟一直到前年才終于超越Linux成為第一大的嵌入式操作系統(tǒng)廠商;惟在針對手持設(shè)備所推出的Windows Mobile操作系統(tǒng),微軟在這塊市場的占有比例還甚小。
此次微軟宣布源代碼開放并非首樁,不過確是微軟難得的大動作。該公司在WinCE 4.2版時,也曾提供開放源代碼,不過只針對研究單位,而源代碼較少,為200萬行。
在兩年前推出WinCE 5.0時,則開放250萬行源代碼程序作為評估套件(evaluation kit),凡是個人、廠商都可以下載這些源代碼加以修改使用。
“分享的源代碼比前一版本的Windows Embedded CE大幅增加56%,”許妙華說。
雖然開放分享源代碼,可望提高微軟OEM客戶定制化的能力,但是微軟長期以來另一被詬病之處——授權(quán)費過高的問題仍未獲解決。對此微軟仍重提時間就是成本的優(yōu)勢。
微軟亞洲區(qū)嵌入式系統(tǒng)事業(yè)部暨全球ODM Ecosystems資深副總經(jīng)理吳勝雄指出,WinCE嵌入式系統(tǒng)產(chǎn)品平均開發(fā)時間為8個月,若以Linux開發(fā)則平均得拉長至14個月。
此外WinCE具有各式各樣的模組,在Linux上可能得自行開發(fā)或另外授權(quán),事實上Linux不見得免費或比較便宜,嵌入式系統(tǒng)廠商必須以上市時間等整體開發(fā)成本為考慮。
除源代碼全數(shù)開放、與Visual Studio開發(fā)工具整合外,許妙華表示,WinCE 6.0可同時支持32,000個程序和每個程序高達2GB的虛擬內(nèi)存定址空間,且保有軟件的實時(real-time)功能。讓開發(fā)人員可將更多應(yīng)用程序加入更復(fù)雜的設(shè)備
]]>