📄 unit1.~pas
字号:
can.Pen.Color := clBlack;
can.Pen.Style := psSolid;
can.MoveTo(0,h div 2);
can.LineTo(wid,h div 2);
can.MoveTo(wid div 2,0);
can.LineTo(wid div 2, h);
can.Font.Height := 10;
can.Font.Name := 'Arial';
{
绘制坐标的最大刻度值
}
can.TextOut(0,h div 2 +1,IntToStr(-1*round(maxV)));
can.TextOut(wid-can.TextWidth(IntToStr(round(maxV))),
h div 2 +1,IntToStr(round(maxV)));
can.TextOut(wid div 2+3,
h-can.TextHeight(IntToStr(-1*round(maxV))),IntToStr(-1*round(maxV)));
can.TextOut(wid div 2+1,0,IntToStr(round(maxV)));
{
绘制坐标的刻度,每个座标轴上有21条刻线
}
pstep := wid / 20;
for i:=0 to 21 do
begin
can.MoveTo(round(pstep*i),h div 2 - 2);
can.LineTo(round(pstep*i),h div 2);
can.MoveTo(wid div 2,round(pstep*i));
can.LineTo(wid div 2 + 2, round(pstep*i));
end;
{
绘制载入的轨迹,颜色为红色
}
if posLengthLoad > 0 then
begin
can.Pen.Color := clRed;
ratio := h / maxV / 2;
x := round(posXArrayLoad[0]*ratio + wid/2);
y := round(h/2-posYArrayLoad[0]*ratio);
can.MoveTo(x,y);
can.Pixels[x,y] := clRed;
for i:= 1 to posLengthLoad-1 do
begin
x := round(posXArrayLoad[i]*ratio + wid/2);
y := round(h/2 - posYArrayLoad[i]*ratio);
can.LineTo(x,y);
end;
end;
{
绘制当前试验的轨迹,颜色为蓝色
}
if posLength > 0 then
begin
can.Pen.Color := clBlue;
ratio := h / maxV / 2;
x := round(posXArray[0]*ratio + wid/2);
y := round(h/2-posYArray[0]*ratio);
can.MoveTo(x,y);
can.Pixels[x,y] := $0000ff;
for i:= 1 to posLength-1 do
begin
x := round(posXArray[i]*ratio + wid/2);
y := round(h/2 - posYArray[i]*ratio);
can.LineTo(x,y);
end;
can.RoundRect(x,y,x+6,y+6,x-6,y-6);//在模型飞机的当前位置绘制一个较小的圆
end;
can.Free; //释放 TMetaFileCanvas对象,把绘制的图像传递给gpsMeta
Form1.ImgTrace.Picture.Assign(gpsMeta);//显示轨迹图像
end;
/////////////////////////////////////////////////////////////////
{
从用户界面的读取发送的数据和指令,保存到线程的内部变量或是全局变量中
}
procedure TSerialOutThread.GetData ;
begin
DataOrCode:=(Form1.rdgrpDataCode.ItemIndex=1);
Seriallength:=Length(Form1.RchdtSerialOut.Text);
SerialOutput:=Form1.RchdtSerialOut.Text;
CodeOutStr[1]:=Form1.dtCode1.Text ;
CodeOutStr[2]:=Form1.dtCode2.Text;
CodeOutStr[3]:=Form1.dtCode3.Text;
CodeOutStr[4]:=Form1.dtCode4.Text;
end;
/////////////////////////////////////////////////////////////////
{
用户在编辑栏中输入格式为01_12_34_56_...
首字符不能空格,必须把高位的0补上,
即确定了输出16进制的数据0x01,0x12,0x34,0x56,...
}
procedure TSerialOutThread.PackData;
var
tmpStr:String;
MaxCount,Count,tmpInt,i:Integer;
begin
Count:=1; //动态Byte类型矩阵tmpVar的j记数变量
MaxCount:=1;//动态Byte类型矩阵tmpVar的大小
CheckOk:=True;
{使用互斥实现线程的同步,主要是为了防止数据流顺序的发生错误}
if WaitForSingleObject(hMutex2,InFinite) =WAIT_OBJECT_0 then
begin
if Seriallength >0 then
begin
i:=1;
tmpVar:=VarArrayCreate([1,1],varByte);
while(i<Seriallength) do
begin
tmpStr:=Copy(SerialOutput,i,2);
tmpStr:=LowerCase(tmpStr);
tmpInt:=HexToInt(tmpStr);
if tmpInt<>-1 then
begin
if Count=(MaxCount+1) then
begin
MaxCount:=MaxCount+1;
VarArrayRedim(tmpVar,MaxCount);
end;
tmpVar[Count]:=tmpInt;
Count:=Count+1;
end else
begin
CheckOk:=False;//数据格式有问题,无法解读
break; //停止while循环
end;
i:=i+3;//跳过3个字符
end;
end;
end;
ReleaseMutex(hMutex2);
end;
/////////////////////////////////////////////////////////////////
{
需要按照协议打包数据,发送几个0x55,然后是0x24,指令代码,结束符号0x0d,0x0a
}
procedure TSerialOutThread.PackCode;
var
tmpInt,i:Integer;
begin
tmpVar:=VarArrayCreate([1,22],varByte);
CheckOk:=True;
if WaitForSingleObject(hMutex2,InFinite) =WAIT_OBJECT_0 then
begin
for i:=1 to 15 do
begin
tmpVar[i]:=85;//0x55
end;
tmpVar[10]:=12;
tmpVar[16]:=36; //0x24=36
for i:=1 to 4 do
begin
tmpInt:=HexToInt(CodeOutStr[i]);
if tmpInt<>-1 then
tmpVar[16+i]:= tmpInt
else
begin
CheckOk:=False;
Break;
end;
end;
tmpVar[21]:=13;//0x0d
tmpVar[22]:=10;//0x0a
End;
ReleaseMutex(hMutex2);
end;
/////////////////////////////////////////////////////////////////
{
由于有调试目的,如果要求发送字符格式的数据,就直接发送用户输入的字符串
其他情况下,都是发送打包好的数据矩阵
}
procedure TSerialOutThread.PostData ;
begin
if CheckOk=True then
begin
// Form1.MSCommOut.Output:=tmpVar; //以16进制发送数据或指令
Form1.MSCommIn.Output:=tmpVar; //以16进制发送数据或指令
end
else
ShowMessage('数据格式有问题,发送失败'); //一旦发现有任何错误,都不会发送数据
Form1.btSendOut.Enabled:=True; //串口发送线程即将结束,运行新的发送
end;
/////////////////////////////////////////////////////////////////
{
调用其它函数实现发送串口数据的功能。
注意函数GetData还没有实现线程的互斥,
目的是把发送的数据保存在各个线程中
}
procedure TSerialOutThread.Execute;
begin
FreeOnTerminate:=True; //线程执行完后自动释放资源
// Synchronize(GetData);
GetData;
if DataOrCode=True then
PackData //发送数据
else
PackCode;//发送指令
{
提交给串口控件实现数据的发送
尝试调用Synchronize
}
// Synchronize(PostData);
PostData;
end;
/////////////////////////////////////////////////////////////////
{
保存串口数据,便于后面进行处理
}
procedure TSerialInThread.GetData ;
begin
Seriallength:=Form1.MSCommIn.InBufferCount;
if ReceiveCharFlag then //以文本格式接受串口数据
begin
SerialStr:=Form1.MSCommIn.Input;
end
else
begin
SerialInput:=Form1.MSCommIn.Input; //以数据格式接受串口数据
SerialStr:='';
end;
end;
/////////////////////////////////////////////////////////////////
{
根据下传的数据转换为适合于显示的字符串形式
}
procedure TSerialInThread.TransToStr ;
var
i:Integer;
tmpSInt,tmpSInt1:SmallInt;
tmpDbl:double;
begin
if ADNewDataFlag =True then
begin
ADDataDblArray[0]:=0.182*(5.0/4095.0)*((15 and ADDataArray[0])*256+ADDataArray[1]-(15 and ADDataArrayMean[0])*256-ADDataArrayMean[1]);
ADStrArray[0]:=FloatToStrF(ADDataDblArray[0],ffFixed,4,3);//陀螺X
ADDataDblArray[1]:=0.182*(5.0/4095.0)*((15 and ADDataArray[2])*256+ADDataArray[3]-(15 and ADDataArrayMean[2])*256-ADDataArrayMean[3]);
ADStrArray[1]:=FloatToStrF(ADDataDblArray[1],ffFixed,4,3);//陀螺Y
ADDataDblArray[2]:=0.182*(5.0/4095.0)*((15 and ADDataArray[4])*256+ADDataArray[5]-(15 and ADDataArrayMean[4])*256-ADDataArrayMean[5]);
ADStrArray[2]:=FloatToStrF(ADDataDblArray[2],ffFixed,4,3);//陀螺Z
ADDataDblArray[3]:=(5.0/4095.0)*((15 and ADDataArray[6])*256+ADDataArray[7]-(15 and ADDataArrayMean[6])*256-ADDataArrayMean[7]);
ADStrArray[3]:=FloatToStrF(ADDataDblArray[3],ffFixed,4,3);//加速度0
ADDataDblArray[4]:=(5.0/4095.0)*((15 and ADDataArray[8])*256+ADDataArray[9]-(15 and ADDataArrayMean[8])*256-ADDataArrayMean[9]);
ADStrArray[4]:=FloatToStrF(ADDataDblArray[4],ffFixed,4,3);//加速度1
ADDataDblArray[5]:=(5.0/4095.0)*((15 and ADDataArray[10])*256+ADDataArray[11]-(15 and ADDataArrayMean[10])*256-ADDataArrayMean[11])/0.046;
ADStrArray[5]:=FloatToStrF(ADDataDblArray[5],ffFixed,4,3);//高度计
ADDataDblArray[6]:=(5.0/4095.0)*((15 and ADDataArray[12])*256+ADDataArray[13]-(15 and ADDataArrayMean[12])*256-ADDataArrayMean[13]);
ADStrArray[6]:=FloatToStrF(ADDataDblArray[6],ffFixed,4,3);//空速计
ADDataDblArray[7]:=0.00244*((15 and ADDataArray[14])*256+ADDataArray[15]);
ADStrArray[7]:=FloatToStrF(ADDataDblArray[7],ffFixed,4,3);//系统电压
end;
if GpsNewDataFlag =True then
begin
GpsStrArray[0]:=IntToStr(256*GpsDataArray[0]+GpsDataArray[1]);//是否定位
GpsStrArray[1]:=IntToStr(GpsDataArray[3])+':'
+IntToStr(GpsDataArray[4])+':'+IntToStr(GpsDataArray[5]);//时间
tmpSInt:=GpsDataArray[6]*256+GpsDataArray[7];
GpsStrArray[2]:=IntToStr(tmpSInt); //速度,有符号16进制整数
tmpSInt:=GpsDataArray[8]*256+GpsDataArray[9];
GpsStrArray[3]:=IntToStr(tmpSInt); //方位 ,有符号16进制整数
tmpDbl:=0.1*(GpsDataArray[10]*256+GpsDataArray[11]);//高度,无符号16进制整数
GpsStrArray[4]:=FloatToStrF(tmpDbl,ffFixed,4,1);;
tmpSInt:=GpsDataArray[12]*256+GpsDataArray[13];//动向 x,有符号16进制整数
tmpSInt1:=GpsDataArray[14]*256+GpsDataArray[15];//北向 y,有符号16进制整数
GpsStrArray[5]:=IntToStr(tmpSInt);
GpsStrArray[6]:=IntToStr(tmpSInt1);
{
由于传输系统总会有一定的吴码率,那么为了避免轨迹图出现问题,例如坐标范围过大
需要除去粗大误差,考虑到模型飞机的飞行速度不会超过10m/s,考虑到数子传输系统
的下传速度,设定如果位置变化超过20m就去掉。
}
if (abs(tmpSInt-posXArray[posLength-1])<20) and (abs(tmpSInt1-posYArray[posLength-1])<20) then
begin
posXArray[posLength] := tmpSInt;
posYArray[posLength] := tmpSInt1;
inc(posLength);
DrawAxis;
if posLength = Length(posXArray) then
begin
SetLength(posXArray,posLength+1000);
SetLength(posYArray,posLength+1000);
end;
end;
CodeInStr[0]:=LowerCase(IntToHex(GpsDataArray[16],2));
CodeInStr[1]:=LowerCase(IntToHex(GpsDataArray[17],2));
CodeInStr[2]:=LowerCase(IntToHex(GpsDataArray[18],2));
CodeInStr[3]:=LowerCase(IntToHex(GpsDataArray[19],2));
end;
end;
/////////////////////////////////////////////////////////////////
{
显示数据
}
procedure TSerialInThread.PostData ;
var
tmpDbl:double;
i:integer;
begin
DownStr:=DownStr+SerialStr; //保存串口的数据到全局变量中
// Form1.RchdtSerialIn.Text:=SerialStr; //文本只是显示最新的数据
Form1.RchdtSerialIn.Text:=Form1.RchdtSerialIn.Text+chr(13)+char(10)+SerialStr;//显示下传的所有数据
{
如果数据量比较大,执行完上面的代码后,控件总是会调整后显示最初的文本。
为了将最新的数据显示给用户,这里调用了控件的Perform函数,使得控件显
示当前插入符所在的位置,而事先设置插入符的位置为上一次接受文本的末尾。
}
if Seriallength>0 then
begin
Form1.RchdtSerialIn.SelStart := Length(Form1.RchdtSerialIn.Text)-Seriallength;
Form1.RchdtSerialIn.Perform(EM_SCROLLCARET, 0, 0);
end;
if ADNewDataFlag =True then//显示新的传感器数据包
begin
ADNewDataFlag:=False;
Form1.lbShowAd0.Caption:=ADStrArray[0];
Form1.lbShowAd1.Caption:=ADStrArray[1];
Form1.lbShowAd2.Caption:=ADStrArray[2];
Form1.lbShowAd3.Caption:=ADStrArray[3];
Form1.lbShowAd4.Caption:=ADStrArray[4];
Form1.lbShowAd5.Caption:=ADStrArray[5];
Form1.lbShowAd6.Caption:=ADStrArray[6];
Form1.lbShowAd7.Caption:=ADStrArray[7];
Form1.srsGyroX .AddY(ADDataDblArray[0]);
Form1.srsGyroY .AddY(ADDataDblArray[1]);
Form1.srsGyroZ .AddY(ADDataDblArray[2]);
Form1.srsAcc1 .AddY(ADDataDblArray[3]);
Form1.srsAcc2 .AddY(ADDataDblArray[4]);
Form1.srsHeight .AddY(ADDataDblArray[5]);
end;
if GpsNewDataFlag =True then //显示新的GPS数据包
begin
GpsNewDataFlag:=False;
Form1.lbShowGps0.Caption:=GpsStrArray[0];
Form1.lbShowGps1.Caption:=GpsStrArray[1];
Form1.lbShowGps2.Caption:=GpsStrArray[2];
Form1.lbShowGps3.Caption:=GpsStrArray[3];
Form1.lbShowGps4.Caption:=GpsStrArray[4];
Form1.lbShowGps5.Caption:=GpsStrArray[5];
Form1.lbShowGps6.Caption:=GpsStrArray[6];
Form1.lbCode1.Caption:=CodeInStr[0]; //显示下传的4个指令代码
Form1.lbCode2.Caption:=CodeInStr[1];
Form1.lbCode3.Caption:=CodeInStr[2];
Form1.lbCode4.Caption:=CodeInStr[3];
end;
if ParaNewDataFlag then //显示新的参数数据包
begin
ParaNewDataFlag:=False;
Form1.lbShowPara0.Caption:=IntToStr(ParaDataArray[0]);
Form1.lbShowPara1.Caption:=IntToStr(ParaDataArray[1]);
Form1.lbShowPara2.Caption:=IntToStr(ParaDataArray[2]);
Form1.lbShowPara3.Caption:=IntToStr(ParaDataArray[3]);
Form1.lbShowPara4.Caption:=IntToStr(ParaDataArray[4]);
Form1.lbShowPara5.Caption:=IntToStr(ParaDataArray[5]);
Form1.lbShowPara6.Caption:=IntToStr(ParaDataArray[6]);
Form1.lbShowPara7.Caption:=IntToStr(ParaDataArray[7]);
Form1.lbShowModel.Caption:=IntToHex(ParaDataArray[8],2);
end;
end;
/////////////////////////////////////////////////////////////////
{
这是执行数据接受,截取数据包的过程。调用其它函数获取数据、转换格式和进行显示
}
procedure TSerialInThread.Execute;
var
tmpInt,i:Integer;
curStr:String;
begin
FreeOnTerminate:=True; //线程执行完后自动释放资源
// Synchronize(GetData);
GetData; //获取串口数据
if not ReceiveCharFlag then
begin
if WaitForSingleObject(hMutex,InFinite) =WAIT_OBJECT_0 then
begin
if Seriallength >0 then
begin
for i:= 0 to Seriallength-1 do //逐一处理串口数据
begin
tmpInt:=SerialInput[i]; //获取当前一个数据
curStr:=LowerCase(IntToHex(tmpInt,2));//转换为16进制的字符
SerialStr :=SerialStr + curStr+' '; //便于显示和保存
{
发现参数数据包
}
if (curStr='fe') and (not ADDataFlag)
and (not GpsDataFlag) and (not ParaDataFlag)then
begin
ParaDataFlag:=True;
ParaDataCount:=0;
end
{
发现GPS数据包
}
else if (curStr='fc') and (not ADDataFlag)
and (not GpsDataFlag)and (not ParaDataFlag) then
begin
GpsDataFlag:=True;
GpsDataCount:=0;
GpsStr:=GpsStr+chr(13) + chr(10);//保存数据
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -