标签:
PC工具: IC util
手持设备:Dynasty ARM嵌入式设备
通信设备: TTL-USB串口传输器
问题:IC_Util向dynasty传输所需的配置文件,传输速度慢。
传输10k大小的文件
顺利时耗时大约10s,文件分块传输,1k/block or 2k/block。
波特率115200
传输时对于接受和发送的函数需要做适当的延时处理,同时需要对传输时的block大小做一定规定,BLOCK为2k时传输正常,BLOCK为1k时IC_Util将会不时的出现接收超时的问题。
Delphi串口模块使用的是TCOM模块
以下为TCOM模块的配置:
object DtmdComm: TDtmdComm
OldCreateOrder = False
OnCreate = DataModuleCreate
OnDestroy = DataModuleDestroy
Left = 415
Top = 275
Height = 225
Width = 314
object cmmMain: TComm
CommName = ‘COM1‘
BaudRate = 9600
ParityCheck = False
Outx_CtsFlow = False
Outx_DsrFlow = False
DtrControl = DtrDisable
DsrSensitivity = False
TxContinueOnXoff = True
Outx_XonXoffFlow = False
Inx_XonXoffFlow = False
ReplaceWhenParityError = False
IgnoreNullChar = False
RtsControl = RtsDisable
XonLimit = 500
XoffLimit = 500
ByteSize = _8
Parity = None
StopBits = _1
XonChar = #17
XoffChar = #19
ReplacedChar = #0
ReadIntervalTimeout = 500
ReadTotalTimeoutMultiplier = 0
ReadTotalTimeoutConstant = 0
WriteTotalTimeoutMultiplier = 0
WriteTotalTimeoutConstant = 0
OnReceiveData = cmmMainReceiveData
Left = 48
Top = 16
end
object tmrPack: TTimer
Tag = 20
Enabled = False
OnTimer = tmrPackTimer
Left = 136
Top = 56
end
end
接收函数的对应实现接口为cmmMainReceiveData()
以下为cmmMainReceiveData()的实现:
procedure TDtmdComm.cmmMainReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
tmpArray:array[1..8096] of Byte;
i,DataCount: Integer;
tmpRecvStr:string;
OneCommand:string;
begin
//Delay(100);
tmpRecvStr := ‘‘;
Move(Buffer^,PChar(@tmpArray)^,BufferLength);
for i:=1 to BufferLength do
tmpRecvStr:=tmpRecvStr+inttohex(tmpArray[i],2);
RecvPOSStr := RecvPOSStr +tmpRecvStr;
OutputMemo.Lines.Add(FormatDateTime(‘hh:nn:ss-zzz‘,now)+‘---->[Receive]:‘);
OutputMemo.Lines.Add(GetBinStrWithSpace(tmpRecvStr));
if Copy(RecvPOSStr,1,2) = ‘02‘ then
begin
CommandType := Copy(RecvPOSStr,3,2);
try
DataCount := StrToInt(‘$‘+Copy(RecvPOSStr,5,2))*256;
DataCount := DataCount +StrToInt(‘$‘+Copy(RecvPOSStr,7,2));
DataCount := DataCount * 2;
if Copy(RecvPOSStr,11+DataCount,2) <> ‘03‘ then //03开头的数据
begin
MoniterMemoAppend(FormatDateTime(‘yy-mm-dd hh:nn:ss‘,now)+‘---->Data format error,(02,03)。‘+Copy(RecvPOSStr,11+DataCount,2),0,0,0);
RecvPOSStr := ‘‘;
POSCommand := ‘‘;
Exit;
end;
if ((CommandType <> ‘40‘) and (CommandType <> ‘41‘) and
(CommandType <> ‘42‘) and (CommandType <> ‘43‘) and
(CommandType <> ‘44‘) and (CommandType <> ‘45‘) and
(CommandType <> ‘46‘) and (CommandType <> ‘47‘) and
(CommandType <> ‘48‘) and (CommandType <> ‘49‘) and
(CommandType <> ‘50‘) and (CommandType <> ‘51‘) and
(CommandType <> ‘52‘) and (CommandType <> ‘53‘) and
(CommandType <> ‘54‘) and (CommandType <> ‘55‘) and
(CommandType <> ‘60‘) and (CommandType <> ‘61‘) and
(CommandType <> ‘70‘) and (CommandType <> ‘71‘)) then
begin
RecvPOSStr := Copy(RecvPOSStr,9,DataCount);
if CommandType <> ‘03‘ then
begin
LogOutputMemoAppend(FormatDateTime(‘yy-mm-dd hh:nn:ss‘,now)+‘-------------------------------->[Transaction Log]:‘);
OperPackageMessage(RecvPOSStr,tmpRecvStr);
LogOutputMemoAppend(FormatDateTime(‘yy-mm-dd hh:nn:ss‘,now)+‘-------------------------------->[End Log]‘);
CommandType := IntToHex(StrToInt(‘$‘+Copy(CommandType,1,2)) + 1 ,2);
SendHostScript(CommandType);
end;
end
else
begin
OneCommand := Copy(RecvPOSStr,9,DataCount);
POSCommand := OneCommand;
RecvPOSStr := ‘‘;
if (CommandType = ‘46‘) then //请求输入密码
begin
SendStringByCom(CommandType,StrToHex(‘ACK‘));//响应ACK
ExecInputPin(OneCommand);
POSCommand := ‘‘;
end
else if (CommandType = ‘47‘) or (CommandType = ‘48‘)
or (CommandType = ‘49‘) or (CommandType = ‘50‘) then
begin
SendStringByCom(CommandType,StrToHex(‘ACK‘)); //响应ACK
tmpRecvStr := ‘‘;
OperSimulatorMessage(CommandType ,OneCommand, tmpRecvStr );
POSCommand := ‘‘;
end
else if (CommandType = ‘51‘) or (CommandType = ‘52‘)
or (CommandType = ‘60‘) or (CommandType = ‘61‘) then
begin
SendStringByCom(CommandType,StrToHex(‘ACK‘)); //响应ACK
tmpRecvStr := ‘‘;
OperSimulatorMessage(CommandType ,OneCommand, tmpRecvStr );
SendStringByCom(CommandType,tmpRecvStr);
POSCommand := ‘‘;
end
else if(CommandType = ‘70‘) then
begin
//START TEST
frmMain.ChangeLedColor(PosCommand);
//EMD TEST
end
else if(CommandType = ‘71‘) then
begin
//START TEST
frmMain.BeepSound(PosCommand);
//EMD TEST
end
end;
RecvPOSStr := ‘‘;
except
RecvPOSStr := ‘‘;
POSCommand := ‘‘;
MoniterMemoAppend(FormatDateTime(‘yy-mm-dd hh:nn:ss‘,now)+‘---->Data length is not hex‘,0,0,0);
Exit;
end;
end
else if (Copy(RecvPOSStr,1,2) = ‘0D‘) or (Copy(RecvPOSStr,1,2) = ‘0A‘) then
begin
MoniterMemoAppend(FormatDateTime(‘yy-mm-dd hh:nn:ss‘,now)+‘---->Log:‘+HexToStr(RecvPOSStr),0,0,0);
RecvPOSStr := ‘‘;
POSCommand := ‘‘;
end
else
begin
MoniterMemoAppend(FormatDateTime(‘yy-mm-dd hh:nn:ss‘,now)+‘---->Log:‘+HexToStr(RecvPOSStr),0,0,0);
RecvPOSStr := ‘‘;
POSCommand := ‘‘;
end;
end;
procedure TDtmdComm.DataModuleCreate(Sender: TObject);
begin
bOperPackBusy := False;
PosMaxCommLen := 2000;
RecvPOSStr := ‘‘;
end;
以下为文件下载中判断Poscommand是否有数据的函数
function TDtmdComm.ReceACKByComm(SendCommandType:string;TimeOut:Integer): Boolean;
var
RecvStr:string;
begin
Result := False;
tmrPack.Tag := TimeOut;
tmrPack.Enabled := True;
while True do
begin
if POSCommand <> ‘‘ then
begin
RecvStr := POSCommand;
tmrPack.Enabled := False;
Break;
end;
if not tmrPack.Enabled then //连接超时
begin
Exit;
end;
if not bComOpened then
begin
tmrPack.Enabled := False;
Exit;
end;
Application.ProcessMessages;
end;
if SendCommandType <> CommandType then Exit;
UnpackTLV(RecvStr);
FindTLV($0,RecvStr);
if RecvStr <> ‘ACK‘ then
begin
Exit;
end
else
begin
Result := True;
end;
end;
超时间为5s
文件传输函数将会对Poscommand的数据进行判断,传输过程中经常出现Poscommand数据为NULL,也就是没有成功获取从ARM设备端获取到数据从而超时的情况。
经过测试发现,在发送和接收之间增加适当的延时或者修改配置文件中ReadIntervalTimeout值对于传输超时现象有很大的改善。(最上面配置文件中红字部分)
1.当将ReadIntervalTimeout从原始的100ms增加为500ms时,无论对于Block为1k或Block为2k的传输单位都不会出现PC接收超时的情况。
2.在PC向ARM设备发送Block数据之间增加500ms的延时,也可以有效的改善PC接收超时的情况。
for j := 0 to 3 do
begin
Delay(500);//ms
SendStringByCom(‘41‘,SendStr);//发送连接相应
if not ReceACKByComm(‘41‘,5) then//5s超时等待接收数据
begin
MoniterMemoAppend(FormatDateTime(‘yy-mm-dd hh:nn:ss‘,now)+‘------>Download file error[‘+IntToStr(j+1)+‘]‘,0,0,0);
Continue;
end;
Break;
end;
但当Delay的时间少于500ms时,每次传输超时现象出现概率大大增加。
注:以上两种方法采用任意一种均可达到消除超时的效果。
================================ 我是分割线 ======================================
分析为什么这两种操作可以改善超时?
尤其是为什么增加ReadIntervalTimeout参数可以改善超时现象?
因为根据ReadInervalTimeout的定义:
来确定所接收到的数据是否属子同一帧数据,其默认值是100ms,也就是说,只要任何两个字节到达的时间间隔小于1OOms,都被认为是属于同一帧数据。
想了半天脑袋都快炸了!!还是没有明白~哪天脑洞一开解决了这个问题再补上,先挖个坑...
就这样,祝您身体健康~
Delphi TCOM控件串口通信调试寻找文件传输速度慢的原因
标签:
原文地址:http://www.cnblogs.com/simon-code/p/5661102.html