谁能够送我一个利用api实现的串口通信程序?(200分)

  • 主题发起人 主题发起人 hua8hua
  • 开始时间 开始时间
H

hua8hua

Unregistered / Unconfirmed
GUEST, unregistred user!
<FONT color=#ff3300>谁能够送我一个利用api实现的串口通信程序?
要求:
1:利用api实现;
2:多线程(读线程和写线程)
3:具有串口事件处理过程;

只要符合要求,马上给分。
</font>
 
Delphi 中 串 行 通 信 的 实 现
王 琛
  随着现代信息技术的发展以及计算机网络的广泛使用,计算机通信技术已经日臻成熟,但串行通信作为一种灵活方便可靠的通信方式,仍不失为有效的通信手段,被广泛应用于工业控制中。在工业生产实践中,用PC机对工程实现实时监控,通常要求PC机能在用户界面上具有数据采集、数据处理以及控制信号的产生与传输等功能。在这种特定的环境下,PC机要与过程控制的实时信号相联系,就要求能实现对PC机的串行端口直接操作。Borland公司推出的Delphi是一种功能强大的高级编程语言,其具有的可视化面向对象的特性,特别适于在Windows环境下图形界面和用户程序的编制。本文就是介绍基于Windows95/NT操作系统用Delphi来实现PC机与下层PLC控制器之间的串口通信方法。

基于WIN95/NT的串行通信机制
  Windows操作系统的机制禁止应用程序直接访问计算机硬件,但它为程序员提供了一系列的标准API函数,使得应用程序的编制更加方便并且免除了对有关硬件的调试麻烦。在Windows95/NT中,原来Windows3.X的WM_COMMNOTIFY消息已被取消,操作系统为每个通信设备开辟了用户可定义大小的读/写缓冲区,数据进出通信口均由操作系统后台完成,应用程序只需对读/写缓冲区操作即可。WIN95/NT中几个常用的串行通信操作函数如下:

   CreatFile  : 打开串行口
   CloseHandle : 关闭串行口
   SetupComm  : 设置通信缓冲区的大小
   ReadFile   : 读串口操作
   WriteFile  : 写串口操作
   SetCommState : 设置通信参数
   GetCommState : 获取默认通信参数
   ClearCommErro: r清除串口错误并获取当前状态
   除上述几个函数外,还要经常用到一个重要的记录DCB(设备控制块)。DCB中记录有可定义的串行口参数,设置串行口参数时必须先用GetCommState函数将系统默认值填入DCB控制块,然后才可把用户想改变的自定义值设定。在WIN95/NT中进行串行通信除了解基本的通信操作函数外,还要掌握多线程编程。线程是进程内部执行的路径,是操作系统分配CPU时间的基本实体。每个进程都由单线程开始完成应用程序的执行。串行通信需要利用多线程技术实现,其主要的处理逻辑可以表述如下:进程一开始先由主线程做一些必要的初始化工作,然后主线程根据需要在适当时候建立通信监视线程监视通信口,当指定的串行口事件发生时,向主线程发送WM_COMMNOTIFY消息(由于WIN95取消了WM_COMMNOTIFY消息,因此必须自己创建),主线程对其进行处理。若不需要WM_COMMNOTIFY消息,则主线程终止通信监视线程。多线程同时执行,将会引起对共享资源的冲突。为避免冲突,就要用同步多线程对共享资源进行访问。WIN95提供了许多保持线程同步的方法,笔者采用创建事件对象来保持线程同步。通过CraeteEvent()创建事件对象,使用SetEvent() 或PulseEvent()函数将事件对象设置成信号同步。在应用程序中,利用WaitSingleObject() 函数等待同步的触发,等到指定的事件被其它线程设置为有信号时,才继续向下执行程序。

