新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > PC并行端口作為數(shù)字I/O口的應用

        PC并行端口作為數(shù)字I/O口的應用

        作者: 時間:2011-11-24 來源:網(wǎng)絡 收藏

        三、PC并行口數(shù)字輸入/輸出

          所謂的數(shù)字輸出就是在程序要求某一個設備的某一開關點開或關,產(chǎn)生高電位或低電位。從計算機的觀點來說,低電位就是0.7V以下(邏輯0),而高電位是2.1V以上(邏輯1),若電位處在0.7~2.1V時,電位的邏輯狀態(tài)是不確定的。想要通過計算機去控制外部設備,最簡單的方法就是控制數(shù)字輸出。

          所謂的數(shù)字輸入,也就是外界的狀況被計算機用0或1的數(shù)值予以記錄下來而儲存,此0與1就代表了外界某一個設備的某一開關點開或關的兩種情形。

          PC并行口即可以作數(shù)字輸出口,也可以作數(shù)字輸入口。其中的數(shù)據(jù)端口、控制端口都可以作為數(shù)字輸出端口,數(shù)據(jù)端口共8位,控制端口共4位,兩個端口可以組成1~12位的任意數(shù)字輸出端口;其中的狀態(tài)端口、控制端口都可以作為數(shù)字輸入端口,狀態(tài)端口共5位,控制端口共4位,兩個端口可以組成1~9位的任意數(shù)字輸入端口。本文給出了3種寄存器的讀寫方法,如下圖所示:

          

        PC并行端口作為數(shù)字I/O口的應用

          四、PC并行口數(shù)字輸入/輸出的VC實現(xiàn)

          由于Windows對系統(tǒng)底層操作采取了屏蔽的策略,因而對用戶而言,系統(tǒng)變得更為安全,但這卻給眾多的硬件或者系統(tǒng)軟件開發(fā)人員帶來了不小的困難,因為只要應用中涉及到底層的操作,開發(fā)人員就不得不深入到Windows的內(nèi)核去編寫屬于系統(tǒng)級的設備驅(qū)動程序。對并行口的讀寫操作就是如此,由于Windows對系統(tǒng)的保護,絕對不允許任何的直接I/O動作發(fā)生,所以必須帶上*.dll、*.sys或*.vxd文件,這些文件用來讓操作系統(tǒng)知道有一個特定的I/O可能會被調(diào)用。系統(tǒng)開機后,這些文件中的內(nèi)容就會加載到內(nèi)存中,一旦有對應的動作發(fā)生,就會引發(fā)I/O的實際動作。

          本文只是介紹并行口作為數(shù)字I/O口的使用,不在于介紹并行I/O口驅(qū)動的編寫。故本文中直接使用由 Yariv Kaplan 編寫的 WinIo 庫,它有如下特點:WinIo 庫通過使用內(nèi)核模式下設備驅(qū)動程序和 其它一些底層編程技巧繞過 Windows 安全保護機制,允許32位 Windows 程序直接對 I/O 口進行操作。

          支持Windows 9x、Windows NT、Windows2000、WindowsXP環(huán)境;在Windows NT/2000/XP下,允許非 Administrator 用戶應用 WinIo 應用程序;不支持中斷。

          注意事項:使用這個類代碼時請確保不要與其它使用常規(guī) Win32 調(diào)用操作的程序發(fā)生沖突。

          WinIo庫在VC應用程序中的使用(WinIo庫下載)

          為了在VC中能正常使用WinIo庫,必須按以下步驟進行配置:

          (1):將WinIo.dll、WinIo.sys、WINIO.VXD三個文件放在程序可執(zhí)行文件所在目錄下;

          (2):將WinIo.lib添加到工程中,WinIo.lib及winio.h文件必須放在工程目錄下;

          (3):在StdAfx.h頭文件中加入#include "winio.h"語句;

          (4):調(diào)用InitializeWinIo函數(shù)初始化WinIo驅(qū)動庫;

          (5):調(diào)用讀寫IO口的GetPortVal或SetPortVal函數(shù);

          (6):調(diào)用ShutdownWinIo函數(shù);

          在非管理員權(quán)限下運行,必須首先完成以下步驟:

          (1):將WinIo.dll、WinIo.sys、WINIO.VXD三個文件放在任一WinIo應用程序可執(zhí)行文件所在目錄下;

          (2):以管理員或其它具有管理員權(quán)限的用戶身份登陸;

          (3):調(diào)用InstallWinIoDriver函數(shù),第一個參數(shù)設置為WinIo.sys文件所在目錄路徑,第二個參數(shù)設置為false;

          (4):重新啟動系統(tǒng);

          (5):以普通用戶身份登錄,現(xiàn)在可以調(diào)用WinIo庫函數(shù);

          (6):當不再需要WinIo庫時,可以再次以管理員身份或其它具有管理員權(quán)限的用戶身份登陸系統(tǒng),調(diào)用RemoveWinIoDriver卸載該庫;

          WinIo庫中幾個函數(shù)說明:

          (1):初始化與終止

          bool _stdcall InitializeWinIo();

          void _stdcall ShutdownWinIo();

          (2):安裝與卸載

          bool _stdcall InstallWinIoDriver(PSTR pszWinIoDriverPath, bool IsDemandLoaded = false);

          bool _stdcall RemoveWinIoDriver();

          (3):讀寫I/O口

          bool _stdcall GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize);

          bool _stdcall SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize);

          GetPortVal函數(shù)從指定端口讀取一個BYTE/WORD/DWORD類型的值;

          wPortAddr是指定一個端口地址值;

          pdwPortVal為指向一雙字節(jié)型變量的指針,該變量存儲從wPortAddr端口讀取的值;

          bSize指定讀取字節(jié)數(shù),值可以為1,2或4。

          SetPortVal函數(shù)向指定端口寫入一個BYTE/WORD/DWORD類型的值;

          除dwPortVal為輸入?yún)?shù),表示待寫入外,其余個變量含義與GetPortVal相似。

          PC并行口數(shù)字輸出的VC實現(xiàn)(示例工程下載)

          為了測試并行口的數(shù)字輸出,可以準備12支LED發(fā)光二極管,將LED的陽極分別與數(shù)據(jù)端口引腳Pin2~Pin9和控制端口引腳Pin1、Pin14、Pin16、Pin17相連接;將LED的陰極連接在一起與并行口的歸地引腳GND相連即可。在實際控制應用中不能這樣連接,因為數(shù)據(jù)端口引腳、控制端口引腳輸出的電流非常小,只有10mA左右,必須添加 其它硬件電路。

          (1):數(shù)據(jù)端口數(shù)字輸出的VC實現(xiàn)

          //獲得數(shù)據(jù)端口地址

          WORD m_nport=(WORD)0x378;

          //獲得要寫入數(shù)據(jù)端口的值WriteValue(數(shù)據(jù)范圍為0~255)

          DWORD m_nValue=(DWORD)WriteValue;

          //調(diào)用WinIo庫函數(shù)SetPortVal寫端口值

          SetPortVal(m_nport, m_nValue, 1);//write a BYTE value to an I/O port

          (2):控制端口數(shù)字輸出的VC實現(xiàn)

          //獲得控制端口地址

          WORD m_nport=(WORD)0x37A;

          //獲得控制端口的值,保持高位值不變,將要輸出的值從低4位輸出,且使連接器上的電位狀態(tài)與想輸出的值一致

          DWORD temp_dwPortVal;

          unsigned int temp_aa;

          GetPortVal(m_nport, temp_dwPortVal, 1); //reads a BYTE value from an I/O port

          temp_aa=(unsigned int)temp_dwPortVal;

          temp_aa=temp_aa0x0F0; //取低8位值,將低4位置為0;高4位不變;

          temp_aa=temp_aa^0x0B; //將低4位中C0、C1、C3置為1,C2置為0;高4位不變;

          //獲得要寫入控制端口的值WriteValue(數(shù)據(jù)范圍為0~15)

          unsigned int WriValue;

          WriValue=WriteValue0x0F; //取低4位;

          temp_aa=temp_aa^WriValue; //將寫入值的低4位中的C0、C1、C3取反,C2位不變,高4位保持端口值不變

          SetPortVal(m_nport, (DWORD)temp_aa, 1); //寫出的值中,高4位保持端口原來的值不變,

          //低4位是寫入什么電平,連接器上既是什么電平

          (3):數(shù)據(jù)端口及控制端口組合成12位數(shù)字輸出的VC實現(xiàn)

          //獲得端口地址

          WORD m_nportData=(WORD)0x378;

          WORD m_nportControl=(WORD)0x37A;

          //獲得要寫入端口的值WriteValue(數(shù)據(jù)范圍為0~4095)

          DWORD m_nValue=(DWORD)(WriteValue0x0FF);//取低8位值

          SetPortVal(m_nportData, m_nValue, 1);//write a BYTE value to Data port

          DWORD temp_dwPortVal;

          unsigned int temp_aa;

          GetPortVal(m_nportControl, temp_dwPortVal, 1); //reads a BYTE value from an I/O port

          temp_aa=(unsigned int)temp_dwPortVal;

          temp_aa=temp_aa0x0F0; //取低8位值,將低4位置為0;高4位不變;

          temp_aa=temp_aa^0x0B; //將低4位中C0、C1、C3置為1,C2置為0;高4位不變;

          unsigned int WriValue;

          WriValue=WriValue>>8;//取高4位值

          temp_aa=temp_aa^WriValue; //將寫入值的低4位中的C0、C1、C3取反,C2位不變,高4位保持端口值不變

          SetPortVal(m_nportControl, (DWORD)temp_aa, 1); //寫出的值中,高4位保持端口原來的值不變,

          //低4位是寫入什么電平,連接器上既是什么電平



        評論


        技術(shù)專區(qū)

        關閉
        主站蜘蛛池模板: 栖霞市| 乌什县| 绥滨县| 新邵县| 二连浩特市| 和林格尔县| 门源| 宁都县| 宣威市| 大安市| 水城县| 富蕴县| 泰兴市| 邵武市| 吉水县| 溧阳市| 娄烦县| 永平县| 蕉岭县| 韶关市| 萍乡市| 阿尔山市| 高雄县| 黄冈市| 塘沽区| 毕节市| 庄河市| 拉孜县| 惠安县| 墨脱县| 三河市| 鹤庆县| 松桃| 庆云县| 永靖县| 九龙城区| 东乡县| 湖南省| 革吉县| 三都| 贡山|