並行埠 (LPT) 以 8 位元並行傳輸,速度遠超序列埠,適合即時控制系統 (單晶片、PLC、數位 I/O 卡)。Windows 保護模式禁止直接 I/O 存取,本文介紹使用 WinIo 函式庫 繞過保護,實現資料/狀態/控制暫存器讀寫,並提供完整 VC++ 範例與硬體測試電路。
| 暫存器 | 位址 | 功能 | 腳位 | 位元 |
|---|---|---|---|---|
| 資料暫存器 | Base (0x378) | 輸出 8 位元 (可讀回) | Pin 2~9 | D0~D7 |
| 狀態暫存器 | Base+1 (0x379) | 輸入 5 位元 (S3~S7) | Pin 15,13,12,10,11 | S3~S7 |
| 控制暫存器 | Base+2 (0x37A) | 輸出 4 位元 (可作輸入) | Pin 1,14,16,17 | C0~C3 |
注意:S7、C0、C1、C3 在接腳端為反相邏輯,讀寫時需對應處理。
WinIo.dll, WinIo.sys, WINIO.VXD 至執行檔目錄。WinIo.lib,StdAfx.h 加入 #include "winio.h"。InitializeWinIo();結束:ShutdownWinIo()。InstallWinIoDriver(path, FALSE) 並重開機。
BOOL GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize); // 讀 1/2/4 bytes
BOOL SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize); // 寫 1/2/4 bytes
WORD port = 0x378;
DWORD val = outputValue; // 0~255
SetPortVal(port, val, 1);
WORD port = 0x37A;
DWORD cur; GetPortVal(port, &cur, 1);
unsigned int v = (unsigned int)cur;
v = (v & 0xF0) ^ 0x0B; // 保留高 4 位,C0/C1/C3 反相預置為 1
v ^= (outputValue & 0x0F); // 寫入低 4 位 (再次反相抵消)
SetPortVal(port, v, 1);
DWORD val = outputValue; // 0~4095
SetPortVal(0x378, val & 0xFF, 1); // 低 8 位
DWORD cur; GetPortVal(0x37A, &cur, 1);
unsigned int v = (unsigned int)cur;
v = (v & 0xF0) ^ 0x0B;
v ^= ((val >> 8) & 0x0F); // 高 4 位
SetPortVal(0x37A, v, 1);
DWORD val; GetPortVal(0x379, &val, 1);
unsigned int v = val ^ 0x80; // S7 反相修正
v = (v & 0xF8) >> 3; // 取 S7~S3 -> 低 5 位
// 結果 0~31
// 1. 設 C0~C3 為高電位 (接腳端高) 啟用輸入模式
DWORD cur; GetPortVal(0x37A, &cur, 1);
unsigned int v = (unsigned int)cur;
v = (v & 0xF0) ^ 0x04; // C2=1, C0/C1/C3=0 (接腳端反相後為高)
SetPortVal(0x37A, v, 1);
// 2. 讀取並修正反相
GetPortVal(0x37A, &val, 1);
v = val ^ 0x0B; // C0/C1/C3 反相修正
v &= 0x0F; // 取低 4 位
// 結果 0~15
// 讀狀態埠 -> 左移 1 位佔高 5 位
// 讀控制埠 (啟用輸入後) -> 佔低 4 位
// 合成 0~511 (Pin 11 接地) 或 256~511 (Pin 11 懸空)
WinIo 庫提供了在 Windows 9x/NT/2000/XP 下直接存取並行埠 I/O 的最簡單路徑。掌握三大暫存器位址、反相邏輯與讀寫 API,即可開發各類數位 I/O 控制應用。範例程式碼涵蓋 1~12 位元輸出、1~9 位元輸入的完整組合,可直接套用至專案中。