Delphi下的具体实现方法
  Delphi的强大功能和支持多线程的面向对象编程技术,使得实现串行通信非常简单方便。它通过调用外部的API函数来实现,主要步骤如下:首先,利用CreateFile函数打开串行口,以确定本应用程序对此串行口的占有权,并封锁其它应用程序对此串口的操作;其次,通过GetCommState函数填充设备控制块DCB,再通过调用SetCommState函数配置串行口的波特率、数据位、校验位和停止位。然后,创建串行口监视线程监视串行口事件。在此基础上就可以在相应的串口上操作数据的传输;最后,用CloseHandle函数关闭串行口。具体的程序如下,本程序用Delphi3.0编制在Win95环t境下调试通过,已投入实际应用中,供广大读者参考。
程序:
unit comdemou;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
const
Wm_commNotify=Wm_User+12;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
Procedure comminitialize;
Procedure MsgcommProcess(Var Message:Tmessage); Message Wm_commnotify;
{ Private declarations }
public
{ Public declarations }
end;
// 线 程 声 明
TComm=Class(TThread)
protected
procedure Execute;override;
end;
var
Form1: TForm1;
hcom,Post_Event:Thandle;
lpol:Poverlapped;
implementation
{$R *.DFM}
Procedure TComm.Execute; // 线 程 执 行 过 程
var
dwEvtMask:Dword;
Wait:Boolean;
Begin
fillchar(lpol,sizeof(toverlapped),0);
While True do Begin
dwEvtMask:=0;
Wait:=WaitCommEvent(hcom,dwevtmask,lpol); // 等 待 串 行 口 事 件;
if Wait Then Begin
waitforsingleobject(post_event,infinite); // 等 待 同 步 事 件 置 位;
resetevent(post_event); // 同 步 事 件 复 位;
PostMessage(Form1.Handle,WM_COMMNOTIFY,0,0);// 发 送 消 息;
end;
end;
end;

procedure Tform1.comminitialize; // 串 行 口 初 始 化
var
lpdcb:Tdcb;
Begin
hcom:=createfile('com2',generic_read or generic_write,0,nil,open_existing,
file_attribute_normal or file_flag_overlapped,0);// 打 开 串 行 口
if hcom=invalid_handle_value then
else
setupcomm(hcom,4096,4096); // 设 置 输 入, 输 出 缓 冲 区 皆 为4096 字 节
getcommstate(hcom,lpdcb); // 获 取 串 行 口 当 前 默 认 设 置
lpdcb.baudrate:=2400;
lpdcb.StopBits:=1;
lpdcb.ByteSize:=8;
lpdcb.Parity:=EvenParity; // 偶 校 验
Setcommstate(hcom,lpdcb);
setcommMask(hcom,ev_rxchar);
// 指 定 串 行 口 事 件 为 接 收 到 字 符;
end;
Procedure TForm1.MsgcommProcess(Var Message:Tmessage);
var
Clear:Boolean;
Coms:Tcomstat;
cbNum,ReadNumber,lpErrors:Integer;
Read_Buffer:array[1..100]of char;
Begin
Clear:=Clearcommerror(hcom,lpErrors,@Coms);
if Clear Then Begin
cbNum:=Coms.cbInQue;
ReadFile(hCom,Read_Buffer,cbNum,ReadNumber,lpol);
// 处 理 接 收 数 据
SetEvent(Post_Event); // 同 步 事 件 置 位
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
comminitialize;
post_event:=CreateEvent(nil,true,true,nil); // 创 建 同 步 事 件;
Tcomm.Create(False); // 创 建 串 行 口 监 视 线 程;
end;
end.
 
再给你一片,记得给分(*_*)
网络和通讯编程
打开拨号连接
  调用拨号网络里的拨号程序来连接:其中'连接Internet'为你创建的拨号程序名称
winexec('rundll32.exe rnaui.dll,RnaDial '+'连接Internet',9);

