0
我正在使用Delphi XE2,并尝试通过串口与某些设备进行通信。沟通应该直截了当,但我有一些问题。设备通信协议如下: I(主)发送以“:”开始并以CRLF结束的帧。 设备(从站)以相同的格式发送响应(以“:”开头并以CRLF结尾)。通过串口(COM)进行非重叠通信的正确方法
我正在使用WinAPI和非重叠IO。我遇到的问题是,我经常收到#0字符作为设备的响应。我相信问题出在我身上,因为我可以使用设备提供商应用程序,并且我可以看到沟通顺利。
下面是如何设置我的COM端口:
Result := False;
FFileHandle := CreateFile('COM3', GENERIC_READ OR GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0);
if FFileHandle = INVALID_HANDLE_VALUE then
Exit;
if not GetCommState(FFileHandle, DCB) then
Exit;
DCB.BaudRate := ASettings.BaudRate;
DCB.Flags := 1 OR // BINARY
(DTR_CONTROL_ENABLE shl 4) OR
(RTS_CONTROL_ENABLE shl 12);
DCB.XonLim := 100; // transmit XON threshold
DCB.XoffLim := 100; // transmit XOFF threshold
DCB.ByteSize := 8; // number of bits/byte, 4-8
DCB.Parity := 0; // 0-4=no,odd,even,mark,space
DCB.StopBits := ONESTOPBIT; // 0,1,2 = 1, 1.5, 2
DCB.XonChar := #1; // Tx and Rx XON character
DCB.XoffChar := #2; // Tx and Rx XOFF character
DCB.ErrorChar := #$FF; // error replacement character
DCB.EofChar := #$0A; // end of input character
DCB.EvtChar := #$0A; // received event character
if not SetCommState(FFileHandle, DCB) then
Exit;
if not SetCommMask(FFileHandle, EV_RXCHAR OR EV_TXEMPTY OR EV_RXFLAG) then
Exit;
Timeouts.ReadIntervalTimeout := 1200;
Timeouts.ReadTotalTimeoutMultiplier := 1;
Timeouts.ReadTotalTimeoutConstant := 1200;
Timeouts.WriteTotalTimeoutMultiplier := 0;
Timeouts.WriteTotalTimeoutConstant := 0;
if not SetCommTimeouts(FFileHandle, Timeouts) then
Exit;
if not PurgeComm(FFileHandle, PURGE_TXABORT OR PURGE_RXABORT OR PURGE_TXCLEAR OR PURGE_RXCLEAR) then
Exit;
if not ClearCommError(FFileHandle, Errors, @ComStat) then
Exit;
if not SetupComm(FFileHandle, 1024, 1024) then
Exit;
Result := True;
这里是如何我不写:
function TCOMPortWrapper.Write(const AFrame: AnsiString): TComPortWriteRes;
var
Written: Cardinal;
Err: Cardinal;
Stat: TComStat;
Mask: Cardinal;
begin
Result := CPW_ERROR;
ClearCommError(FFileHandle, Err, @Stat);
if not IsOpened then
Exit;
if not WriteFile(FFileHandle, AFrame[1], Length(AFrame), Written, nil) then
Exit;
Mask := EV_TXEMPTY;
if not WaitCommEvent(FFileHandle, Mask, nil) then
Exit;
ClearCommError(FFileHandle, Err, @Stat);
Result := CPW_OK;
end;
最后这里是我如何读取:
function TCOMPortWrapper.Read(out Frame: AnsiString): TComPortReadRes;
var
S: AnsiString;
BytesRead: Cardinal;
Mask: Cardinal;
begin
Result := CPR_ERROR;
if not IsOpened then
Exit;
SetLength(S, 4096);
Mask := EV_RXFLAG;
if not WaitCommEvent(FFileHandle, Mask, nil) then
Exit;
if not ReadFile(FFileHandle, S[1], Length(S), BytesRead, nil) then
Exit;
SetLength(S, BytesRead);
Frame := S;
Result := CPR_OK;
end;
正如我上面提到的,在读取而不是获取实际框架,我得到#0字符串。我想,我的错误可能是WaitCommEvent API调用,因为我对串行通信非常陌生。
感谢您的帮助!
虽然这不会回答你的问题,有一些很好的水果盘组件在那里。过去我多次使用TPAPRO。这是当时的商业组件,但现在它已经作为开源发布:http://tpapro.sourceforge.net/ – whosrdaddy