《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 其他 > 業(yè)界動態(tài) > VB環(huán)境下實現(xiàn)PCI設(shè)備底層訪問的兩種方法

VB環(huán)境下實現(xiàn)PCI設(shè)備底層訪問的兩種方法

2009-04-10
作者:姜萬波 徐 興

  摘? 要: 介紹了在VB開發(fā)環(huán)境下,,對PCI設(shè)備進行底層訪問的兩種方法:一是通過調(diào)用用戶自己編寫的動態(tài)連接庫(DLL)實現(xiàn),,二是利用WINDRIVER提供的VB運行庫編寫直接訪問硬件的接口函數(shù),并對兩種方法進行了比較。

  關(guān)鍵詞: WINDRIVER? PCI 動態(tài)連接庫 應(yīng)用程序接口

?

  VB集成化編程語言是一種功能強大而又容易上手的開發(fā)工具,。在用戶界面、數(shù)據(jù)庫,、多媒體,、網(wǎng)絡(luò)編程等方面,VB可謂得心應(yīng)手。然而VB有限的硬件編程能力又使得許多硬件開發(fā)者對此深感無奈,。尤其在工業(yè)控制,,測控技術(shù)等領(lǐng)域,自行設(shè)計開發(fā)的I/O卡,,數(shù)據(jù)采集卡等在WIN32下的驅(qū)動常常需要借助DDK,, VtoolsD等工具進行艱苦而又長期的內(nèi)核模式開發(fā)。本文介紹了在VB開發(fā)環(huán)境下訪問PCI設(shè)備的方法,。對于其他設(shè)備,,方法與此大同小異。

  在VB開發(fā)環(huán)境下,,用戶要訪問諸如數(shù)據(jù)采集卡之類硬件上的PCI設(shè)備,,一般來說有兩種途徑:一是直接訪問,即用VB直接編寫訪問PCI設(shè)備的接口函數(shù)(這種方法需要有相關(guān)軟件的支持);二是間接訪問,,即VB調(diào)用其它編程語言(如匯編,,C/C++等)寫的底層驅(qū)動模塊(一般封裝成動態(tài)連接庫DLL的形式)實現(xiàn)。

1 PCI總線的配置空間

  PCI規(guī)范定義了三種地址空間,,除了存儲器和I/O地址空間外,,為支持PCI設(shè)備系統(tǒng)資源的自動配置,還定義了配置地址空間,。

  PCI總線的配置空間由256個字節(jié)組成,,分為預(yù)定首區(qū)和設(shè)備關(guān)聯(lián)區(qū)。預(yù)定首區(qū)包括開始64個字節(jié),,對所有的PCI設(shè)備來說,,都必須支持該區(qū)的設(shè)置;設(shè)備關(guān)聯(lián)區(qū)的寄存器有不同的PCI設(shè)備廠家自己定義。

  配置空間的預(yù)定首區(qū)分兩個部分,,前16個字節(jié)的定義對各類PCI設(shè)備而言都是相同的,,后48個字節(jié)空間根據(jù)設(shè)備支持的功能有不同的分配。首區(qū)類型定義了該空間的分配情況(目前只有一種類型00H),。表1是首區(qū)的組織結(jié)構(gòu),。

?

  所有的PCI設(shè)備必須支持首區(qū)中的供應(yīng)商ID、設(shè)備ID,、指令和狀態(tài)區(qū),。對于其他寄存器的使用可根據(jù)設(shè)備的功能來選擇。對于不同的PCI設(shè)備,,其供應(yīng)商ID由PCI SIG分配以確保唯一性,,而設(shè)備ID則由供應(yīng)商自己分配。

