Delphi Berlin 10.1下CPort Lib接收数据包时响应拆分问题求助
解决USB设备响应被拆分的问题
看起来你的问题核心是ComDataPacket的OnPacket事件会在每次收到部分数据时就触发,而非等待完整响应,导致长响应被拆分成多行输出。既然无法依赖固定的Start/StopString,我们需要自己实现数据缓存和完整性判断逻辑。
解决方案思路
- 用全局缓存变量存储收到的原始数据,每次OnPacket触发时先把新数据追加到缓存中。
- 根据设备通信协议,判断缓存中的数据是否构成完整响应(比如固定长度匹配、校验和验证等)。
- 确认收到完整响应后,将其转换为HEX格式输出,并清空缓存准备下一次请求。
修改后的代码示例
首先在你的Form类中添加缓存和预期响应长度变量,用于对应不同命令的响应规则:
type TForm1 = class(TForm) ComDataPacket1: TComDataPacket; Memo1: TMemo; procedure ComDataPacket1Packet(Sender: TObject; const Str: string); private FBuffer: string; // 缓存收到的原始数据 FExpectedResponseLen: Integer; // 当前命令对应的预期响应长度 public { Public declarations } end;
然后修改发送命令的逻辑,比如发送getNodeStatus,03或getId,03时:
// 发送getNodeStatus,03时,设置预期响应长度为53(对应你提供的完整响应字节数) FExpectedResponseLen := 53; ComDataPacket1.Send('getNodeStatus,03'); // 发送getId,03时,设置预期响应长度为4 FExpectedResponseLen := 4; ComDataPacket1.Send('getId,03');
最后更新OnPacket事件处理代码:
procedure TForm1.ComDataPacket1Packet(Sender: TObject; const Str: string); var I: Integer; str2: String; begin // 将新收到的数据追加到缓存 FBuffer := FBuffer + Str; // 判断是否达到预期响应长度(完整响应) if Length(FBuffer) = FExpectedResponseLen then begin // 转换完整数据为HEX格式 str2 := ''; for I := 1 to Length(FBuffer) do begin str2 := str2 + IntToHex(Byte(FBuffer[I]), 2) + ' '; end; // 输出完整响应 Memo1.Lines.Add('(HEX) > ' + str2); Memo1.Lines.Add(' '); // 清空缓存,准备下一次请求 FBuffer := ''; end; end;
关键注意事项
- 如果设备响应不是固定长度,而是通过校验和/CRC验证完整性,你需要替换长度判断逻辑。比如假设最后一个字节是前面所有字节的异或校验:
var CheckSum: Byte; I: Integer; begin CheckSum := 0; for I := 1 to Length(FBuffer) - 1 do CheckSum := CheckSum xor Byte(FBuffer[I]); if CheckSum = Byte(FBuffer[Length(FBuffer)]) then begin // 处理完整响应的逻辑... end; end; - 务必确保
FExpectedResponseLen的设置和发送的命令严格对应,若有更多命令,可维护一个TDictionary<string, Integer>存储命令与响应长度的映射,提升扩展性。
内容的提问来源于stack exchange,提问作者Martin Ocando Corleone
相关产品推荐
相关产品推荐

