[ บทความ : ยูนิตสำหรับ ET-LAB3A (LPT Port) ]

 

            สวัสดีครับ บทความนี้ (ไม่น่าจะเรียกว่าบทความนะครับ) เป็นโค้ดของยูนิตสำหรับใช้กับ ET-LAB3A ผ่านทาง Printer Port ครับ เขียนขึ้นมาเพื่อใช้กับ Delphi6 สามารถใช้งานกับ Windows 98/ME ได้ทันที แต่ถ้าเป็น Windows XP จะต้องมีการติดตั้ง UserPort และเรียกใช้โปรแกรม UserPort.exe เสียก่อน เพราะผมไม่มี DDK ที่สามารถทำให้เราเขียนโปรแกรมเพื่อเข้าถึงฮาร์ดแวร์ผ่าน Windows XP ได้โดยตรง (เมื่อก่อนไม่ยอมโหลด ตอนนี้ Microsoft เขาทำขายซะแล้ว เลยไม่สามารถทำอะไรได้)

            การใช้งานก็ไม่มีอะไรยุ่งยากเพราะมีฟังก์ชันการทำงานให้ใช้คือ SendCtrl สำหรับส่ง Control Command ไปที่ 8255, SendData สำหรับส่งข้อมูลไปยัง 8255 และ ReadData สำหรับอ่านข้อมูลผ่าน 8255

            การทำงานผมได้ทดลองกับเครื่อง Pentium II-450MHz 512MB (RAM) ที่ติดตั้ง Windows XP กับ Pentium Pro200 128MB (RAM) ที่ติดตั้ง Windows ME ก็สามารถทำงานได้ปกติดีครับ จะมีปัญหาก็ตรงที่พอร์ต LPT รุ่นใหม่ๆนั้นจะสามารถสั่ง SendData ได้อย่างเดียว วงจรส่วนการ ReadData จะไม่ทำงานครับ ซึ่งปัญหาจุดนี้ก็แก้ไขได้โดยการปรับให้อ่านข้อมูลโดยใช้ขา Data แทน (ได้ข่าวว่า ETT กำลังออก CP-jrLPT ที่จะทำให้ใช้งานได้ดีกว่าวงจรของ LAB3A ประกอบกับสั่งงานแบบ 8 บิตอีกด้วย)

            โค้ดก็เป็นตามด้านล่างนี้เลยครับ เวลาใช้งานก็เพิ่มแฟ้ม usrLPT.pas เข้าไปใน Project ของ Delphi และเรียก Uses ยูนิต usrLPT เข้าไปด้วยก็ทำงานได้แล้วครับ

 

 

 

{*******************************************************************

    Filename                  :           usrLPT.Pas

    Author                     :           Supachai Budsaratij (raek@etteam.com)

                                                Faculty of Information Technologies

                                                Phetchaburi Rajabhat University

    Operating System   :           Microsoft Windows 98/ME/2000/XP

    Compiler                  :           Borland Delphi6 or later

*******************************************************************}

unit usrLPT;

 

interface

 

var

  tDelay : integer;

 


procedure
oportb(portid : integer; value : byte);

function  iportb(portid : integer) : byte;

function  StartUpIOPorts(PortToAccess : Integer) : boolean;

procedure SendCtrl(ctrl:byte);

procedure SendData(value,portno:byte);

function  ReadData(portno:byte):byte;
 

 

implementation

 

uses Windows;

var

  LPT_DATA, LPT_STATUS, LPT_CONTROL : Word;

  InvertedLogic : array[0..15] of byte;

 

 

procedure oportb(portid : integer; value : byte);

{*******************************************************************

   ส่งข้อมูล 8 บิตออกพอร์ต

*******************************************************************}
 

 

begin

    asm

        mov edx,portid

        mov al,value

        out dx,al

    end;

end;
 

 

function iportb(portid : integer) : byte;

{*******************************************************************

   รับข้อมูล 8 บิตจากพอร์ต

*******************************************************************}
 

 

begin

    asm

        mov edx,portid

        in  al,dx

        mov Result,al

    end;

end;

 

 

procedure SendCtrl(ctrl:byte);

{*******************************************************************

   ส่ง Control Word ไปที่ IC8255

*******************************************************************}
 

var

  a, b : byte;

begin
 

{ Step 1 : Selected }

  oportb(LPT_DATA,$0f);
 

{ Step 2 : Write High bits }

  a := ctrl and $f0;

  oportb(LPT_DATA,a or $0f);
 

{ Step 3 : Write Low bits }

  b := ctrl and $0f;

  oportb(LPT_CONTROL, InvertedLogic[b]);
 

{ Step 4 : Put /Strobe Low }

  a := iportb(LPT_DATA);

  oportb(LPT_DATA, a and $F7);

  Sleep(TDelay); { Wait }
 

{ Step 5 : Put /Strobe High }

  oportb(LPT_DATA, a or $08);

end;
 

 


procedure SendData(value,portno:byte);

{*******************************************************************

   ส่ง Data ไปที่ IC8255 portno (0=PortA, 1=PortB, 2=PortC)

*******************************************************************}

 

var

  a, b : byte;

begin
 

{ Step 1 : Selected }

  a := portno or $0c;

  oportb(LPT_DATA, a);

 

{ Step 2 : Write High bits }

  b := value and $f0;

  oportb(LPT_DATA,a or b);
 

{ Step 3 : Write Low bits }

  b := value and $0f;

  oportb(LPT_CONTROL, InvertedLogic[b]);

 