2 PCI設(shè)備的配置過程

  PCI總線的配置空間規(guī)范保證了所有PCI設(shè)備對“即插即用”的支持,。

  系統(tǒng)在上電后,,“即插即用”BIOS通過隔離算法讀取每一個“即插即用”設(shè)備的資源申請數(shù)據(jù),,并分配相應(yīng)的系統(tǒng)資源,同時檢查資源的沖突情況,,然后引導(dǎo),、加載操作系統(tǒng),并將控制權(quán)交給操作系統(tǒng);如果加載的是“即插即用”操作系統(tǒng)(WINDOWS 95及以后版本),,那么操作系統(tǒng)將接管系統(tǒng)的資源管理權(quán),,它首先從BIOS讀取“即插即用”設(shè)備的資源配置信息,并仲裁資源沖突情況,,然后配置BIOS尚未配置的“即插即用”設(shè)備,,將設(shè)備的配置信息寫入配置管理器,最后激活無資源沖突的“即插即用”設(shè)備,,裝載相應(yīng)的設(shè)備驅(qū)動程序,。???

  對于PCI設(shè)備來說,系統(tǒng)完成引導(dǎo)之后,,除了將資源的分配寫入系統(tǒng)的配置管理器外,,還寫入了相應(yīng)的PCI配置寄存器。程序可以通過直接讀取設(shè)備的配置寄存器來得到設(shè)備的I/O,,存儲器等資源配置情況,。

3 VB下PCI設(shè)備的訪問

  驅(qū)動程序訪問PCI設(shè)備的過程一般包括掃描PCI總線,查找指定的PCI設(shè)備,,確定I/O等資源分配情況,,進行I/O、存儲器,、中斷以及DMA等操作,。VB本身并不能實現(xiàn)上述對PCI設(shè)備的訪問過程,下面介紹在VB下通過其他途徑實現(xiàn)對PCI設(shè)備的訪問,。

3.1 VB直接訪問

  由于VB只提供了非常有限的I/O訪問能力(如串口通信),,在VB下直接訪問PCI設(shè)備時需要借助其它軟件。目前WINDRIVER提供這方面的支持,。WINDRIVER是KRFTech公司主推產(chǎn)品,,是許多PCI廠家所推薦的首選驅(qū)動程序開發(fā)工具。??

WINDRIVER為VB 4.0以上版本提供了一個類模塊(WINDRAR.CLS),,利用這個類模塊,,用戶可以手工編寫自己所需的接口函數(shù)來訪問相應(yīng)的設(shè)備,。下面以具體例子來說明WINDRAR.CLS的使用方法,。

3.1.1 掃描PCI總線得到指定設(shè)備的數(shù)目

  利用WINDRAR.CLS提供的應(yīng)用程序接口函數(shù)(APIs),編寫一個掃描PCI總線,,獲得指定PCI設(shè)備數(shù)目的函數(shù)如下:

  Function GetCardsNum(dwVendorID As

  Long,, dwDeviceID As Long) As Integer

  Dim pciScan As WD_PCI_SCAN_CARDS

  Dim hWD As Long

  hWD = WD_Open()

  If hWD = INVALID_HANDLE_VALUE Then?

?????? MsgBox ″設(shè)備打開出錯!″

?????? Exit Function

  End If

  pciScan.searchId.dwVendorID =

?????? dwVendorID

?????? pciScan.searchId.dwDeviceID =

?????? dwDeviceID

  WD_PciScanCards hWD, pciScan

  WD_Close (hWD)

  GetCardsNum = pciScan.dwCards

  End Function???????????????

  該函數(shù)可以通過輸入?yún)?shù):PCI設(shè)備的供應(yīng)商ID和設(shè)備ID得到所需的PCI設(shè)備數(shù)目。如查找AMCC公司的PCI適配芯片S5933,,則輸入?yún)?shù)為:&H10E8和&H4750,。

  下面例子用于讀寫S5933的PCI配置寄存器。在工程的全局模塊中需要先定義下列數(shù)據(jù)結(jié)構(gòu),,同時設(shè)備必須處于打開狀態(tài),。

  Type??AMCC_INTERRUPT

??????   Int As WD_INTERRUPT????

??????  hThread As Long

??????  Trans(0 To 1) As WD_Transfer

  End Type

  Type AMCC_ADDR_DESC

?     dwLocalBase As Long

?     dwMask As Long

?     dwBytes As Long

?     dwAddr As Long

?     dwAddrDirect As Long

?     fIsMemory As Boolean

  End Type

  Type AMCC_STRUCT

?     hWD As Long

?     cardLock As WD_CARD

?     pciSlot As WD_PCI_SLOT

?     cardReg As WD_CARD_REGISTER

?     addrDesc(0 To AD_PCI_BARS - 1) As

??????????AMCC_ADDR_DESC

?     fUseInt As Boolean

?     Int As AMCC_INTERRUPT

  End Type

