对于串口的操作可以直接使用API
我这里有一个自己近期使用的单元可以参考一下
我的中文注释出来居然是乱码,我懒得改了,讲究看吧
{ System Resource }
{ Copyright (c) 2005, CHR Corporation }
{ Date: 2005-10-01 }
{ Build: 2005-10-04 }
{ Author: muhx }
unit UntCommDefine;
interface
uses
Windows, Classes, SyncObjs, SysUtils, UntTypeDefine;
type
{ ´®¿ÚͨѶÀà }
TCom = class
private
FCriticalSection: TCriticalSection;
FHandle: THandle;
FComName: string;
FBaud: TBaudRate;
FParity: TParity;
FStopBit: TStopBit;
FDataBit: TDataBit;
FInQueue: Integer;
FOutQueue: Integer;
FReadTimeOut: Integer;
FWriteTimeOut: Integer;
FTimeOut: COMMTIMEOUTS;
FEventMask: Integer;
private
procedure Lock;
procedure Unlock;
public
constructor ComCreate(AComSet: TComSet);
destructor Destroy; override;
public
procedure ChangeComSet(const AComSet: TComSet);
procedure ChangeParity(AParity: TParity);
procedure CloseCom;
procedure OpenCom;
procedure PurgeCom;
function Enabled: Boolean;
function Read(var APData; ADataLen: Integer): Boolean;
function Write(var APData; ADataLen: Integer): Boolean;
public
function SendCommand(APCommand: PCmdParam): Boolean;
function HandtoClip(AAddress: Byte): Boolean;
function ReceiveData(APReceive: PByte; AReceiveLen: Integer): Boolean;
public
property gHandle: THandle read FHandle;
property gBaud: TBaudRate read FBaud default br57600;
property gDataBit: TDataBit read FDataBit default da8;
property gInQueue: Integer read FInQueue default 4096;
property gOutQueue: Integer read FOutQueue default 2048;
property gParity: TParity read FParity default paSpace;
property gStopBits: TStopBit read FStopBit default sb10;
property gReadTimeOut: Integer read FReadTimeOut default 2000;
property gComName: string read FComName;
property gWriteTimeOut: Integer read FWriteTimeout default 2000;
end;
implementation
{ ´´½¨´®¿ÚÀà }
constructor TCom.ComCreate(AComSet: TComSet);
begin
inherited Create;
{ ÁÙ½çÇø }
FCriticalSection := TCriticalSection.Create;
{ ´®¿Ú¿ØÖƾä±ú }
FHandle := INVALID_HANDLE_VALUE;
{ ´®¿Ú²ÎÊý }
FComName := COMComID[AComSet.csComID];
FParity := AComSet.csParity;
FBaud := AComSet.csBaud;
FDataBit := AComSet.csDataBit;
FStopBit := AComSet.csStopBit;
FInQueue := AComSet.csInQueue;
FOutQueue := AComSet.csOutQueue;
FReadTimeOut := AComSet.csReadTimeOut;
FWriteTimeOut := AComSet.csWriteTimeOut;
FEventMask := EV_RXCHAR;
{ Á½¸ö×Ö½Ú´«Êä¼ä¸ô }
FTimeOut.ReadIntervalTimeout := 30;
{ ÿ×Ö½Ú´«Êäʱ¼ä }
FTimeOut.ReadTotalTimeoutMultiplier := 5;
{ ûÓÐ×Ö½Úʱ·µ»Øʱ¼ä }
FTimeOut.ReadTotalTimeoutConstant := 80;
{ ÿ×Ö½Ú´«Êäʱ¼ä }
FTimeOut.WriteTotalTimeoutMultiplier := 5;
{ ´«Êäʱ¼ä³£Á¿ }
FTimeOut.WriteTotalTimeoutConstant := 50;
{ ´ò¿ª´®¿Ú }
OpenCom;
end;
{ ÊÍ·Å´®¿ÚÀà }
destructor TCom.Destroy;
begin
CloseCom;
if FCriticalSection <> nil then
begin
FCriticalSection.Free;
FCriticalSection := nil;
end;
inherited Destroy;
end;
{ &Aring;&ETH;&para;&Iuml;&acute;&reg;&iquest;&Uacute;&Ecirc;&Ccedil;·&ntilde;&acute;&acute;&frac12;¨ }
function TCom.Enabled: Boolean;
begin
Result := FHandle <> INVALID_HANDLE_VALUE;
end;
{ &sup1;&Oslash;±&Otilde;&acute;&reg;&iquest;&Uacute; }
procedure TCom.CloseCom;
begin
if Enabled then
begin
Sleep(100);
CloseHandle(FHandle);
FHandle := INVALID_HANDLE_VALUE;
end;
end;
{ &cedil;ü&cedil;&Auml;&acute;&reg;&iquest;&Uacute;&sup2;&Icirc;&Ecirc;&yacute; }
procedure TCom.ChangeComSet(const AComSet: TComSet);
var
tmpDCB: DCB;
begin
try
with AComSet do
begin
FParity := csParity;
FBaud := csBaud;
FDataBit := csDataBit;
FStopBit := csStopBit;
FInQueue := csInQueue;
FOutQueue := csOutQueue;
FReadTimeOut := csReadTimeOut;
FWriteTimeOut := csWriteTimeOut;
end;
if Enabled then
begin
tmpDCB.DCBlength := SizeOf(DCB);
GetCommState(FHandle, tmpDCB);
tmpDCB.BaudRate := COMBaudRate[FBaud];
tmpDCB.Parity := COMParity[FParity];
tmpDCB.ByteSize := COMDataBit[FDataBit];
tmpDCB.StopBits := COMStopBit[FStopBit];
if not (SetupComm(FHandle, FInQueue, FOutQueue) and SetCommState(FHandle, tmpDCB))
then Abort;
PurgeCom;
end;
except
on E: Exception do
begin
CloseCom;
end;
end;
end;
{ &cedil;ü&cedil;&Auml;&acute;&reg;&iquest;&Uacute;&AElig;&aelig;&Aring;&frac14;&ETH;&pound;&Ntilde;é&Eacute;è&Ouml;&Atilde; }
procedure TCom.ChangeParity(AParity: TParity);
var
tmpDCB: DCB;
begin
try
FParity := AParity;
if Enabled then
begin
tmpDCB.DCBlength := SizeOf(DCB);
GetCommState(FHandle, tmpDCB);
tmpDCB.Parity := COMParity[FParity];
if not SetCommState(FHandle, tmpDCB) then
Abort;
PurgeCom;
end;
except
on E: Exception do
begin
CloseCom;
end;
end;
end;
{ &frac12;&oslash;&Egrave;&euml;&Aacute;&Ugrave;&frac12;&ccedil;&Ccedil;&oslash; }
{ &Ocirc;&Uacute;&para;&Ocirc;&acute;&reg;&iquest;&Uacute;&frac12;&oslash;&ETH;&ETH;&sup2;&Ugrave;×÷&micro;&Auml;&Ecirc;±&ordm;ò&Egrave;·±&pound;&Atilde;&raquo;&Oacute;&ETH;&Iacute;&not;&Ecirc;±&frac12;&oslash;&ETH;&ETH;&AElig;&auml;&Euml;&ucirc;&sup2;&Ugrave;×÷ }
procedure TCom.Lock;
begin
FCriticalSection.Enter;
end;
{ &Iacute;&Euml;&sup3;&ouml;&raquo;&ordm;&sup3;&aring;&Ccedil;&oslash; }
procedure TCom.Unlock;
begin
FCriticalSection.Leave;
end;
{ &acute;&acute;&frac12;¨&acute;&reg;&iquest;&Uacute; }
procedure TCom.OpenCom;
var
tmpDCB: DCB;
begin
if Enabled then
Exit;
try
FHandle := CreateFile(PChar(FComName), GENERIC_READ or GENERIC_WRITE,
0, nil,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if not Enabled then
Abort
else begin
{ &Eacute;è&Ouml;&Atilde;&acute;&reg;&iquest;&Uacute;&sup2;&Icirc;&Ecirc;&yacute; }
tmpDCB.DCBlength := SizeOf(DCB);
GetCommState(FHandle, tmpDCB);
tmpDCB.BaudRate := COMBaudRate[FBaud];
tmpDCB.Parity := COMParity[FParity];
tmpDCB.ByteSize := COMDataBit[FDataBit];
tmpDCB.StopBits := COMStopBit[FStopBit];
if not (SetCommMask(FHandle, FEventMask) and
SetCommTimeouts(FHandle, FTimeOut) and
SetupComm(FHandle, FInQueue, FOutQueue) and
SetCommState(FHandle, tmpDCB) and
(FCriticalSection <> nil)) then
Abort;
end;
except
on E: Exception do
begin
CloseCom;
end;
end;
end;
{ &Ccedil;&aring;&iquest;&Otilde;&raquo;&ordm;&sup3;&aring;&Ccedil;&oslash; }
procedure TCom.PurgeCom;
begin
if Enabled then
begin
PurgeComm(FHandle, PURGE_RXCLEAR);
PurgeComm(FHandle, PURGE_TXCLEAR);
end;
end;
{ &acute;&Oacute;&acute;&reg;&iquest;&Uacute;&para;&Aacute;&Egrave;&iexcl;&Ecirc;&yacute;&frac34;&Yacute; }
function TCom.Read(var APData; ADataLen: Integer): Boolean;
var
tmpOverlapped: TOverlapped;
tmpEvent: TSimpleEvent;
tmpReceive: DWord;
begin
Result := True;
Lock;
tmpEvent := TSimpleEvent.Create;
try
tmpReceive := 0;
FillChar(tmpOverlapped, SizeOf(tmpOverlapped), 0);
tmpOverlapped.hEvent := tmpEvent.Handle;
if not ReadFile(FHandle, APData, ADataLen, DWord(tmpReceive),
@tmpOverlapped) and (GetLastError <> ERROR_IO_PENDING) then
Result := False;
if tmpEvent.WaitFor(FReadTimeOut) <> wrSignaled then
Result := False
else begin
GetOverlappedResult(FHandle, tmpOverlapped, DWord(tmpReceive), False);
tmpEvent.ResetEvent;
end;
finally
Unlock;
tmpEvent.Free;
if tmpReceive <> DWord(ADataLen) then
Result := False;
end;
end;
{ &Iuml;ò&acute;&reg;&iquest;&Uacute;&ETH;&acute;&Egrave;&euml;&Ecirc;&yacute;&frac34;&Yacute; }
function TCom.Write(var APData; ADataLen: Integer): Boolean;
var
tmpOverlapped: TOverlapped;
tmpEvent: TSimpleEvent;
tmpWrite: DWord;
begin
Lock;
Result := True;
tmpEvent := TSimpleEvent.Create;
try
tmpWrite := 0;
FillChar(tmpOverlapped, SizeOf(tmpOverlapped), 0);
tmpOverlapped.hEvent := tmpEvent.Handle;
if not WriteFile(FHandle, APData, ADataLen, DWord(tmpWrite),
@tmpOverlapped) and (GetLastError <> ERROR_IO_PENDING) then
Result := False;
if tmpEvent.WaitFor(FWriteTimeOut) <> wrSignaled then
Result := False
else begin
GetOverlappedResult(FHandle, tmpOverlapped, DWord(tmpWrite), False);
tmpEvent.ResetEvent;
end;
finally
Unlock;
tmpEvent.Free;
if tmpWrite <> DWord(ADataLen) then
Result := False;
end;
end;
{ ·&cent;&Euml;&Iacute;&Atilde;ü&Aacute;&icirc; }
function TCom.SendCommand(APCommand: PCmdParam): Boolean;
var
i: Integer;
begin
Result := False;
Lock;
try
i := 0;
while (i < 5) do
begin
{ &micro;&Oslash;&Ouml;·&Icirc;&Otilde;&Ecirc;&Ouml; }
ChangeParity(paMark);
if not HandtoClip(APCommand^.cmdAddress) then
begin
Inc(i);
Continue;
end;
{ ·&cent;&Euml;&Iacute;&Atilde;ü&Aacute;&icirc; }
ChangeParity(paSpace);
if not Write(APCommand^.cmdCommand, SizeOf(APCommand^.cmdCommand)) then
begin
Inc(I);
Continue;
end;
{ ·&cent;&Euml;&Iacute;&Ecirc;&yacute;&frac34;&Yacute; }
if APCommand^.cmdSendLen <> 0 then
begin
if not Write(APCommand^.cmdPSend^, APCommand^.cmdSendLen) then
begin
Inc(I);
Continue;
end;
end;
{ &frac12;&Oacute;&Ecirc;&Otilde;&Ecirc;&yacute;&frac34;&Yacute; }
if not ReceiveData(APCommand^.cmdPReceive, APCommand^.cmpReceiveLen) then
begin
Inc(I);
Continue;
end;
Result := True;
Break;
end;
finally
Sleep(100);
PurgeCom;
UnLock;
end;
end;
{ &Oacute;&euml;MCU&micro;&Oslash;&Ouml;·&Icirc;&Otilde;&Ecirc;&Ouml; }
function TCom.HandtoClip(AAddress: Byte): Boolean;
var
tmpRead: array[0..2] of Byte;
begin
{ ·&cent;&Euml;&Iacute;&micro;&Oslash;&Ouml;· }
if not Write(AAddress, SizeOf(AAddress)) then
begin
Result := False;
Exit;
end;
{ &para;&Aacute;&Egrave;&iexcl;&Ecirc;&yacute;&frac34;&Yacute; }
if not Read(tmpRead, SizeOf(tmpRead)) then
begin
Result := False;
Exit;
end;
{ ±&Egrave;&frac12;&Iuml;&Ecirc;&yacute;&frac34;&Yacute; }
if (tmpRead[0] <> $AA) or (tmpRead[1] <> $55) or (tmpRead[2] <> AAddress) then
begin
Result := False;
Exit;
end;
{ &Egrave;&ocirc;&frac12;&Oacute;&Ecirc;&Otilde;&sup3;&Eacute;&sup1;&brvbar;&Ccedil;&Ograve;&Ecirc;&yacute;&frac34;&Yacute;&Otilde;&yacute;&Egrave;··&micro;&raquo;&Oslash;True }
Result := True;
end;
{ &frac12;&Oacute;&Ecirc;&Otilde;&Ecirc;&yacute;&frac34;&Yacute;&pound;&not;&cedil;ù&frac34;&Yacute;&Iacute;¨&Ntilde;&para;&ETH;&shy;&Ograve;é&pound;&not;&Ocirc;&Uacute;&frac12;&Oacute;&Ecirc;&Otilde;&Ecirc;&yacute;&frac34;&Yacute;&Ccedil;°&Oacute;&ETH;AA55&Aacute;&frac12;×&Ouml;&frac12;&Uacute;&ETH;&pound;&Ntilde;é&Acirc;&euml; }
function TCom.ReceiveData(APReceive: PByte; AReceiveLen: Integer): Boolean;
var
tmpRead: array[0..1023] of Byte;
tmpPByte: PByte;
i: Integer;
begin
if AReceiveLen <> 0 then
begin
if Read(tmpRead, AReceiveLen + 2) then
begin
if (tmpRead[0] = $AA) and (tmpRead[1] = $55) then
begin
tmpPByte := APReceive;
for i := 0 to AReceiveLen - 1 do
begin
tmpPByte^ := tmpRead[i + 2];
Inc(tmpPByte);
end;
end
else
begin
Result := False;
Exit;
end;
end
else
begin
Result := False;
Exit;
end;
end
else
begin
if (not Read(tmpRead, 3)) or (tmpRead[0] <> $AA) or (tmpRead[1] <> $55) then
begin
Result := False;
Exit;
end;
if tmpRead[2] = $88 then
begin
Result := False;
Exit;
end
end;
Result := True;
end;
end.