📄 rs232_api.pas
字号:
unit Rs232_Api;
interface
uses
Windows, Variants, SysUtils, Forms, pub_Funcs, Dialogs;
const
// 设备调用正常返回码
DEVICE_NORMAL = 0;
// 超时
E_TIMEOUT = 999;
// 端口初始化失败
E_PORT_INIT = 998;
// 设备尚未初始化
E_DEVICE_BEFORE_INIT = 997;
// 无效操作
E_VOID_ACTION = 996;
// 打印机少纸
W_LOW_PAPE = 19001;
// 打印机缺纸
E_NO_PAPE = 18001;
// 打印机卡纸
E_JAM_PAPE = 18002;
type
BYTES = array[1..255] of Byte;
TBYTES = ^BYTES;
var
CommHandle: THandle;
Connected: Boolean;
PostEvent: THandle;
ReadOs: Toverlapped;
Receive: Boolean;
ReceiveData: Dword;
szInputBuffer: Pointer;
Check_ErrorSum: integer;
DeviceLastError: integer;
ResponseData: array[0..255] of Byte;
function OpenCom(Port: pchar): integer; //打开串口
function CloseCom(): integer; //关闭串口
function ReadProcess(Timeout: integer): string; //以下是实际的读取动作,读取线程函数
function SendData(strOrder: string): Boolean; //发送数据
implementation
function OpenCom(Port: pchar): integer;
var
CommTimeOut: TCOMMTIMEOUTS;
DCB: TDCB;
ComStr: string;
begin
//发送消息的句柄
PostEvent := CreateEvent(nil, True, True, nil);
if PostEvent = null then begin
DeviceLastError := E_PORT_INIT;
Result := -1;
Exit;
end;
//Overlapped Read建立句柄
ReadOs.hEvent := CreateEvent(nil, True, FALSE, nil);
if ReadOs.hEvent = null then begin
//MessageBox(0, 'CreateEvent Error!', 'Notice', MB_OK);
DeviceLastError := E_PORT_INIT;
CloseHandle(PostEvent);
Result := -1;
Exit;
end;
//建立串口句柄
CommHandle := CreateFile(Port, GENERIC_WRITE or GENERIC_READ,
0, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED or FILE_ATTRIBUTE_NORMAL, 0);
if CommHandle = INVALID_HANDLE_VALUE then begin
CloseHandle(PostEvent);
CloseHandle(ReadOs.hEvent);
DeviceLastError := E_PORT_INIT;
Result := -1;
Exit;
end;
//设置超时
CommTimeOut.ReadIntervalTimeout := MAXDWORD;
CommTimeOut.ReadTotalTimeoutMultiplier := 0;
CommTimeOut.ReadTotalTimeoutConstant := 0;
SetCommTimeouts(CommHandle, CommTimeOut);
//设置读写缓存
SetupComm(CommHandle, 4096, 1024);
//对串口进行指定配置
GetCommState(CommHandle, DCB);
DCB.BaudRate := 9600;
DCB.ByteSize := 8;
DCB.Parity := 0; ;
DCB.StopBits := 0;
Connected := SetCommState(CommHandle, DCB);
//关系串口的读事件
if (not SetCommMask(CommHandle, EV_RXCHAR)) then begin
DeviceLastError := E_PORT_INIT;
Result := -1;
Exit;
end;
if (Connected) then begin
Connected := True;
Result := 0;
end
else begin
CloseHandle(CommHandle);
Result := -1;
end;
end;
function CloseCom(): integer;
begin
if CommHandle <> INVALID_HANDLE_VALUE then begin
CloseHandle(CommHandle);
CommHandle := INVALID_HANDLE_VALUE;
end;
Result := 0;
end;
//以下是实际的读取动作,读取线程函数
function ReadProcess(Timeout: integer): string;
var
CommState: ComStat;
dwNumberOfBytesRead: Dword;
ErrorFlag: Dword;
InputBuffer: Pointer; //array[0..1024] of Char; 此处改用指针的方式,便于后续16制显示 jtp
lpszPostedBytes: LPSTR;
_Buffer: TBYTES;
_ByteStr: AnsiString;
tmpStr: string;
temp: string;
j, i: integer;
EndTime: Dword;
begin
if CommHandle = INVALID_HANDLE_VALUE then begin
DeviceLastError := E_DEVICE_BEFORE_INIT;
Result := '';
Exit;
end;
EndTime := GetTickCount + Timeout;
while GetTickCount < EndTime do begin
Application.ProcessMessages;
ClearCommError(CommHandle, ErrorFlag, @CommState);
//if CommState.cbInQue > 0 then break;
end;
if not ClearCommError(CommHandle, ErrorFlag, @CommState) then begin
DeviceLastError := E_DEVICE_BEFORE_INIT;
Result := '';
PurgeComm(CommHandle, Purge_Rxabort or Purge_Rxclear);
Exit;
end;
if CommState.cbInQue > 0 then begin
GetMem(InputBuffer, CommState.cbInQue + 1);
if (not ReadFile(CommHandle, InputBuffer^, CommState.cbInQue,
dwNumberOfBytesRead, @ReadOs)) then begin
ErrorFlag := GetLastError();
if (ErrorFlag <> 0) and (ErrorFlag <> ERROR_IO_PENDING) then begin
DeviceLastError := E_PORT_INIT;
Result := '';
Receive := FALSE;
CloseHandle(ReadOs.hEvent);
CloseHandle(PostEvent);
CloseHandle(CommHandle);
Exit;
end
else begin
WaitForSingleObject(CommHandle, INFINITE); // 等待操作完成
GetOverLappedResult(CommHandle, ReadOs, dwNumberOfBytesRead, FALSE);
end;
end;
if dwNumberOfBytesRead > 0 then begin
ReadOs.Offset := ReadOs.Offset + dwNumberOfBytesRead;
ReceiveData := ReadOs.Offset;
// 处理接收的数据
_Buffer := InputBuffer;
_ByteStr := '';
j := 0;
for i := 1 to dwNumberOfBytesRead do begin
_ByteStr := _ByteStr + IntToHex(_Buffer^[i], 2);
ResponseData[j] := _Buffer^[i];
inc(j);
end;
end
else begin
DeviceLastError := E_TIMEOUT;
Result := '';
end;
FreeMem(InputBuffer);
end;
Result := _ByteStr;
end;
function SendData(strOrder: string): Boolean;
var
strOrderByte: array[0..128] of Byte;
lrc: LongWord;
Str: TBlocka;
i: integer;
writeoverlapped: Toverlapped;
ByteToWrite, BytesWritten, AllBytesWritten: Dword;
ErrorCode, ErrorFlag: Dword;
CommStat: ComStat;
begin
//Str := myHextoStr(strOrder);
//Str := strOrder;
Str := HexTobytearray(strOrder);
Result := True;
if CommHandle = INVALID_HANDLE_VALUE then begin
Result := FALSE;
DeviceLastError := E_DEVICE_BEFORE_INIT;
Exit;
end;
ByteToWrite := Length(strOrder) div 2;
try
//初始化一步读写结构
FillChar(writeoverlapped, SizeOf(writeoverlapped), 0);
//避免贡献资源冲突
writeoverlapped.hEvent := CreateEvent(nil, True, FALSE, nil);
//发送数据
if not WriteFile(CommHandle, Str, ByteToWrite, BytesWritten, @writeoverlapped) then begin
ErrorCode := GetLastError;
if ErrorCode <> 0 then begin
if ErrorCode = ERROR_IO_PENDING then begin
//StatusBar1.SimpleText := '端口忙,正在等待...';
while not GetOverLappedResult(CommHandle, writeoverlapped, BytesWritten, True) do begin
ErrorCode := GetLastError;
if ErrorCode = ERROR_IO_PENDING then
continue
else begin
ClearCommError(CommHandle, ErrorFlag, @CommStat);
DeviceLastError := E_VOID_ACTION;
Result := FALSE;
CloseHandle(writeoverlapped.hEvent);
CloseHandle(CommHandle);
Exit;
end;
end;
AllBytesWritten := AllBytesWritten + BytesWritten;
end
else begin
ClearCommError(CommHandle, ErrorFlag, @CommStat);
DeviceLastError := E_VOID_ACTION;
Result := FALSE;
CloseHandle(writeoverlapped.hEvent);
Receive := FALSE;
CloseHandle(CommHandle);
CloseHandle(PostEvent);
Exit;
end;
end;
end;
finally
CloseHandle(writeoverlapped.hEvent);
end;
end;
procedure Delay(waittime: integer);
var
EndTime: Dword;
begin
EndTime := GetTickCount + waittime;
while GetTickCount < EndTime do Application.ProcessMessages;
end;
function InsertLogfile(log_str: string): Boolean;
var
F: TextFile;
MyStr: string;
sss: string;
FileHandle: integer;
begin
try
sss := FormatDateTime('yyyy-mm-dd', Now) + '.txt';
if not FileExists(sss) then begin
FileHandle := FileCreate(sss);
FileClose(FileHandle);
end;
AssignFile(F, sss);
Append(F);
MyStr := FormatDateTime('yyyy-mm-dd hh:mm:ss', Now) + chr(9) + log_str;
Writeln(F, MyStr);
Flush(F);
CloseFile(F);
except
Result := FALSE;
end;
Result := True;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -