透過Lpt8255_.pas元件與印表機8255介面卡取得通信 |
|
jackkcg
站務副站長 發表:891 回覆:1050 積分:848 註冊:2002-03-23 發送簡訊給我 |
此為轉貼資料 原來源位置 庵已經忘記 希望知道之人可以補上 //設計:張勇富 email:ufau0083@ms11.hinet.net //
//1999/4/30 ver:1.0
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 目前區域網路,網際網路的發達日益蓬勃,各式應用層出不窮,不久前在媒體上,得知未來的電腦控制家庭設備正在積極規劃及實驗中,透過網際網路由地球上的一點監控地球上遠方另一點的家電設備的概念產物也正式向世人宣告,這一波流行,如果能跟得上,我想好玩也是值待研究的重點。
為了將原來單一機器上執行的程式,透通性的轉移的網路上,即原始程式不用更改,只要更換元件做簡單的設定即可達到目標是本章的主要想法,要達成這個目的最簡單的方法或許是DCOM離散物件模型,此一技術由於需要系統做大部分的配合而且在Window NT上的效果遠比Window 98上容易,所以留待後面專章討論,本章純就利用Delphi元件的的設計技術,繼承原先單機時的Lpt8255_.pas的元件,保留原屬性之外,另擴充一些網路特性的屬性,而這些擴充的屬性若只透過物件觀測器的設定,而不是在程式中用程式碼撰寫,即可更換元件而達到單機或遠端遙控程式的完成。
以上是將單机元件壙展成網路元件時的架構圖,將Lpt8255_.pas更換成Lpt8255Client.pas的元件,再透過UDP網路協定與Lpt8255ServerWindow.exe程式通信,而程式內部再透過Lpt8255_.pas元件與印表機8255介面卡取得通信。 Lpt8255ServerWindow.exe Lpt8255Client.pas的元件在發展過程中,經過許多次的失敗,其問題的關鍵在那裏呢?如果沒有親自體會一下,就不容易理解,在程式中我為何不用Delphi內附的網路通信元件,而另求他解,主要原因是出在視窗事件驅動的架構,做輸出口指令時是單向沒有問題,而輸入口卻是雙向的事件驅動,不容易用Delphi中元件屬性的方法表達出來,在此提出此事,也期望讀者在閱讀程式時,特別注意輸入口的寫法。
以下列出Lpt8255_.pas及Lpt8255Client.pas可供比較參考。
//**************************************************//
// 印表機介面8255 io 卡 元件 //
//設計:張勇富 email:ufau0083@ms11.hinet.net //
//1999/4/30 ver:1.0
//**************************************************//
//請參考 lpt8255.sch 的電路圖
//印表機的資料埠是在:378h 或3bch 或 278h
//資料埠 bit 0..7 ==>pin2..9
//狀態埠:379h 或3bdh 或 279h
//bit 3..bit6
//控制埠 37ah 或3beh 或 27ah
//bit0:strobe\==>pin 1 ---------------->as Command/ 或 data 的選擇腳
//bit1:auto feed\==>pin14 ---------------->as Command Clock/
unit Lpt8255;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,printers,IniFiles;
const
//命令暫存器的常數定義:74LS377
//bit 7 6 5 4 3 2 1 0
// ---AO DEFAULT:0
// ------A1 DEFAULT:0
// --------CS0/ DEFAULT:1
// -----------CS1/ DEFAULT:1
// ----------------CS2/ DEFAULT:1
// ------------------Write/ DEFAULT:1
// -----------------------Read/ DEFAULT:1
// ----------------------------Read High or Low Nibble/ DEFAULT:1
//以上bit 0..1 ,2..4,5..6,7共分為4組利用或閘運算組合成一個命令位元組送到4ls377
DISABLE_ALL_8255=$FC ; // 11111100
WRITE_8255=$c0 ; // 11000000
READ_HIGH_NIBBLE=$A0 ; // 10100000
READ_LOW_NIBBLE=$20 ; // 00100000
CS0_8255=$18 ; // 00011000
CS1_8255=$14 ; // 00010100
CS2_8255=$0c ; // 00001100
PORTA_ADDRESS =0 ; // 00000000
PORTB_ADDRESS =1 ; // 00000001
PORTC_ADDRESS =2 ; // 00000010
PORTCRTL_ADDRESS =3 ; // 00000011
type
Tport=(porta,portb,portc,portcrtl);
Tlpt8255_ = class(TComponent)
private
{ Private declarations }
//利用印表機資料埠可寫出及讀入時資料相同的特性判斷是否為印表機介面卡安裝之所在
Function IsPrintPort(Address:Word):Boolean;
protected
{ Protected declarations }
//設定印表機介面卡的資料埠位址
FPrinterAddress:word;
//泱定是否可送資料到印表機介面卡
FEnabled:Boolean;
//選擇電路板上三顆825子中的一顆
F8255ID:Byte;//select 8255_CS0 ,CS1,CS2 Range 0..2
FPortCrtlData:Byte;
//將命令位元組送到74LS377
procedure WriteCommand(Command:Byte);
//真正寫資料到8255的指令
procedure WritePort(port:TPort;data:byte);virtual;
//真正從8255讀取資料的指令
function ReadPort(port:TPort):Byte;virtual;
procedure SetEnabled(Value:Boolean);virtual;
procedure SetPrinterAddress(Value:Word);
public
{ Public declarations }
//送資料到輸出口
procedure OutPortB(Address:Word;data:byte);virtual;
//從輸入口讀取資料
function InPortB(Address:word):byte;virtual;
Constructor Create(AOwner: TComponent); override;
//尋找印表機介面卡安裝之資料埠
Function FindPrintPort:Word;virtual;
//測試電路板上由8255ID所指定的8255是否正常
//若有問題會從status傳回錯誤訊息
Function Test8255(var Status:String):Boolean;virtual;
//讀寫825子的ID
procedure Set8255ID(value:byte);virtual;
function Get8255ID:Byte;virtual;
//將3顆8255共72支輸出腳分別讀寫
//bitNo:0..71
//Cs0:PortA[0..7] Portb[8..15],PortC[16..23]
procedure SetBit(BitNo:byte;Value:Boolean);virtual;
Function GetBit(BitNo:Byte):Boolean;virtual;
//讀寫8255的4個Port
procedure WritePortA(data:byte);
function ReadPortA:Byte;
procedure WritePortB(data:byte);
function ReadPortB:Byte;
procedure WritePortC(data:byte);
function ReadPortC:Byte;
procedure WritePortCrtl(data:byte);
function ReadPortCrtl:Byte;
//資料格式轉換
// Function ByteToBin(Value:Byte):String;
// Function BinToByte(Value:String):Byte;
// Function ByteToHex(Value:Byte):String;
// Function HexToByte(Value:String):Byte;
property PortAData:byte read ReadPorta write Writeporta;
property PortBData:byte read ReadPortb write Writeportb;
property PortCData:byte read ReadPortc write Writeportc;
property PortCrtlData:byte read readPortCrtl write Writeportcrtl;
published
{ Published declarations }
property ID_8255:byte read Get8255Id write Set8255ID default 0;
Property PrinterAddress:Word read FPrinterAddress write SetPrinterAddress default $378;
property Enabled:boolean read FEnabled write SetEnabled default True;
end;
procedure Register;
implementation
var g_CriticalSection:TRTLCriticalSection;
procedure Register;
begin
RegisterComponents('張勇富', [Tlpt8255_]);
end;
constructor Tlpt8255_.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
InitializeCriticalSection(g_CriticalSection);
FEnabled:=True;
F8255ID:=0;
FPrinterAddress:=$378;
end;
procedure Tlpt8255_.OutPortB(Address:Word;data:byte);
begin
try
asm mov dx,address
mov al,data
out dx,al
end;
except
end;
end;
function Tlpt8255_.InPortB(Address:word):byte;
begin
try
asm mov dx,Address
in al,dx
mov result,al
end;
except
end;
end;
Function Tlpt8255_.IsPrintPort(Address:Word):Boolean;
var Data:byte;
begin
Result:=True;
data:=$ff;
OutPortB(Address,Data);
if data<>InPortB(Address) then begin Result:=False;Exit;end;
data:=$00;
OutPortB(Address,Data);
if data<>InPortB(Address) then begin Result:=False;Exit;end;
data:=$aa;
OutPortB(Address,Data);
if data<>InPortB(Address) then begin Result:=False;Exit;end;
data:=$55;
OutPortB(Address,Data);
if data<>InPortB(Address) then Result:=False;
end;
Function Tlpt8255_.FindPrintPort:Word;
begin
result:=$378;
if IsPrintPort($378) then result:=$378
else if IsPrintPort($3bc) then result:=$3bc
else if IsPrintPort($278) then result:=$278
else Raise Exception.Create('找不到印表機位置或是介面卡故障');
end;
Function Tlpt8255_.Test8255(var Status:String):Boolean;
var testData,ReadBackData:Byte;
Begin
EnterCriticalSection(g_CriticalSection);
Status:='';
Result:=True;
PortCrtlData:=$80;//set all out port
// 當8255的PortA規劃為輸出口,而輸出端有接上輸入設備時會有錯誤的測試結果
//PortB, PortC 都沒有測試到有此現象 ,若欲詳細測試請執行Lpt8255的測試程式
{
TestData:=$55;
PortAData:=TestData;
ReadBackdata:=PortAData;
if TestData<>ReadBackData then begin Result:=False;Status:='PortA=55h error! ';end;
TestData:=$AA;
PortAData:=TestData;
ReadBackdata:=PortAData;
if TestData<>ReadBackData then begin Result:=False;Status:='PortA=aah error! ';end;
}
TestData:=$55;
PortBData:=$55;
if TestData<>PortBData then begin Result:=False;Status:=Status+'PortB=55h error! ';end;
TestData:=$AA;
PortBData:=$AA;
if TestData<>PortBData then begin Result:=False;Status:=Status+'PortB=aah error! ';end;
TestData:=$55;
PortCData:=$55;
if TestData<>PortCData then begin Result:=False;Status:=Status+'PortC=55h error! ';end;
TestData:=$AA;
PortCData:=$AA;
if TestData<>PortCData then begin Result:=False;Status:=Status+'PortC=aah error! ';end;
PortCrtlData:=$ff;
LeaveCriticalSection(g_CriticalSection);
end;
procedure Tlpt8255_.SetEnabled(Value:Boolean);
begin
if Value<>FEnabled then FEnabled:=Value;
end;
procedure Tlpt8255_.SetPrinterAddress(Value:Word);
begin
if Value<>FPrinterAddress then FPrinterAddress:=Value;
end;
procedure Tlpt8255_.Set8255ID(value:byte);
begin
EnterCriticalSection(g_CriticalSection); //避免同一行程,多執行緒的錯誤
if Value>2 then Value:=0;
if Value<>F8255ID then F8255ID:=Value;
LeaveCriticalSection(g_CriticalSection);
end;
function Tlpt8255_.Get8255ID:byte;
begin
EnterCriticalSection(g_CriticalSection);
result:=F8255ID;
LeaveCriticalSection(g_CriticalSection);
end;
procedure Tlpt8255_.WriteCommand(Command:Byte);
Begin
EnterCriticalSection(g_CriticalSection);
//send Command and Clock
OutPortB(FprinterAddress+2,3);//bit 1 bit0= 11
//send Command data
OutPortB(FprinterAddress,Command);
//send Commandand Clock
OutPortB(FprinterAddress+2,1);//bit 1 bit0= 01
LeaveCriticalSection(g_CriticalSection);
end;
procedure Tlpt8255_.WritePort(Port:TPort;data:byte);
var ChipSelect,PortAddress:byte;
begin
if ( csDesigning in ComponentState ) or (csLoading in ComponentState) then exit;
EnterCriticalSection(g_CriticalSection);
PortAddress:=PortA_ADDRESS;
ChipSelect:=CS0_8255;
if Not FEnabled then exit;
case F8255Id of
0:ChipSelect:=CS0_8255;
1:ChipSelect:=CS1_8255;
2:ChipSelect:=CS2_8255;
end;
case Port of
porta:PortAddress:=PortA_ADDRESS;
portb:PortAddress:=PortB_ADDRESS;
portc:PortAddress:=PortC_ADDRESS;
portCrtl:PortAddress:=PortCRTL_ADDRESS;
end;
//write data
OutPortB(FprinterAddress,data);
//enable Data to 74ls373
OutPortB(FprinterAddress+2,0);//bit 1 bit0= 00
WriteCommand(WRITE_8255 or PortAddress or ChipSelect);
WriteCommand(DISABLE_ALL_8255);//gengerator 8255 write Pulse trigger
LeaveCriticalSection(g_CriticalSection);
end;
function Tlpt8255_.ReadPort(port:TPort):Byte;
var ChipSelect,PortAddress:byte;
begin
if ( csDesigning in ComponentState ) or (csLoading in ComponentState) then exit;
EnterCriticalSection(g_CriticalSection);
if Not FEnabled then exit;
case F8255Id of
0:ChipSelect:=CS0_8255;
1:ChipSelect:=CS1_8255;
2:ChipSelect:=CS2_8255;
end;
case Port of
porta:PortAddress:=PortA_ADDRESS;
portb:PortAddress:=PortB_ADDRESS;
portc:PortAddress:=PortC_ADDRESS;
portCrtl:PortAddress:=PortCRTL_ADDRESS;
end;
WriteCommand(READ_LOW_NIBBLE or PortAddress or ChipSelect);
//read Low nibble
Result:=InPortB(FprinterAddress+1) shr 3;
WriteCommand(READ_HIGH_NIBBLE or PortAddress or ChipSelect);
//read High nibble
Result:=((InPortB(FprinterAddress+1) shl 1) and $F0) or Result;
WriteCommand(DISABLE_ALL_8255);
LeaveCriticalSection(g_CriticalSection);
end;
procedure Tlpt8255_.WritePortA(data:byte);
Begin
WritePort(PortA,data);
end;
function Tlpt8255_.ReadPortA:Byte;
Begin
Result:=ReadPort(PortA);
end;
procedure Tlpt8255_.WritePortB(data:byte);
Begin
WritePort(PortB,data);
end;
Function Tlpt8255_.ReadPortB:Byte;
Begin
Result:=ReadPort(PortB);
end;
procedure Tlpt8255_.WritePortC(data:byte);
Begin
WritePort(PortC,data);
end;
Function Tlpt8255_.ReadPortC:Byte;
Begin
Result:=ReadPort(PortC);
end;
function Tlpt8255_.ReadPortCrtl:Byte;
var lpt8255Ini:TIniFile;
Begin
Lpt8255Ini:=TIniFile.Create('Lpt8255.ini');
try
Result:=Lpt8255Ini.ReadInteger('8255 ID '+IntTostr(F8255Id), 'CrtlPort',255);
finally
Lpt8255Ini.Free;
end;
// Result:=ReadPort(PortCrtl);
end;
procedure Tlpt8255_.WritePortCrtl(data:byte);
var lpt8255Ini:TIniFile;
Begin
WritePort(PortCRTL,data);
Lpt8255Ini:=TIniFile.Create('Lpt8255.ini');
try
Lpt8255Ini.WriteInteger('8255 ID '+IntTostr(F8255Id), 'CrtlPort', Data);
finally
Lpt8255Ini.Free;
end;
// FPortCrtlData:=data;
end; procedure Tlpt8255_.SetBit(BitNo:byte;Value:Boolean);
Var ShiftMask,MaskData:Byte;
Port:TPort;
Begin
If ((BitNo>71) or (BitNo<0)) then Raise Exception.Create('Bit Value range error');
Id_8255:=Trunc(BitNo / 24);
case Trunc((BitNo mod 24) /8) of
0:Port:=PortA;
1:Port:=PortB;
2:Port:=PortC;
end;
ShiftMask:=(BitNo mod 24) mod 8;
MaskData:=1;
if Value=True then
begin
Case Port of
PortA:PortAData:=(PortAData or (MaskData shl ShiftMask));
PortB:PortBData:=(PortBData or (MaskData shl ShiftMask));
PortC:PortCData:=(PortCData or (MaskData shl ShiftMask));
end;
end
else//value=False
begin
Case Port of
PortA:PortAData:=(PortAData and (not (MaskData shl ShiftMask)));
PortB:PortBData:=(PortBData and (not (MaskData shl ShiftMask)));
PortC:PortCData:=(PortCData and (not (MaskData shl ShiftMask)));
end;
end;
end;
Function Tlpt8255_.GetBit(BitNo:Byte):Boolean;
Var ShiftMask,MaskData:Byte;
Port:TPort;
Begin
If ((BitNo>71) or (BitNo<0)) then Raise Exception.Create('Bit Value range error');
Id_8255:=Trunc(BitNo / 24);
case Trunc((BitNo mod 24) /8) of
0:Port:=PortA;
1:Port:=PortB;
2:Port:=PortC;
end;
ShiftMask:=(BitNo mod 24) mod 8;
MaskData:=1;
Case Port of
PortA:Result:=(PortAData and (MaskData shl ShiftMask))<>0;
PortB:Result:=(PortBData and (MaskData shl ShiftMask))<>0;
PortC:Result:=(PortCData and (MaskData shl ShiftMask))<>0;
end;
end;
{
Function Tlpt8255_.ByteToBin(Value:Byte):String;
var i:integer;
begin
result:='';
for i:=0 to 7 do
if (Value and (1 shl i)) <>0 then Result:='1' Result
else Result:='0' Result;
end;
Function Tlpt8255_.ByteToHex(Value:Byte):String;
Begin
Result:=IntTohex(Value,2);
end;
Function Tlpt8255_.BinToByte(Value:String):Byte;
var i,len:integer; begin
result:=0;
len:=8;
if StrLen(PChar(Value))<8 then len:=StrLen(PChar(Value));
for i:=1 to len do begin
if Value[i]='1' then result:=result or (1 shl (8-i));
end;
end;
//---------------------------------------------------------
function Exponent(Base,Count:integer):longInt;
var i:integer;
begin
if Count = 0 then
Result:=1
else
begin
Result:=1;
for i:= 1 to Count do
Result:=Result*Base;
end;//...else
end;//...function Exponent
var TransTable:array[0..5] of Integer=(10,11,12,13,14,15);
Function Tlpt8255_.HexToByte(Value:String):Byte;
var I,j,Temp,InPutDataLength:integer;
InPutData:string; begin
InPutData:=Uppercase(value);
InPutDataLength:=Length(Value);
Result:=0;
for i:= 1 to InPutDataLength do
begin
case InPutData[i] of
'0'..'9':
Temp:=StrToInt(InPutData[i]);
'A'..'F':
Temp:=transtable[Ord(InPutData[i])-ord('A')];
end;//...case
Result:=Temp*Exponent(16,InPutDataLength-i) result;
end;//...for
end;//...function
}
end. //************************************************** //
// 印表機介面8255 io 卡,網路client元件 //
//設計:張勇富 email:ufau0083@ms11.hinet.net //
//伺服端配合 Lpt8255ServerWindow.exe Window 95/98/NT//
//1999/5/8 版本:1.0 //
//1999/7/7 增加RegFileName的屬性 //
//************************************************** //
unit Lpt8255Client;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Lpt8255,Winsock,Wsocket,Client8255Server_H,registry; type
{$H }
TLpt8255Client = class(TLpt8255_)
private
Wsocket:Twsocket;//提供UDP 網路傳輸功能的元件
FProtol:string; //可選用 TCP or UDP 協定
FIP:string; //遠端主機的IP
FRemotePort:string; //遠端主機服務的PORT
FLocalPort:string; //本地端主機服務的PORT
FConnect:Boolean;
FReciveTimeOut:integer; //等待SERVER 回傳的最長時間
FDebugReport:boolean; //提供讀寫PORTA,PORTB,PORTC
//若是有錯誤是否舉發例外,
FRegFile:string; // 紀錄網路配置參數
procedure SetIP(Value:string);
Function GetIP:string;
procedure SetRemotePort(Value:string);
Function GetRemotePort:string;
procedure SetLocalPort(Value:string);
Function GetLocalPort:string;
protected
procedure WritePort(port:TPort;Value:byte);override;
function ReadPort(port:TPort):Byte;override;
procedure Loaded;override;
property LocalPort:string read GetLocalPort write SetLocalPort;
property RemotePort:string read GetRemotePort write SetRemotePort; public
Constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SetRegFile(Value:string);
Function GetRegFile:String;
function SendRecive(Value:dword):string;
Function Test8255(var Status:String):Boolean;override;
Procedure Set8255ID(value:byte);override;
procedure OutPortB(Address:Word;data:byte);override;
//從輸入口讀取資料
function InPortB(Address:word):byte;override;
// function Get8255ID:Byte; 本函數沿用其祖先所以不會從伺服端讀取
//只會讀本端的8255ID
procedure SetBit(BitNo:byte;Value:Boolean);override;
Function GetBit(BitNo:Byte):Boolean;override;
//procedure SetEnabled(Value:Boolean); 本函數沿用其祖先所以不會從伺服端讀取
//只會讀本端的FENABLED 的變數
property PortAData;
property PortBData;
property PortCData;
property PortCrtlData;
Property PrinterAddress;
published //給物件觀測器叫用的屬性
property RegFileName:string read FRegFile write FRegFile;
property ID_8255;
property Enabled;
property ServerIP:string read GetIP write SetIP;
property ReciveTimeOut_ms:integer read FReciveTimeOut write FreciveTimeOut;
property DebugReport:boolean read FDebugReport write FDebugReport;
end; procedure Register; implementation
//************************************************************************//
procedure Register;
begin
RegisterComponents('張勇富', [TLpt8255Client]);
end;
//**********************************************************************//
Constructor TLpt8255Client.Create(AOwner: TComponent);
Begin
inherited Create(AOwner);
try
Wsocket:=TWsocket.Create(self);
except
raise Exception.Create('Create Client Winsock error!');
end;
FProtol:='udp';
FremotePort:='1111';
FLocalPort:='9999';
FConnect:=False;
Fip:='255.255.255.255';
FReciveTimeOut:=250; // 250MS 當網路通信速度變慢時,最好數值用較大些
FDebugReport:=False;
end;
//**********************************************************************//
procedure Tlpt8255Client.Loaded;
begin
inherited;
GetRegFile;
end;
destructor TLpt8255Client.Destroy;
begin
Wsocket.free;
inherited;
end;
procedure TLpt8255Client.SetRegFile(Value:string);
var regFile:TregIniFile; begin
if CsDesigning in ComponentState then exit;
if Value<>FregFile then FRegFile:=Value;
if FregFile='' then exit;
Try
RegFile:=TRegIniFile.Create('Lpt8255Client');
RegFile.WriteString(FregFile,'Remote local', FIP);
RegFile.WriteInteger(FregFile,'Recive TimeOut',FReciveTimeOut);
if FDebugReport then
RegFile.WriteString(FregFile,'Debug Report','True')
else
RegFile.WriteString(FregFile,'Debug Report','False');
Finally
RegFile.Free;
end;
end;
Function TLpt8255Client.GetRegFile:String;
var regFile:TregIniFile;
TempIp:string;
TempTimeOut:integer;
TempBool:string;
begin
if FregFile='' then exit;
Try
RegFile:=TRegIniFile.Create('Lpt8255Client');
TempIP:=RegFile.ReadString(FregFile,'Remote local','');
if TempIP<>'' then FIP:=TempIP;
TempTimeOut:=RegFile.ReadInteger(FregFile,'Recive TimeOut',0);
if TempTimeOut<>0 then FReciveTimeOut:=TempTimeOut;
TempBool:=RegFile.ReadString(FregFile,'Debug Report','');
if TempBool<>'' then if
TempBool='True' then FDebugReport:=True
else FDebugReport:=False;
Finally
RegFile.Free;
result:=FregFile;
end;
end;
procedure TLpt8255Client.SetIP(Value:string); begin
// if FConnect then raise Exception.Create(' 連線中不可更改 IP')
// else if (Value<>FIP) then FIP:=Value;
if (Value<>FIP) then FIP:=Value;
end;
Function TLpt8255Client.GetIP:string;
begin
result:=FIP;
end;
procedure TLpt8255Client.SetRemotePort(Value:string);
begin
if (Value<>FRemotePort) then FRemotePort:=Value;
end;
Function TLpt8255Client.GetRemotePort:string;
begin
result:=FRemotePort;
end;
procedure TLpt8255Client.SetLocalPort(Value:string);
begin
// if FConnect then raise Exception.Create(' 連線中不可更改 Local PORT')
// else if (Value<>FLocalPort) then FLocalPort:=Value;
if (Value<>FLocalPort) then FLocalPort:=Value;
end;
Function TLpt8255Client.GetLocalPort:string;
begin
result:=FLocalPort;
end;
//***********************************************************//
//命令格式是4個位元組,以十六進制表示如下格式 //
//ccccppdd cccc共2個位元組是命令种類 //
// pp共1個位元組表示Port 或 BitNo //
// dd共1個位元組表示 port 的值 0..255 //
// 或是 SetBit otr GetBit //
//***********************************************************//
//1999/7/5 修改為下列格式
//***********************************************************//
//命令格式是4個位元組,以十六進制表示如下格式 //
//ccppppdd cc共1 個位元組是命令种類 //
// pppp共2個位元組表示Port 或 BitNo 或I/O位址 //
// dd共1個位元組表示 port 的值 0..255 //
// 或是 SetBit //
// 或是 OutportB //
//***********************************************************//
Function TLpt8255Client.SendRecive(Value:dword):String;
var Buffer:string;
TimeOut:integer;
begin
//當元件在設計或載入階段立刻離開本函數
if (csDesigning in ComponentState) or (csLoading in ComponentState) then exit;
if not FEnabled then exit;
//每次傳輸狀態未完全結束時,不執行,所以若傳送資料速度大於處理速度時
//資料將會漏失
if Wsocket.State<>wsClosed then exit;
WSocket.Proto := FProtol;
WSocket.Addr := FIP;
WSocket.Port := FRemotePort;
WSocket.LocalPort := FLocalPort;
WSocket.Connect;//開始通信連線
FConnect:=True;
WSocket.SendStr(IntTostr(Value)); //傳送一筆資料
//ReadLine(timeOut,Buffer) 是直接向遙控主機讀取回送資訊
//若是在timeout用完之後,沒有資訊則buffer為空,若是有有資訊
//也要在timout 用完之後才能返回,意界是此指令一定要浪費
//timeout的時間才能完成
buffer:='';
TimeOut:=0;
while (buffer='') do begin
Wsocket.ReadLine(-1,Buffer);//1 ms
inc(timeout);
if Timeout >FReciveTimeOut then begin
buffer:=WaitReciveTimeOut;
break;
end;//if
end;//while
//解決ReadLine Timeout不用完就不返回的問題
WSocket.Close;//關閉本次傳輸
FConnect:=False;
result:=Buffer;//伺服端傳回的資料
end;
//*********************************************************************//
//本函數最好在開始執行控制前執行,一來確定伺服端是否存在,二來介面卡是否有故障
Function TLpt8255Client.Test8255(var Status:String):Boolean;
var Temp:string;
tempEnabled:boolean;
begin
TempEnabled:=enabled;//保留原來的Enabled,避免被本函數破坯
enabled:=True;
ID_8255:=F8255ID;//同步伺服端與Client 中8255的ID
Temp:= SendRecive(Test8255Msg);
if Temp=TESTOK then begin
Status:='';
result:=True;
end else begin
Status:=Temp;
result:=False;
end;
enabled:=False;
Enabled:=Tempenabled;
end;
//*********************************************************************//
Procedure TLpt8255Client.Set8255ID(value:byte);
var Temp:string;
begin
inherited;
if (csDesigning in ComponentState) or (csLoading in ComponentState) then exit;
case Value of
0:begin
remotePort:='1111';
LocalPort:='9999';
end;
1:begin
remotePort:='2222';
LocalPort:='8888';
end;
2:begin
remotePort:='3333';
LocalPort:='7777';
end;
end;
if not FEnabled then exit;
inherited;
Temp:= SendRecive(Set8255IDMsg or Value);//傳送命令舉8255ID的值
if (Temp<>Set8255IDOK) and DebugReport then
raise Exception.Create(Set8255IDFail);
end ;
//*********************************************************************//
procedure TLpt8255Client.WritePort(port:TPort;Value:byte);
var temp:string;
Begin
if not FEnabled then exit;
case port of
PORTA:begin
Temp:= SendRecive(WritePortAMsg or Value);
//當寫入錯誤時,若舉發錯誤,就會產生一個提示視窗
//若快速寫入而且一直錯誤,可能會因產生太多視窗而當機
//所以慢速而且安全的傳輸是必要的,可令DebugReport:=True
if (Temp<>WriteOK) and DebugReport then
raise Exception.Create(WritePortAFail);
end;
PORTB:begin
Temp:= SendRecive(WritePortBMsg or Value);
if (Temp<>WriteOK) and DebugReport then
raise Exception.Create(WritePortBFail);
end;
PORTC:begin
Temp:= SendRecive(WritePortCMsg or Value);
if (Temp<>WriteOK) and DebugReport then
raise Exception.Create(WritePortCFail);
end;
PORTCRTL:begin
Set8255ID(F8255ID);
Temp:= SendRecive(WritePortCRTLMsg or Value);
if (Temp<>WriteOK) and DebugReport then
raise Exception.Create(WritePortCRTLFail);
end;
end;//case
end;
function TLpt8255Client.ReadPort(port:TPort):Byte;
var temp:string;
Begin
if not FEnabled then exit;
case port of
PORTA:begin
Temp:= SendRecive(ReadPortAMsg);
try
//讀回的資料若不能轉換成整數就是錯誤,而且會舉發例外
//而在except的區塊中處理
result:=StrToInt(temp);
except
result:=255;
if DebugReport then raise Exception.Create(ReadPortAFail);
end;
end;
PORTB:begin
Temp:= SendRecive(ReadPortBMsg);
try
result:=StrToInt(temp);
except
result:=255;
if DebugReport then raise Exception.Create(ReadPortBFail);
end;
end;
PORTC:begin
Temp:= SendRecive(ReadPortCMsg);
try
result:=StrToInt(temp);
except
result:=255;
if DebugReport then raise Exception.Create(ReadPortCFail);
end;
end;
PORTCRTL:begin
Temp:= SendRecive(ReadPortCRTLMsg);
try
result:=StrToInt(temp);
except
result:=255;
if DebugReport then raise Exception.Create(ReadPortCRTLFail);
end;
end;
end;//case end;
//*********************************************************************//
procedure TLpt8255Client.SetBit(BitNo:byte;Value:Boolean);
var temp:string;
tempValue:integer;
Begin
if not FEnabled then exit;
if Value then TempValue:=1 else tempValue:=0; Temp:= SendRecive(SetBitMsg or (BitNo shl 8) or TempValue);
if (Temp<>SetBitOK) and DebugReport then
raise Exception.Create(SetBitFail);
end;
//*********************************************************************//
Function TLpt8255Client.GetBit(BitNo:Byte):Boolean;
var temp:string;
tempValue:integer;
Begin
if not FEnabled then exit;
Temp:= SendRecive(GetBitMsg or (BitNo shl 8));
try
StrToInt(temp);//讀回的資料若不能轉換成整數就是錯誤,而且會舉發例外
//而在except的區塊中處理
if temp='0' then result:=False else result:=True;
except
result:=True;
if DebugReport then raise Exception.Create(GetBitFail);
end;
end;
//---------------------------------------------------------
procedure TLpt8255Client.OutPortB(Address:word;data:byte);
var temp:string;
Begin
if not FEnabled then exit;
Temp:= SendRecive(OutPortBMsg or (Address shl 8) or data);
if (Temp<>OutPortBOK) and DebugReport then
raise Exception.Create(OutPortBFail);
end;
//*********************************************************************//
Function TLpt8255Client.InportB(Address:word):Byte;
var temp:string;
tempValue:integer;
Begin
if not FEnabled then exit;
Temp:= SendRecive(InportBMsg or (Address shl 8));
try
result:=StrToInt(temp);//讀回的資料若不能轉換成整數就是錯誤,而且會舉發例外
//而在except的區塊中處理
except
result:=0;
if DebugReport then raise Exception.Create(InportBFail);
end;
end; end. *********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind to make knowledge together!
希望能大家敞開心胸,將知識寶庫結合一起
------
********************************************************** 哈哈&兵燹 最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知 K.表Knowlege 知識,就是本站的標語:Open our mind |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |