並行埠(Parallel Port,通稱 LPT)曾是 PC 連接印表機、掃描器與自製硬體電路的標準介面。雖然現代電腦已少見,但在工業控制、教學實驗與舊系統維護中仍具價值。本文將示範如何在 Delphi 中以內嵌組合語言直接存取 LPT1 的資料、狀態與控制埠,並進一步實作位元級控制、即時監控與走馬燈動畫。
常用的 LPT1 擁有三個 I/O 位址:
378H(寫入輸出電位,讀取可回讀輸出狀態)379H(唯讀,反映外部訊號如 BUSY、ACK、PE、SLCT、ERROR)37AH(讀寫,控制 STROBE、AUTOFD、INIT、SLCT_IN 等)Delphi 無內建 I/O 指令,但支援 ASM 區塊,可直接嵌入 IN/OUT 指令:
function ReadPort(Port: Word): Byte;
var
B: Byte;
begin
asm
MOV DX, Port
IN AL, DX
MOV B, AL
end;
Result := B;
end;
procedure WritePort(Port: Word; ConByte: Byte);
begin
asm
MOV DX, Port
MOV AL, ConByte
OUT DX, AL
end;
end;
優點:無需第三方 DLL/驅動程式,執行效率極高,程式碼簡潔。
限制:僅適用於 Windows 9x 系列(95/98/Me)。NT 核心系統(NT/2000/XP/後續版本)需使用 CreateFile 開啟 \\.\LPT1 或第三方驅動(如 inpout32.dll、dlportio.sys)。
控制單一位元而不影響其他位,核心在於 AND(清除位)與 OR(設定位):
Value := Value and (not Mask)。例如將 D2(Bit 2,值 4)歸零:$84 and $FB = $80。Value := Value or Mask。例如將 D1(Bit 1,值 2)設為 1:$84 or $02 = $86。if (Value and Mask) = Mask then ... 或 if (Value or (not Mask)) = $FF then ...。{ 設為低電位 (0) }
B := ReadPort($378);
B := B and $FB; { $FB = 11111011b,清除 Bit 2 }
WritePort($378, B);
{ 設為高電位 (1) }
B := ReadPort($378);
B := B or $04; { $04 = 00000100b,設定 Bit 2 }
WritePort($378, B);
{ 判斷電位高低 }
B := ReadPort($378);
if (B and $04) = $04 then
{ 高電位處理 }
else
{ 低電位處理 }
以下步驟在 Delphi 6/7 中建立一個展示專案:
Form1。Unit1.pas 的 implementation 區加入上述 ReadPort/WritePort 函式。TCheckBox(CheckBox1~CheckBox8),Caption 分別設為 D0~D7,由右至左排列對應 Bit 0~7。OnClick 事件指向同一處理函式。procedure TForm1.CheckBox1Click(Sender: TObject);
var
B: Byte;
begin
B := 0;
if CheckBox1.Checked then B := B or $01; { D0 }
if CheckBox2.Checked then B := B or $02; { D1 }
if CheckBox3.Checked then B := B or $04; { D2 }
if CheckBox4.Checked then B := B or $08; { D3 }
if CheckBox5.Checked then B := B or $10; { D4 }
if CheckBox6.Checked then B := B or $20; { D5 }
if CheckBox7.Checked then B := B or $40; { D6 }
if CheckBox8.Checked then B := B or $80; { D7 }
WritePort($378, B);
end;
Timer1,Interval := 100(100 ms),Enabled := False。CheckBox9,Caption := '監控並口',OnClick 切換 Timer1.Enabled。procedure TForm1.Timer1Timer(Sender: TObject);
var
B: Byte;
begin
B := ReadPort($378);
{ 利用 OR 運算檢測各位是否為 1 }
CheckBox1.Checked := (B or $FE) = $FF; { D0 }
CheckBox2.Checked := (B or $FD) = $FF; { D1 }
CheckBox3.Checked := (B or $FB) = $FF; { D2 }
CheckBox4.Checked := (B or $F7) = $FF; { D3 }
CheckBox5.Checked := (B or $EF) = $FF; { D4 }
CheckBox6.Checked := (B or $DF) = $FF; { D5 }
CheckBox7.Checked := (B or $BF) = $FF; { D6 }
CheckBox8.Checked := (B or $7F) = $FF; { D7 }
end;
procedure TForm1.CheckBox9Click(Sender: TObject);
begin
Timer1.Enabled := CheckBox9.Checked;
end;
tb: Byte。Timer2,Interval := 300,Enabled := False。CheckBox10,Caption := '走馬燈演示',控制 Timer2.Enabled。procedure TForm1.Timer2Timer(Sender: TObject);
var
B: Byte;
begin
if tb = 0 then
tb := 1
else
tb := tb * 2; { 左移一位 }
if tb = 0 then { 溢位歸零 }
tb := 1;
WritePort($378, tb);
B := ReadPort($378);
{ 同步更新 CheckBox 顯示 }
CheckBox1.Checked := (B or $FE) = $FF;
CheckBox2.Checked := (B or $FD) = $FF;
CheckBox3.Checked := (B or $FB) = $FF;
CheckBox4.Checked := (B or $F7) = $FF;
CheckBox5.Checked := (B or $EF) = $FF;
CheckBox6.Checked := (B or $DF) = $FF;
CheckBox7.Checked := (B or $BF) = $FF;
CheckBox8.Checked := (B or $7F) = $FF;
end;
為了驗證輸出,可自製簡易測試板:

執行程式並勾選「走馬燈演示」,即可觀察 LED 依序亮滅。

若需在 Windows NT/2000/XP/7/10/11 上運作,請改用成熟的開源庫:
DeviceIoControl透過 Delphi 內嵌組合語言直接操作 I/O 埠,是認識電腦底層硬體介面的最佳入門。雖然並行埠已逐漸退出歷史舞台,但其位元操作邏輯(AND/OR/XOR/移位)通用於所有嵌入式開發、驅動程式撰寫與通訊協定實作。掌握這些基礎,將為後續學習 GPIO、SPI、I²C 等現代介面打下堅實基礎。