3.1.2 讀寫PCI配置寄存器

  完成以上數(shù)據(jù)結(jié)構(gòu)的定義后,用下面的函數(shù)可讀寫S5933的PCI配置寄存器內(nèi)容,。

  Function AMCC_ReadPCIReg( hAmcc As

  AMCC_STRUCT,, dwReg As Long)

  Dim pciCnf As WD_PCI_CONFIG_DUMP?

  Dim dwVal As PVOID?

  pciCnf.pciSlot = hAmcc.pciSlot?

  pciCnf.pBuffer = dwVal?

  pciCnf.dwOffset = dwReg?

  pciCnf.dwBytes = 4?

  pciCnf.fIsRead = True?

  WD_PciConfigDump hAmcc.hWD, pciCnf?

  AMCC_ReadPCIReg = dwVal?

  End Function? ?? ‘讀函數(shù)?

  Sub AMCC_WritePCIReg(hAmcc As ?

  AMCC_STRUCT,, dwReg As Long,, dwData As PVOID)

????????????? Dim pciCnf As WD_PCI_CONFIG_DUMP?

????????????? pciCnf.pciSlot = hAmcc.pciSlot?

?????? ?????? pciCnf.pBuffer = dwData?

????????????? pciCnf.dwOffset = dwReg?

????????????? pciCnf.dwBytes = 4?

????????????? pciCnf.fIsRead = False?

????????????? WD_PciConfigDump hAmcc.hWD, pciCnf?

  End Sub???????? ‘寫過程

  · 參數(shù)說明:

  hAMCC????? 設(shè)備打開后系統(tǒng)分配的句柄

  dwReg????? 讀寫的PCI配置寄存器

????dwVal????? 讀出的寄存器數(shù)據(jù)??????

  dwData?? 寫入寄存器的數(shù)據(jù)

  以上例子僅僅是拋磚引玉,。WINDRAR.CLS類模塊提供了功能極為強大的底層驅(qū)動的API函數(shù),,用戶通過編寫相應(yīng)的驅(qū)動模塊可以方便地實現(xiàn)對各類硬件的I/O、存儲器映射,、中斷以及DMA等操作,,同時可以實現(xiàn)WIN32下物理內(nèi)存空間的申請、讀寫等處理,。另外對于實時性要求較高的設(shè)備,,WINDRIVER提供的“內(nèi)插”(Plug-In)特性可以讓程序的相關(guān)模塊運行于Ring 0內(nèi)核模式(Kernel mode),以提高性能,。

  開發(fā)完成的底層驅(qū)動模塊既可直接為VB的應(yīng)用程序調(diào)用,,也可以在VB下封裝成DLLs供其它的WIN32開發(fā)工具調(diào)用。

3.2 自定義DLL訪問

  DLL使VB的功能得到極大的增強,,使得VB的應(yīng)用范圍不斷擴大,,使用更加靈活。VB通過調(diào)用自定義DLL可以實現(xiàn)對硬件的底層訪問,。下面用例子說明VB對DLL的調(diào)用及DLL的編寫過程,。

3.2.1 DLL的功能和編寫

  本例中的DLL通過掃描PCI總線,得到總線上S5933接口芯片的數(shù)目,,打開指定設(shè)備,,向S5933的輸入郵箱1中寫入命令字,然后從輸出郵箱1中讀取返回數(shù)據(jù),,最后關(guān)閉設(shè)備,。

  extern “C” _declspec(dllexport) int _stdcall GetCardsNum()

  {

AFX_MANAGE_STATE(AfxGetStaticModuleState());

?????? int cards;

?????? cards=AMCC_CountCards(0x10e8,0x4750);

?????? return cards;

}?????????????????? // 此函數(shù)得到S5933的數(shù)目;

extern “C” _declspec(dllexport) DWORD_stdcall SendCommand(int CardNum,,DWORD dwCmd)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

DWORD data;?????????????

If(AMCC_Open(&hAMCC,,0x10e8,,0x4750,?? CardNum,,0))??? // 打開指定設(shè)備

