英創ARM9工控主板的數據采集功能通常采用板上的GPIO實現數字輸入輸出、通過精簡ISA總線擴展相應的AD或DA實現模擬數據的輸入輸出。在英創ARM9工控主板提供的基本開發資料中對GPIO和精簡ISA總線的驅動均以C的靜態庫的形式提供,對部分使用C#、LabView等其他開發工具的客戶來說,不能直接使用C的API函數。針對這一部分客戶的應用需求,我們把相關C函數庫封裝成標準COM組件,使客戶能方便使用主板的數據采集功能。本文將詳細介紹數據采集COM組件的相關技術要點,供廣大客戶使用時參考。
COM(Component Object Model),即組件對象模型,是微軟公司開發的一種新的軟件開發技術,提出了組件之間進行交互的規范,也提供了實現交互的環境,因為組件對象之間交互的規范不依賴于任何特定的語言,所以COM也可以是不同語言協作開發的一種標準,如VB、C#、LabView可以使用同一個COM組件來進行軟件開發。COM組件的整體結構大概分為三個層次:組件、接口、方法函數,它們的關系如下圖所示:
COM組件與我們常用的C++類的關系,可以簡單的理解為:
COM組件名:即C++庫文件名稱
COM組件接口:即C++庫中的類
COM組件實現方法函數:即C++中的類的成員函數
下面以EM9000的EM9000_ISA_API.LIB靜態庫為例,介紹在EVC開發環境,如何在EM9000_ISA_API.LIB靜態庫的基礎上構建相應的COM組件,該方法也可同樣應用于英創公司的其他ARM9工控主板產品。
1、新建一個工程,在新建工程中選擇WCE ATL COM AppWizard,并給工程命名為“EM9000_ISA_API_COM”,工程會自動生成一個文件來。在工程編譯后,將生成“EM9000_ISA_API_COM.DLL”庫文件。這個文件就是要用的COM組件的目標文件。
2、設置好以后,點擊“OK”進入工程的類型選項,在這里,選擇動態鏈接庫并將對MFC的支持選擇上。即完成工程的建立。
3、將英創提供的EM9000_ISA_API.h文件復制到當前這個工程目錄下面,并在工程的“Settings”下面的LINK中加入“EM9000_ISA_API.lib”。
4、為COM組件添加接口:這個接口名就是在調用COM組件時的入口名字,在工程中命為EM9000_ISA_COM,添加接口的方法是:Insert -> New ALT Object…,在彈出來的對話框中,直接點擊下一步,這時會再彈出一個對話框,這時,在對話框的Name表單的左上角框中輸出接口名EM9000_ISA_COM,這時會生成相應的接口的名字,左邊是C++調用的頭文件及庫,右邊是COM組件的接口文件名。系統會自動地在接口名Interface項前加上一個大寫字符“I”。
5、為該COM組件添加方法函數:將EM9000_ISA_API.H中的函數添加到COM組件中去。要注意一點,由于在制作COM組件過程中,COM組件實現的方法函數會調用EM9000_ISA_API.H中的函數且方法函數名和要調用的函數不能同名,所以在COM組件的方法函數名前加前綴“COM_”以便區分。在工程的workspace的ClassView中,單擊COM組件的接口名“IEM9000_ISA_COM”并單擊右鍵選擇“Add Method…”,彈出添加方法函數的對話框。
如將EM9000_ISA_API.H中的GetPortState( int Port )函數添加進去。這里方法函數為就變為“COM_GetPortState”,參數則有兩個,一個是輸入參數,用[in]關鍵字說明,一個是函數返回值,用[out,retval]關鍵字說明,除了返回值的參數名外,其它的輸入輸出參數最好和函數的參數一樣。參數類型均為”long”,可以參考:http://www.vckbase.com/document/viewdoc/?id=1488。
輸入完畢后,點擊“OK”完成,這時可以看見新增加的這個方法函數出現在工程中了。雙擊接口名“IEM9000_ISA_COM”,就會看到該方法函數在文件中的定義:
interface IEM9000_ISA_COM : IDispatch
{
[id(1), helpstring('method COM_GetPortState')] HRESULT COM_GetPortState([in] long Port , [out,retval] long *pVal);
};
6、雙擊CEM9000_COM下的IEM9000_ISA_COM的方法函數名“COM_GetPortState(long Port,Long *Val)”,這時就打開具體實現的源文件EM9000_ISA_COM.CPP文件。在文件中加入:#include 'EM9000_ISA_API.h',并且在FileView的頭文件中加入該文件。
這時將COM_GetPortState方法函數的實現完成,即調用EM9000_ISA_API.h中相應的函數完成功能。
STDMETHODIMP CEM9000_ISA_COM::COM_GetPortState(long Port, long *pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
*pVal = GetPortState( Port );
return S_OK;
}
到這里,就完成了對靜態庫中的一個函數轉成COM組件的方法函數的基本操作,依照上述方法,將其它的函數需要加入到COM組件中,只需重復第5、6步的操作就行了。注意,最后還需要加入出錯處理的方法函數:
方法函數名:_com_issue_errorex
參數:HRESULT _hr1 , IUnknown *pthis1 , const GUID refiid1
通過編譯生成COM組件EM9000_ISA_API_COM.dll。
我們所提供的COM組件“EM9000_ISA_API_COM.dll”的文件說明:
COM組件文件名:EM9000_ISA_API_COM.dll
COM組件接口名:EM9000_ISA_COM
COM組件方法函數和EM9000_ISA_API靜態庫函數的對應關系如下:
COM組件方法函數名 |
庫態庫函數名 |
功能描述 |
COM_InitEM9000ISA( ) | InitEM9000ISA( ) | 初始化EM9000的ISA總線 |
COM_GetPortState( int Port ) | GetPortState( int Port ) | 查詢Port設置狀態 |
COM_Swap2ISA( int Port ) | Swap2ISA( int Port ) | 把Port設置為ISA總線 |
COM_Swap2DIO( int Port ) | Swap2DIO( int Port ) | 把Port設置為DIO功能 |
COM_SetPortDir( int Port, int Mode ) | SetPortDir( int Port, int Mode ) | 把Port對應管腳設置為DIO狀態 |
COM_EM9000_INB( int Port ) | EM9000_INB( int Port ) | 把Port對應管腳設置為DIO狀態 |
COM_EM9000_OUTB( int Port, UCHAR Value ) | EM9000_OUTB( int Port, UCHAR Value ) | 把Value輸出到Port對應管腳 |
COM_EM9000_READ( int nSeg, UINT nOffset ) | EM9000_READ( int nSeg, UINT nOffset ) | 從ISA擴展總線某地址讀取一個字節的數據 |
COM_EM9000_WRITE( int nSeg, UINT nOffset, UCHAR Value ) | EM9000_WRITE( int nSeg, UINT nOffset, UCHAR Value ) | 向ISA擴展總線某地址寫入一個字節的數據 |
COM_EM9000_ResetISA( int milliseconds ) | EM9000_ResetISA( int milliseconds ) | 使RSTOUT#輸出低脈沖milliseconds毫秒 |
COM_EM9000_PWMOUT( int ChIdx, float* pFreq, float* pDuty ) | EM9000_PWMOUT( int ChIdx, float* pFreq, float* pDuty ) | 使能并輸出脈寬調制信號 |
COM_EM9000_PWMSTOP( int ChIdx ) | EM9000_PWMSTOP( int ChIdx ) | 停止輸出脈寬調制信號 |
COM_EM9000_StartWatchDog( ) | EM9000_StartWatchDog( ) | 啟動系統WATCH DOG TIMER |
COM_EM9000_KicktheDog( ) | EM9000_KicktheDog( ) | 重載系統WATCH DOG TIMER |
COM_EM9000_ResetBy( ) | EM9000_ResetBy( ) | 返回上次復位產生的原因 |
COM_EM9000_DelayInUs(int MicroSeconds ) | EM9000_DelayInUs(int MicroSeconds ) | 微秒延時 |
下面以EVC開發環境為基于MFC編程,調用EM9000_ISA_API_COM.dll實現GPIO操作為例,對如何使用COM組件“EM9000_ISA_API_COM.dll”進行說明,以更指導客戶方便地使用COM組件來完成自有產品的開發。
在eVC中調用COM組件,需按如下基本步驟來完成:
1、注冊COM組件
運行英創公司提供的regsvr32程序進行COM組件的注冊
2、初始化組件,并創建一個實體對像
(1)在測試文件的頭文件中,先定義所需要的對像及變量:
首先,先將COM組件EM9000_ISA_API_COM.dll文件放在當前的工程目錄下,同時要在工程的StdAfx.h文件中,添加導入COM組件文件的語句:
#import “EM9000_ISA_API_COM.dll” no_namespace
// 如果COM組件文件沒在當前應用的工程目錄下面,則需要寫出COM組件文件所在的路徑
然后在測試工程文件頭COM_TESTDlg.h中,在CCOM_TESTDlg類中進行定義:
private:
CLSID clsid; // 用以緩存所查詢到的COM組件的標識
IEM9000_ISA_COM *m_pSimple; // 利用COM組件接口定義一個指針
(2)完成COM組件的初始化:
在測試工程文件COM_TESTDlg.cpp中,在BOOL CCOM_TESTDlg::OnInitDialog()過程中完成初始化部份
HRESULT hr;
CoInitializeEx(NULL,COINIT_MULTITHREADED) ;//初始化COM組件以便創建線程
Hr = CLSIDFromProgID( OLESTR ( 'EM9000_ISA_API_COM. EM9000_ISA_COM ' ) , &clsid );
// 查找組件是否存在,并獲取組件的標識,這里的參數為:COM組件名字.接口名
C, oCreateInstance ( clsid , NULL , CLSCTX_INPROC_SERVER , _uuidof ( I EM9000_ISA_COM ) , ( void** ) &m_pSimple );
// 利用查找組件時所獲得的標識創建實體對像,并交給指針。這里的第四個參數為組件的接口名
3、調用COM組件中的方法函數
利用, , 所定義的接口指針*m_pSimple,在事件中調用相應的函數。如要調用COM_GetPortState方法函數來獲取GPIO(P4口)的狀態,則可以如下方式來實現調用:
#define P4 4
int iState ;
iState= m_pSimple-> COM_GetPortState (P4); // 調用成員函數讀出GPIO(P4口)的狀態
4、當使用后,應當釋放COM組件
CoUninitialize(); // 釋放COM組件
-
嵌入式主板
+關注
關注
7文章
6085瀏覽量
35434
發布評論請先 登錄
相關推薦
評論