{ Step 4 : Put /Strobe Low }

  a := iportb(LPT_DATA);

  oportb(LPT_DATA, a and $F7);

  Sleep(TDelay); { Wait}

 

{ Step 5 : Put /Strobe High }

  oportb(LPT_DATA, a or $08);

end;

 


function ReadData(portno:byte):byte;

{*******************************************************************

   รับ Data จาก IC8255 portno (0=PortA, 1=PortB, 2=PortC)

*******************************************************************}

 

var

  a, b, c : byte;

begin

 

{ Step 1 : Selected port }

  oportb(LPT_DATA,portno or $0c);

 

{ Step 2 : Initial the data }

  a := iportb(LPT_DATA) and $0b;

  oportb(LPT_DATA, a);

  oportb(LPT_CONTROL,$04); { Initialize = 1 }

 

{ Step 3 : Read data }

  a := iportb(LPT_CONTROL) and $0f; { Read Low bits }

  b := iportb(LPT_STATUS) and $f0;  { Read High bits }

  c := InvertedLogic[a]; { Inverted the Low bits }

 

{ Step 4 : Active /Strobe and AutoLineFeed }

  oportb(LPT_DATA, portno or $0c);

 

{ Step 5 : Retuen the value }

  Result := b or c;

end;

 

 

function StartUpIOPorts(PortToAccess : Integer) : boolean;

{*******************************************************************

   กำหนดค่าเริ่มต้นสำหรับการติดต่อกับพอร์ต

*******************************************************************}

 

var

  hUserPort : THandle;

begin

  tDelay := 1;

  LPT_DATA := PortToAccess;

  LPT_STATUS := PortToAccess+1;

  LPT_CONTROL := PortToAccess+2;

 


{*******************************************************************

   สร้าง InvertedLogic เพื่อส่งให้บอร์ด ET-LPT Interface

*******************************************************************}

 

  InvertedLogic[0] := $B; { 1011 }

  InvertedLogic[1] := $A; { 1010 }

  InvertedLogic[2] := $9; { 1001 }

  InvertedLogic[3] := $8; { 1000 }

 

  InvertedLogic[4] := $F; { 1111 }

  InvertedLogic[5] := $E; { 1110 }

  InvertedLogic[6] := $D; { 1101 }

  InvertedLogic[7] := $C; { 1100 }

 

  InvertedLogic[8] := $3; { 0011 }

  InvertedLogic[9] := $2; { 0010 }

  InvertedLogic[10]:= $1; { 0001 }

  InvertedLogic[11]:= $0; { 0000 }

 

  InvertedLogic[12]:= $7; { 0111 }

  InvertedLogic[13]:= $6; { 0110 }

  InvertedLogic[14]:= $5; { 0101 }

  InvertedLogic[15]:= $4; { 0100 }

 


{*******************************************************************

    ด้านล่างนี้เป็นกรณีของ Windows 2000/XP ถ้าเป็น Windows 98/ME ไม่จำเป็นต้องติดต่อกับ UserPort

*******************************************************************}

 

    if (LOBYTE(LOWORD(GetVersion))=5) then

    begin

 

      { เรียกใช้ไดรเวอร์ของ UserPort }

      hUserPort := CreateFile('\\.\UserPort',GENERIC_READ,0,nil,

                              OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

      CloseHandle(hUserPort);

      Sleep(100);

    end;

 

{ ทดสอบติดต่อกับพอร์ต }

    try

        iportb(PortToAccess);

        Result := true;

    except

        MessageBox(0,'ไม่สามารถเรียกใช้พอร์ตได้','มีปัญหา',MB_OK);

        Result := false;

    end;

end;

 

end.

 

 

            ตัวอย่างการสั่งไฟวิ่งครับ

 


unit mainLED;

 

interface

 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics,

  Controls, Forms, Dialogs, StdCtrls, usrLPT;

 

type

  TForm1 = class(TForm)

    btnConnect: TButton;

    l0: TCheckBox;

    l1: TCheckBox;

    l2: TCheckBox;

    l3: TCheckBox;

    l4: TCheckBox;

    l5: TCheckBox;

    l6: TCheckBox;

    l7: TCheckBox;

    btnSend: TButton;

    procedure btnConnectClick(Sender: TObject);

    procedure btnSendClick(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;

var

  Form1: TForm1;

 

implementation

{$R *.dfm}

procedure TForm1.btnConnectClick(Sender: TObject);

begin

    if StartUpIOPorts($378) = true then

    begin

        SendCtrl($80);

        MessageBox(0,'สำเร็จ','ติดต่อกับ LPT',MB_OK);

    end;

end;

 

procedure TForm1.btnSendClick(Sender: TObject);

var a:byte;

begin

    a:=0;

    if (l0.Checked) then a:=$01;

    if (l1.Checked) then a:=a or $02;

    if (l2.Checked) then a:=a or $04;

    if (l3.Checked) then a:=a or $08;

    if (l4.Checked) then a:=a or $10;

    if (l5.Checked) then a:=a or $20;

    if (l6.Checked) then a:=a or $40;

    if (l7.Checked) then a:=a or $80;

 

    SendData(a,0);

end;

end.

 

 

 

 

 

 


เขียนโดย : ศุภชัย บุศราทิจ
Author : Supachai Budsaratij
วันที่ทำการปรับปรุง : ๑๑ ก.พ. ๒๕๔๘