问题解决! 用TApdComPort与TApdDataPacket相结合,控制数据接收,并保证一帧数据的完整性。APro控件的应用,在《DELPHI串口及语音传真高级编程》一书之第三章有详细介绍,并有大量示例程序。此书电子版及附书源码在网上可以下载得到。
现把主要处理代码贴出,可供参考:
procedure TForm_Main.CommInitialize;//串口初始化
type
ComSet = record
ComPort : SmallInt;
BaudRate : Integer;
VerifyBit : TParity;
DataBit : SmallInt;
StopBit : SmallInt;
end;
var
iniFile : TIniFile;
aStr : string;
aInt : Word;
aComSet : ComSet;
begin
//读取串口参数设置信息,进行串口初始设置
iniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'SysParams.ini');
try
aStr := iniFile.ReadString('Machine','MachineModel','HJK-120');
ComBox_Machine.ItemIndex := ComBox_Machine.Items.IndexOf(aStr);
aStr := iniFile.ReadString('COMParam','COMPort','COM1');
if DM.GetComList(ComBox_ComPort.Items) then
ComBox_ComPort.ItemIndex := ComBox_ComPort.Items.IndexOf(aStr);
aStr := Copy(aStr,4,Length(astr) - 3);
aComSet.ComPort := StrToInt(aStr);//值为 1、2时分别设置coml、com2
aInt := iniFile.ReadInteger('COMParam','BaudRate',2400);
Combox_Baud.ItemIndex := Combox_Baud.Items.IndexOf(IntToStr(aInt));
aComSet.BaudRate := aInt;
aInt := iniFile.ReadInteger('COMParam','VerifyBit',NOPARITY);
ComBox_CheckBit.ItemIndex := ComBox_CheckBit.Items.IndexOf(IntToStr(aInt));
case aInt of
NOPARITY : aComSet.VerifyBit := pNone;
ODDPARITY : aComSet.VerifyBit := pOdd;
EVENPARITY : aComSet.VerifyBit := pEven;
MARKPARITY : aComSet.VerifyBit := pMark;
else
aComSet.VerifyBit := pSpace;
end;
aInt := iniFile.ReadInteger('COMParam','DataBit',8);
ComBox_DataBit.ItemIndex := ComBox_DataBit.Items.IndexOf(IntToStr(aInt));
aComSet.DataBit := aInt;
aInt := iniFile.ReadInteger('COMParam','StopBit',2);
ComBox_StopBit.ItemIndex := ComBox_StopBit.Items.IndexOf(IntToStr(aInt));
aComSet.StopBit := aInt;
try
ApdComPort.Open := False;
ApdComPort.ComNumber := aComSet.ComPort;
ApdComPort.Baud := aComSet.BaudRate;
ApdComPort.Parity := aComSet.VerifyBit;
ApdComPort.DataBits := aComSet.DataBit;
ApdComPort.StopBits := aComSet.StopBit;
ApdComPort.PromptForPort := False;//不显示选择串口对话框
With ApdDataPacketdo
begin
Enabled := False;
IgnoreCase := True;
if Trim(ComBox_Machine.Text) = 'HJK-120' then
//串口设备
begin
endCond := [ecString,ecPacketSize];
EndString := #13#10;//协议约定一帧的结束符
PacketSize := 84;
//协议约定一帧的字符数
StartCond := scString;
StartString := 'T';
//协议约定一帧的起始符
IncludeStrings := True;
end;
Enabled := True;
end;
ApdComPort.Open := True;
//打开串口
StatusBar1.Panels[0].Text := '串行口' + ComBox_ComPort.Text + '已打开,处于待命状态...';
except
on e : Exceptiondo
begin
StatusBar1.Panels[0].Text := '串行口' + ComBox_ComPort.Text + '打开失败! 错误信息:' + e.Message;
Application.MessageBox('打开串口错误,请检查串口参数设定或硬件连接!',提示',64);
end;
end;
finally
FreeAndNil(iniFile);
end;
end;
TApdDataPacket的OnStringPacket()事件,在这里获取接收到的完整一帧数据并解析处理:
procedure TForm_Main.ApdDataPacketStringPacket(Sender: TObject;
Data: String);
var
ReadStr,ErrorInfo : string;
begin
ReadStr := Data;
if ReadStr <> '' then
begin
StatusBar1.SimpleText := '串行口' + ComBox_ComPort.Text + '接收到的数据:' + Trim(ReadStr);
Memo1.Lines.Append(Trim(ReadStr));
//原数据,用Trim()去除末尾的回车换行符
if SameText(trim(ComBox_Machine.Text),'HJK-120') then
begin
if (Length(ReadStr) = 84) and (Copy(ReadStr,1,1) = 'T')
and (Copy(ReadStr,Length(ReadStr) - 1,2) = #13#10) then
//协议约定,正确的是84个字符,第一位是T,最后二位是回车换行符
begin
//通过串口接收正确以后, 就要在这里解析,并保存数据到数据库的表中去
if not WriteDataIntoDB(ReadStr,ErrorInfo) then
begin
//如果写入失败,则需要写错误日志
StatusBar1.SimpleText := ErrorInfo;
dm.WriteINIFile(FormatDateTime('yyyyMMDD',Now()),
'ErrorInfo',FormatDateTime('yyyy-MM-DD HH:mm:ss',Now()),ErrorInfo);;
end;
end;
end;
end;
end;
在此应该感谢盒子上的朋友:huangxw,是他给我指明了方向。