江湖救急,com读些问题

duanbj 2004-01-12 03:14:13
各位,小弟编写的读取com的函数,在初始化的时候偶尔会有小恙,总是不很稳定,我运行的是win200系统,源代码如下,请帮忙指点一二,小弟不胜感激!
//读取POS函数,返回26位的字符串为有效
function ReadComm: String;
var
Len,number:Cardinal;
buff :Array[1..80] of char;
id : THandle;
dcb : TDCB;
ct : TCOMMTIMEOUTS;
osReader : OVERLAPPED;
i : Integer;
tempchar : char;
begin
Len := 1;
number := 0;
tempchar := '1';
buff[1] := '1';
For i := 2 to 80 do
begin
buff[i] := ' ';
end;
id := CreateFile('COM1',GENERIC_READ or GENERIC_WRITE,0,NIL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if id = null then
begin
Result := '创建或打开COM1出错';
end
else
begin
SetupComm(id,128,512);
PurgeComm(id,PURGE_TXCLEAR or PURGE_RXCLEAR);
if(Not(GetCommState(id,dcb))) then//在这个地方,有时就不正常
begin
CloseHandle(id);
Result := '绑定COM1出错';
end
else
begin
dcb.BaudRate := CBR_19200;
dcb.ByteSize := 8;
dcb.Parity := NOPARITY;
dcb.StopBits := ONESTOPBIT;
if(Not(SetCommState(id,dcb))) then
begin
CloseHandle(id);
Result := '初始化设置出错';
end
else
begin
//设置超时值
ct.ReadIntervalTimeout := MAXDWORD;
ct.ReadTotalTimeoutConstant := 500;
ct.ReadTotalTimeoutMultiplier := 0;
ct.WriteTotalTimeoutConstant := 0;
ct.WriteTotalTimeoutMultiplier := 0;
if(Not(SetCommTimeouts(id,ct))) then
begin
CloseHandle(id);
Result := '设置超时值出错';
end
else
begin
if (not WriteFile(id,tempchar,1,Len,Nil)) then
begin
CloseHandle(id);
Result := 'COM1写出错';
end
else
begin
while ( Length(Trim(buff))<=1 ) do
begin
ReadFile(id,buff,512,len,0);
Sleep(500);
number := number + 1;
if(number>60) then
begin
break;
end;
end;
CloseHandle(id);
if(number>60) then
begin
Result := '刷卡超时出错';
end
else
begin
Result := Copy(buff,1,26);
end;
end;
end;
end;
end;
end;
end;
...全文
27 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
ttzzj 2004-01-12
  • 打赏
  • 举报
回复
GetCommState(id,dcb)只是得到Comm的设置,以前的设置
ttzzj 2004-01-12
  • 打赏
  • 举报
回复

procedure TEYICCOMM.SendData(sData: PChar; len: DWORD);
var
dwLastError,

dwNumberOfBytesWritten,
dwWhereToStartWriting,

dwHandleSignaled: DWORD;
HandlesToWaitFor: array[0..1] of THandle;
begin
if hCommFile = 0 then
if OldCom = 0 then
raise Exception.Create('发送数据时串口还未打开')
else
OpenComm(OldCom,OldBaudRate);

PurgeComm( hCommFile, PURGE_RXCLEAR
+ PURGE_TXCLEAR );

dwNumberOfBytesWritten := 0;
dwWhereToStartWriting := 0; // Start at the beginning.


// Keep looping until all characters have been written.
repeat
// Start the overlapped I/O.
if not WriteFile( hCommFile,
sData[ dwWhereToStartWriting ],
Len, dwNumberOfBytesWritten,
lov ) then
begin
// WriteFile failed. Expected; lets handle it.
dwLastError := GetLastError;

// Its possible for this error to occur if the
// service provider has closed the port. Time to end.
if dwLastError = ERROR_INVALID_HANDLE then
Exit;

// Unexpected error. No idea what.
if dwLastError <> ERROR_IO_PENDING then
begin
Exit;
end;

// This is the expected ERROR_IO_PENDING case.

// Wait for either overlapped I/O completion,
// or for the CloseEvent to get signaled.
dwHandleSignaled := WaitForMultipleObjects(2, @HandlesToWaitFor,
False, INFINITE);

case dwHandleSignaled of
WAIT_OBJECT_0: // CloseEvent signaled!
begin
// Time to exit.
Exit;
end;

WAIT_OBJECT_0 + 1: // Wait finished.
begin
// Time to get the results of the WriteFile
if not GetOverlappedResult(hCommFile,
lov^,
dwNumberOfBytesWritten, True) then
begin
dwLastError := GetLastError;

// Its possible for this error to occur if the
// service provider has closed the port.
if dwLastError = ERROR_INVALID_HANDLE then
Exit;

// No idea what could cause another error.
Exit;
end
end;

WAIT_FAILED: // Wait failed. Shouldn't happen.
begin
Exit;
end

else // This case should never occur.
begin
Exit;
end
end {case}
end; {WriteFile failure}

// Some data was written. Make sure it all got written.

Dec( Len, dwNumberOfBytesWritten );
Inc( dwWhereToStartWriting, dwNumberOfBytesWritten );
until (Len <= 0); // Write the whole thing!

// Wrote the whole string.
end;
ttzzj 2004-01-12
  • 打赏
  • 举报
回复
type
TEYICCOMM=Class(TComponent)
protected

public
procedure OpenComm(ComNo:Integer;
BaudRate:Integer);
procedure CloseComm;
procedure SendData(sData: PChar; len: DWORD);
function ReceiveData(num: DWORD; rBuf: PChar): boolean;

private
hCommFile: THandle;
lov : pOverLapped;
OldCom: integer;
OldBaudRate: Integer;
published

end;
var
ECOM:TEYICCOMM;
{$R *.res}
procedure TEYICCOMM.CloseComm;
begin
if hCommFile<>0 then
begin
PurgeComm(hCommFile, PURGE_TXABORT
+PURGE_RXCLEAR
+PURGE_TXCLEAR
+PURGE_RXABORT
);
CloseHandle(hCommFile);
hCommFile := 0;
end;
end;

procedure TEYICCOMM.OpenComm(ComNo:Integer;
BaudRate:Integer);
var
dcb:Tdcb;
CommTimeOuts:TCommTimeOuts;
CommName:String;
dwErrorFlag:dword;
begin
CommName:='COM'+IntToStr(ComNo);
if (hCommFile <> 0) then //is already been opened by the application
begin
CloseHandle(hCommFile);
hCommFile := 0;
end;
hCommFile := CreateFile( PChar(CommName),
GENERIC_READ or GENERIC_WRITE,
0, //engloss
nil, // no security ??
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,
0 );

if hCommFile = INVALID_HANDLE_VALUE then
raise Exception.Create( '打开串口出错,确认串口是否被占用' );

// Is this a valid comm handle?
if GetFileType( hCommFile ) <> FILE_TYPE_CHAR then
begin
CloseHandle( hCommFile );
hCommFile := 0;
raise Exception.Create( '不是一个串口' )
end;

if not SetupComm( hCommFile, 512, 512 ) then
begin
CloseHandle( hCommFile );
hCommFile := 0;
raise Exception.Create( '不能设置串口缓冲' )
end;

dcb.DCBlength:= sizeof(TDCB);
GetCommState(hCommFile,dcb);
dcb.Flags:=1;
dcb.BaudRate:=BaudRate; //9600 BaudRate
dcb.Parity:=0; // n no Parity
dcb.ByteSize:=8; // 8 8 data bits
dcb.StopBits:=0; // 1 1 Stop bit
if not SetCommState(hCommFile,dcb) then
begin
dwErrorFlag:=GetLastError;
raise Exception.Create('设置串口参数失败'+IntToStr(dwErrorFlag));
end;

GetCommTimeOuts(hCommFile,CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout:=$0ffffffff;
CommTimeOuts.ReadTotalTimeoutMultiplier:=0;
CommTimeOuts.ReadTotalTimeoutConstant:=0;
CommTimeOuts.WriteTotalTimeoutMultiplier:=0;
CommTimeOuts.WriteTotalTimeoutConstant:=500;
if not SetCommTimeOuts(hCommFile,CommTimeOuts) then
begin
dwErrorFlag:=GetLastError;
raise Exception.Create('设置超时失败'+IntToStr(dwErrorFlag));
end;
SetCommMask(hCommFile,EV_RXCHAR);

PurgeComm( hCommFile, PURGE_RXCLEAR
+ PURGE_TXCLEAR );
OldCom := ComNo;
OldBaudRate := BaudRate;
end;

function TEYICCOMM.ReceiveData(num: DWORD; rBuf: PChar): boolean;
var
nRead : DWORD;
dwLastError:DWORD;
bSuccess: Boolean;
dwByteToRead: DWORD;
dwByteExist:DWORD;
readTime: Integer;
begin
dwByteToRead := num;
if hCommFile = 0 then
if OldCom = 0 then
begin
result := false;
Exit;
end
else begin
try
OpenComm(OldCom,OldBaudRate);
except
Result := false;
Exit;
end;
end;

ZeroMemory(lov,sizeof(POVERLAPPED));
lov.hEvent:= CreateEvent(nil,
false,
false,
nil);

readTime := 0;
WaitForSingleObject( lov.hEvent, 25 );
ResetEvent(lov.hEvent);
Sleep(0); //the time for publisher to send data back
bSuccess:=true;
while (dwByteToRead > 0) and (readTime<10) do
begin
dwByteExist:=dwByteToRead;
bSuccess := ReadFile(hCommFile,
rBuf^,
dwByteExist,
nRead,
lov) ;
dwByteToread := dwByteToRead - nRead;
ReadTime:=ReadTime+1;
if( GetLastError() = ERROR_IO_PENDING ) then
WaitForSingleObject( lov.hEvent, 10 );
if dwByteToRead > 0 then
Sleep(3);
end;
if not bSuccess then
begin
dwLastError:=GetLastError;
if dwLastError = ERROR_IO_PENDING then
begin
Result := true;
Exit;
end;

// Its possible for this error to occur if the
// service provider has closed the port. Time to end.
if dwLastError = ERROR_INVALID_HANDLE then
begin
result:=true;
Exit;
end;
end;
result:=true;
end;
duanbj 2004-01-12
  • 打赏
  • 举报
回复
好的,不胜感激!
可是,我有个问题,如果把com的信息不能读入到DCB中,那怎么能设置com的信息呢?
ttzzj 2004-01-12
  • 打赏
  • 举报
回复
我把我的类帖给你吧?
ttzzj 2004-01-12
  • 打赏
  • 举报
回复
dcb.DCBlength:= sizeof(TDCB); //重要
GetCommState(hCommFile,dcb); //结果无所谓
dcb.Flags:=1;
dcb.BaudRate:=BaudRate; //9600 BaudRate
dcb.Parity:=0; // n no Parity
dcb.ByteSize:=8; // 8 8 data bits
dcb.StopBits:=1; // 1 1 Stop bit
if not SetCommState(hCommFile,dcb) then
begin
dwErrorFlag:=GetLastError;
raise Exception.Create('设置串口参数失败'+IntToStr(dwErrorFlag));
end;
duanbj 2004-01-12
  • 打赏
  • 举报
回复
就是 GetCommState(id,dcb)执行的结果为0,不能把com的信息读入到dcb中,我就觉得纳闷,每次使用完后我都释放了com,可有时候可以,有时候就不行了,麻烦再看看,谢谢
lgqTiger 2004-01-12
  • 打赏
  • 举报
回复
不稳定时,提示什么?

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