一个串口通讯的问题?
Serial Port Communications?
问:
I want to build a simple electrical controller which receives input from a
sensor through a comm port and either turns a power source(s) on or off based
upon this signal. I want this controller to be software in nature.How do I
communicate through the port and is it possible to discern changes in voltage.
If not, what kind of signal must be input.
答:
When you want to write and read only binary signals you can use the printer
parallel port. For that purpose the Port command is useful. In the below an
example of some D1 code used for bidirectional 2 wire bus communication (I2C).
BaseAddress is $278, $378 or $3BC,depending on the LPT port used for communicati
on.There is a 'but'. In D1 the port function was available but not documented.
In D2 and D3 it seems to have disappeared entirely (Please somebody correct me
if this is wrong).We are using the parallel printer port with attached a small
interface card with some I/O buffering for control of RF modules. Could
somebody indicate whether the Port function still exist or what the alternative
could be ? regards,
Hans Brekelmans.
PROCEDURE SetIICline(Terminal: IICterminalTypes; High: Boolean);
Var Count : Word;
CtrlAddress: word;
Begin { set iic line }
CtrlAddress:=BaseAddress+2;
Case Terminal of
SCL : if High then Port[CtrlAddress]:=$08 else Port[CtrlAddress]:=$00;
SDA : if NOT High then Port[BaseAddress]:=$80 else Port[BaseAddress]:=$00;
END;
For Count := 1 to ClockDelay do;
End; {SetIICline}
FUNCTION GetIICline(Terminal: IICterminalTypes): Boolean;
const SDA_IN=$80; { SDA: 25 pin #11, status, NOT BUSY, bit 7 }
SCL_IN=$08; { SCL: 25 pin #15, status, NOT Error, bit 3 }
var Count : Word;
ReadAddress: word;
Begin
ReadAddress:=BaseAddress+1;
CASE Terminal OF
SCL: GetIICline:=((Port[ReadAddress] AND SCL_IN) = SCL_IN);
SDA: GetIICline:=((Port[ReadAddress] AND SDA_IN) = SDA_IN); { read sda
pin }
END;
For Count := 1 to ClockDelay do;
End;

得到本机IP地址?
How about using winsockets?
This code is untested and ugly.
program get_ip;
uses
winsock,sysutils;
VAR
ch : ARRAY[1..32] OF Char;
i : Integer;
WSData: TWSAData;
MyHost: PHostEnt;
begin
IF WSAstartup(2,wsdata)<>0 THEN
BEGIN
Writeln('can''t start Winsock: Error ',WSAGetLastError);
Halt(2);
END;
try
IF getHostName(@ch[1],32)<>0 THEN
BEGIN
Writeln('getHostName failed');
Halt(3);
END;
except
Writeln('getHostName failed');
halt(3);
end;
MyHost:=GetHostByName(@ch[1]);
IF MyHost=NIL THEN
BEGIN
Writeln(GetHostName('+StrPas(@ch[1])+') failed : Error
'+IntToStr(WSAGetLastError));
Halt(4);
END
ELSE
BEGIN
Write('address ');
FOR i:=1 TO 4 DO
BEGIN
Write(Ord(MyHost.h_addr^[i-1]));
IF i<4 THEN
then write('.')
ELSE
writeln;
END;
END;
end.

任何动态改变/添加网络设置中的 TCP/IP 的 DNS 地址
例如,把 DNS Server的地址添加为192.0.0.1和192.1.1.0,可调用:
SetTCPIPDNSAddresses('192.0.0.1 192.1.1.0') ;
// 各地址之间用一个空格隔开
1. SetTCPIPDNSAddresses 定义如下:
procedure SetTCPIPDNSAddresses( sIPs : string );
begin
//
// if using Windows NT
//
SaveStringToRegistry_LOCAL_MACHINE(
'SYSTEM/CurrentControlSet' +
'/Services/Tcpip/Parameters',
'NameServer',
sIPs );
//
// if using Windows 95
//
SaveStringToRegistry_LOCAL_MACHINE(
'SYSTEM/CurrentControlSet' +
'/Services/VxD/MSTCP',
'NameServer',
sIPs );
end;
2. 其中 SaveStringToRegistry_LOCAL_MACHINE 定义:
uses Registry;
procedure SaveStringToRegistry_LOCAL_MACHINE(
sKey, sItem, sVal : string );
var
reg : TRegIniFile;
begin
reg := TRegIniFile.Create( '' );
reg.RootKey := HKEY_LOCAL_MACHINE;
reg.WriteString( sKey, sItem, sVal + #0 );
reg.Free;
end;

如何在程序中动态取得Win95/98的网络邻居中的工作组及计算机名?
可参考下面代码,或许有所帮助:
procedure GetDomainList(TV:TTreeView);
var
a : Integer;
ErrCode : Integer;
NetRes : Array[0..1023] of TNetResource;
EnumHandle : THandle;
EnumEntries : DWord;
BufferSize : DWord;
s : string;
itm : TTreeNode;
begin
{ Start here }
try
With NetRes[0] do begin
dwScope :=RESOURCE_GLOBALNET;
dwType :=RESOURCETYPE_ANY;
dwDisplayType :=RESOURCEDISPLAYTYPE_DOMAIN;
dwUsage :=RESOURCEUSAGE_CONTAINER;
lpLocalName :=NIL;
lpRemoteName :=NIL;
lpComment :=NIL;
lpProvider :=NIL;
end;
{ get net root }
ErrCode:=WNetOpenEnum(
RESOURCE_GLOBALNET,
RESOURCETYPE_ANY,
RESOURCEUSAGE_CONTAINER,
@NetRes[0],
EnumHandle
);
If ErrCode=NO_ERROR then begin
EnumEntries:=1;
BufferSize:=SizeOf(NetRes);
ErrCode:=WNetEnumResource(
EnumHandle,
EnumEntries,
@NetRes[0],
BufferSize
);
WNetCloseEnum(EnumHandle);
ErrCode:=WNetOpenEnum(
RESOURCE_GLOBALNET,
RESOURCETYPE_ANY,
RESOURCEUSAGE_CONTAINER,
@NetRes[0],
EnumHandle
);
EnumEntries:=1024;
BufferSize:=SizeOf(NetRes);
ErrCode:=WNetEnumResource(
EnumHandle,
EnumEntries,
@NetRes[0],
BufferSize
);
IF ErrCode=No_Error then with TV do try
a:=0;
Items.BeginUpDate;
Items.Clear;
Itm:=Items.Add(TV.Selected,string(NetRes[0].lpProvider));
Itm.ImageIndex:=0;
Itm.SelectedIndex:=0;
{ get domains }
下面的一个单元定义了一个组件. TNetworkBrowser, 可以枚举hierachical树上所有的网络资源. 实际上浏览是要花费很长时间的,这您可以通过在WINDOWS资源管理器中打开"整个网络" 来比较一下. 如果你设置SCOPE属性 为nsContext , 你就可以看到和网络邻居中一样的机器列表.
unit NetBrwsr;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TNetScope = (nsConnected, nsGlobal, nsRemembered, nsContext);
TNetResourceType = (nrAny, nrDisk, nrPrint);
TNetDisplay = (ndDomain, ndGeneric, ndServer, ndShare, ndFile, ndGroup,
ndNetwork, ndRoot, ndShareAdmin, ndDirectory, ndTree, ndNDSContainer);
TNetUsage = set of (nuConnectable, nuContainer);
TNetworkItems = class;
TNetworkItem = class
private
FScope: TNetScope;
FResourceType: TNetResourceType;
FDisplay: TNetDisplay;
FUsage: TNetUsage;
FLocalName: string;
FRemoteName: string;
FComment: string;
FProvider: string;
FSubItems: TNetworkItems;
public
constructor Create;
destructor Destroy; override;
property Scope: TNetScope read FScope;
property ResourceType: TNetResourceType read FResourceType;
property Display: TNetDisplay read FDisplay;
property Usage: TNetUsage read FUsage;
property LocalName: string read FLocalName;
property RemoteName: string read FRemoteName;
property Comment: string read FComment;
property Provider: string read FProvider;
property SubItems: TNetworkItems read FSubItems;
end;
TNetworkItems = class
private
FList: TList;
procedure SetItem(Index: Integer; Value: TNetworkItem);
function GetItem(Index: Integer): TNetworkItem;
function GetCount: Integer;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure Add(Item: TNetworkItem);
procedure Delete(Index: Integer);
property Items[Index: Integer]: TNetworkItem read GetItem write
SetItem; default;
property Count: Integer read GetCount;
end;
TNetworkBrowser = class(TComponent)
private
FItems: TNetworkItems;
FScope: TNetScope;
FResourceType: TNetResourceType;
FUsage: TNetUsage;
FActive: Boolean;
procedure Refresh;
procedure SetActive(Value: Boolean);
procedure SetScope(Value: TNetScope);
procedure SetResourceType(Value: TNetResourceType);
procedure SetUsage(Value: TNetUsage);
procedure EnumerateNet(NetItems: TNetworkItems; lpnr: PNetResource);
protected
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Open;
procedure Close;
property Items: TNetworkItems read FItems;
published
property Scope: TNetScope read FScope write SetScope default nsGlobal;
property ResourceType: TNetResourceType read FResourceType
write SetResourceType default nrAny;
property Usage: TNetUsage read FUsage write SetUsage default [];
property Active: Boolean read FActive write SetActive default False;
end;
implementation
type
PNetResourceArray = ^TNetResourceArray;
TNetResourceArray = array[0..0] of TNetResource;
{ TNetworkItem }
constructor TNetworkItem.Create;
begin
inherited;
FSubItems := TNetworkItems.Create;
end;
destructor TNetworkItem.Destroy;
begin
if FSubItems <> nil then
FSubItems.Free;
inherited;
end;
{ TNetworkItems }
constructor TNetworkItems.Create;
begin
inherited;
FList := TList.Create;
end;
destructor TNetworkItems.Destroy;
begin
Clear;
if FList <> nil then
FList.Free;
inherited;
end;
procedure TNetworkItems.SetItem(Index: Integer; Value: TNetworkItem);
begin
if (FList.Items[Index] <> nil) and (FList.Items[Index] <> Value) then
TNetworkItem(FList.Items[Index]).Free;
FList.Items[Index] := Value;
end;
function TNetworkItems.GetItem(Index: Integer): TNetworkItem;
begin
Result := TNetworkItem(FList.Items[Index]);
end;
procedure TNetworkItems.Clear;
begin
while Count > 0 do
Delete(0);
end;
procedure TNetworkItems.Add(Item: TNetworkItem);
begin
FList.Add(Item);
end;
procedure TNetworkItems.Delete(Index: Integer);
begin
if FList.Items[Index] <> nil then
TNetworkItem(FList.Items[Index]).Free;
FList.Delete(Index);
end;
function TNetworkItems.GetCount: Integer;
begin
if FList <> nil then
Result := FList.Count
else
Result := 0;
end;
{ TNetworkBrowser }
constructor TNetworkBrowser.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FItems := TNetworkItems.Create;
FScope := nsGlobal;
FResourceType := nrAny;
FUsage := [];
end;
destructor TNetworkBrowser.Destroy;
begin
if FItems <> nil then
FItems.Free;
inherited;
end;
procedure TNetworkBrowser.EnumerateNet(NetItems: TNetworkItems; lpnr:
PNetResource);
var
dwResult, dwResultEnum: Integer;
hEnum: THandle;
cbBuffer, cEntries, i: Integer;
nrArray: PNetResourceArray;
NewItem: TNetworkItem;
dwScope, dwType, dwUsage: Integer;
begin
cbBuffer := 16384;
cEntries := $FFFFFFFF;
case FScope of
nsConnected: dwScope := RESOURCE_CONNECTED;
nsGlobal: dwScope := RESOURCE_GLOBALNET;
nsRemembered: dwScope := RESOURCE_REMEMBERED;
nsContext: dwScope := RESOURCE_CONTEXT;
else
dwScope := RESOURCE_GLOBALNET;
end;
case FResourceType of
nrAny: dwType := RESOURCETYPE_ANY;
nrDisk: dwType := RESOURCETYPE_DISK;
nrPrint: dwType := RESOURCETYPE_PRINT;
else
dwType := RESOURCETYPE_ANY;
end;
dwUsage := 0;
if nuConnectable in FUsage then
dwUsage := dwUsage or RESOURCEUSAGE_CONNECTABLE;
if nuContainer in FUsage then
dwUsage := dwUsage or RESOURCEUSAGE_CONTAINER;
dwResult := WNetOpenEnum(dwScope, dwType, dwUsage, lpnr, hEnum);
if dwResult <> NO_ERROR then Exit;
GetMem(nrArray, cbBuffer);
repeat
dwResultEnum := WNetEnumResource(hEnum, cEntries, nrArray, cbBuffer);
if dwResultEnum = NO_ERROR then
for i := 0 to cEntries-1 do
begin
NewItem := TNetworkItem.Create;
case nrArray.dwScope of
RESOURCE_CONNECTED: NewItem.FScope := nsConnected;
RESOURCE_GLOBALNET: NewItem.FScope := nsGlobal;
RESOURCE_REMEMBERED: NewItem.FScope := nsRemembered;
RESOURCE_CONTEXT: NewItem.FScope := nsContext;
else
NewItem.FScope := nsGlobal;
end;
case nrArray.dwType of
RESOURCETYPE_ANY: NewItem.FResourceType := nrAny;
RESOURCETYPE_DISK: NewItem.FResourceType := nrDisk;
RESOURCETYPE_PRINT: NewItem.FResourceType := nrPrint;
else
NewItem.FResourceType := nrAny;
end;
case nrArray.dwDisplayType of
RESOURCEDISPLAYTYPE_GENERIC: NewItem.FDisplay := ndGeneric;
RESOURCEDISPLAYTYPE_DOMAIN: NewItem.FDisplay := ndDomain;
RESOURCEDISPLAYTYPE_SERVER: NewItem.FDisplay := ndServer;
RESOURCEDISPLAYTYPE_SHARE: NewItem.FDisplay := ndShare;
RESOURCEDISPLAYTYPE_FILE: NewItem.FDisplay := ndFile;
RESOURCEDISPLAYTYPE_GROUP: NewItem.FDisplay := ndGroup;
RESOURCEDISPLAYTYPE_NETWORK: NewItem.FDisplay := ndNetwork;
RESOURCEDISPLAYTYPE_ROOT: NewItem.FDisplay := ndRoot;
RESOURCEDISPLAYTYPE_SHAREADMIN: NewItem.FDisplay :=
ndShareAdmin;
RESOURCEDISPLAYTYPE_DIRECTORY: NewItem.FDisplay :=
ndDirectory;
RESOURCEDISPLAYTYPE_TREE: NewItem.FDisplay := ndTree;
RESOURCEDISPLAYTYPE_NDSCONTAINER: NewItem.FDisplay :=
ndNDSContainer;
else
NewItem.FDisplay := ndGeneric;
end;
NewItem.FUsage := [];
if nrArray.dwUsage and RESOURCEUSAGE_CONNECTABLE <> 0 then
Include(NewItem.FUsage, nuConnectable);
if nrArray.dwUsage and RESOURCEUSAGE_CONTAINER <> 0 then
Include(NewItem.FUsage, nuContainer);
NewItem.FLocalName := StrPas(nrArray.lpLocalName);
NewItem.FRemoteName := StrPas(nrArray.lpRemoteName);
NewItem.FComment := StrPas(nrArray.lpComment);
NewItem.FProvider := StrPas(nrArray.lpProvider);
NetItems.Add(NewItem);
// if container, call recursively
if (nuContainer in NewItem.FUsage) and (FScope <> nsContext) then
EnumerateNet(NewItem.FSubItems, @nrArray)
end;
until dwResultEnum = ERROR_NO_MORE_ITEMS;
FreeMem(nrArray);
WNetCloseEnum(hEnum);
end;
procedure TNetworkBrowser.Refresh;
begin
FItems.Clear;
if FActive then
EnumerateNet(FItems, nil);
end;
procedure TNetworkBrowser.SetActive(Value: Boolean);
begin
if Value <> FActive then
begin
FActive := Value;
Refresh;
end;
end;
procedure TNetworkBrowser.SetScope(Value: TNetScope);
begin
if Value <> FScope then
begin
FScope := Value;
Refresh;
end;
end;
procedure TNetworkBrowser.SetResourceType(Value: TNetResourceType);
begin
if Value <> FResourceType then
begin
FResourceType := Value;
Refresh;
end;
end;
procedure TNetworkBrowser.SetUsage(Value: TNetUsage);
begin
if Value <> FUsage then
begin
FUsage := Value;
Refresh;
end;
end;
procedure TNetworkBrowser.Open;
begin
Active := True;
end;
procedure TNetworkBrowser.Close;
begin
Active := False;
end;
end.

 
一个串口通讯的问题?


Serial Port Communications?

I want to build a simple electrical controller which receives input from a
sensor through a comm port and either turns a power source(s) on or off
based upon this signal. I want this controller to be software in nature.
How do I communicate through the port and is it possible to discern changes
in voltage.
If not, what kind of signal must be input.

When you want to write and read only binary signals you can use the printer
parallel port. For that purpose the Port command is useful. In the below an
example of some D1 code used for bidirectional 2 wire bus communication (I2C).
BaseAddress is $278, $378 or $3BC, depending on the LPT port used for
communication.

There is a 'but'. In D1 the port function was available but not documented. In
D2 and D3 it seems to have disappeared entirely (Please somebody correct me if
this is wrong).

We are using the parallel printer port with attached a small interface card
with some I/O buffering for control of RF modules. Could somebody indicate
whether the Port function still exist or what the alternative could be ?

regards,

Hans Brekelmans


PROCEDURE SetIICline(Terminal: IICterminalTypes; High: Boolean);
Var Count : Word;
CtrlAddress: word;
Begin { set iic line }
CtrlAddress:=BaseAddress+2;
Case Terminal of
SCL : if High then Port[CtrlAddress]:=$08 else Port[CtrlAddress]:=$00;
SDA : if NOT High then Port[BaseAddress]:=$80 else Port[BaseAddress]:=$00;
END;
For Count := 1 to ClockDelay do;
End; {SetIICline}

FUNCTION GetIICline(Terminal: IICterminalTypes): Boolean;
const SDA_IN=$80; { SDA: 25 pin #11, status, NOT BUSY, bit 7 }
SCL_IN=$08; { SCL: 25 pin #15, status, NOT Error, bit 3 }
var Count : Word;
ReadAddress: word;
Begin
ReadAddress:=BaseAddress+1;
CASE Terminal OF
SCL: GetIICline:=((Port[ReadAddress] AND SCL_IN) = SCL_IN);
SDA: GetIICline:=((Port[ReadAddress] AND SDA_IN) = SDA_IN); { read sda
pin }
END;
For Count := 1 to ClockDelay do;
End;
 
说真的,陈琛的程序,我试过,好象还有点问题。
 
to xujiancai:
这个程序我造就有了,也试过,有问题。
 
多人接受答案了。
 
后退
顶部