⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unit1.~pas

📁 求是科技出版的《Delphi串口通信工程开发实例导航》所有的源代码。是一本很好的书。拿出来与大家共享。
💻 ~PAS
📖 第 1 页 / 共 3 页
字号:
  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 + -