{?

AMCC_WriteRegDWord(hAMCC,,OMB1_ADDR,

dwCmd);??????? // 寫入命令字

?????? do{

?????? data=AMCC_ReadRegDWord(hAMCC,,MBEF_ADDR);

}while((data&0x000f0000)==0x00000000),;????

?????????????????????????????????? // 等待輸入郵箱1滿

data=AMCC_ReadRegDWord(hAMCC,IMB1_ADDR);???

?????????????????????????????????? // 讀取返回數(shù)據(jù)

?????? if(hAMCC)???? AMCC_Close(hAMCC);

??????????????????????????? // 關(guān)閉設(shè)備

?????? return data;

else

{ AfxMessageBox(“打開設(shè)備失敗?選”);

?????? ? return 0;}

程序中用到的函數(shù)包含在WINDRIVER的API函數(shù)庫中,,在VC++下編譯時加上頭文件:

#include “amcclib.h”

#include “amcclib.c”

  同時在DEF文件中列出DLL的導(dǎo)出函數(shù)名,,生成的DLL即可為VB所調(diào)用。讀者也可用其它工具編寫驅(qū)動模塊,,最后封裝成DLL即可,。

3.2.2 VB調(diào)用DLL

  VB調(diào)用動態(tài)連接庫(DLL)時,首先聲明DLL,,然后即可像調(diào)用VB的語句或函數(shù)一樣使用DLL中的例程,。下面介紹VB調(diào)用上例生成的DLL(假設(shè)文件名為Test.dll)。

· 聲明

  Public Declare Function GetCardsNum Lib “Test.dll” () As Integer

  Public Declare Function SendCommand Lib “Test.dll” (ByVal dwCmd as Long) As Long

  在聲明時需要注意:DLL的路徑;參數(shù)傳遞的方式;參數(shù)的類型,。

  另外,,VB遵從 _stdcall的參數(shù)傳遞約定,而VC++默認_cdecl的傳遞約定,,因此在DLL中的導(dǎo)出聲明需采用_stdcall的修飾符,。

  · 調(diào)用

  一旦聲明后,在VB的應(yīng)用程序中就可調(diào)用DLL中的例程,。如:

  Private Sub Form_Load()

  Dim CardsNum As Integer?

  CardsNum = GetCardsNum()?

?????? MsgBox “系統(tǒng)中有”+ Str(CardsNum)+“塊S5933插卡!”?

  End Sub?

  WINDRIVER包括了諸如AMCC,、Altera、PLX,、Galileo,、V3、PLDA等公司PCI芯片的專用C/C++的API函數(shù)庫,,其中包含了I/O讀寫,,內(nèi)存映射,中斷處理以及DMA等底層驅(qū)動的函數(shù),,可以非常方便地用VC++,,BC++以及C++ Builder等工具編譯成DLLs供VB調(diào)用。?

  本文提供了兩種在VB的開發(fā)環(huán)境下訪問PCI設(shè)備的方法,。第一種方法需要有WINDRIVER的VB運行庫支持,,可以在VB環(huán)境下直接編寫所需的接口函數(shù),但對WINDRAR.CLS類模塊中定義的內(nèi)核數(shù)據(jù)結(jié)構(gòu)要有較深的了解;第二種方法具有一定的靈活性,、普遍性,,編寫DLL的工具較多,,DLL除了可用于VB外,,還可用于其他的WIN32開發(fā)工具,,有較強的適應(yīng)性。

  以上方法在北京航空航天大學(xué)測控技術(shù)研究所研制的PHD2000高速并行數(shù)據(jù)采集系統(tǒng)中得到實際應(yīng)用,,取得了良好的效果,。

參考文獻

1 WinDriver V4 Developer's Guide.KRFTech 1997~1999

2 S5933 PCI Matchmaker Controller Data Book. Applied?Micro Circuits Corporation,1996

3 余永進譯.“即插即用”技術(shù)大全.北京:電子工業(yè)出版社
本站內(nèi)容除特別聲明的原創(chuàng)文章之外,,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,,并不代表本網(wǎng)站贊同其觀點。轉(zhuǎn)載的所有的文章,、圖片,、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認版權(quán)者,。如涉及作品內(nèi)容,、版權(quán)和其它問題,請及時通過電子郵件或電話通知我們,,以便迅速采取適當(dāng)措施,,避免給雙方造成不必要的經(jīng)濟損失。聯(lián)系電話:010-82306118,;郵箱:[email protected],。