delphi 串口与多线程.docx
《delphi 串口与多线程.docx》由会员分享,可在线阅读,更多相关《delphi 串口与多线程.docx(81页珍藏版)》请在冰点文库上搜索。
delphi串口与多线程
unitUnit1;
interface
uses
Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,
Dialogs,StdCtrls,ComCtrls,TeEngine,Series,ExtCtrls,TeeProcs,Chart,
OleCtrls,MSCommLib_TLB;
type
TForm1=class(TForm)
tbshtSignalChart:
TPageControl;
tbshtDebug:
TTabSheet;//串口调试
rchdtSerialIn:
TRichEdit;//串口发送的数据
cmbbxSerialIn:
TComboBox;//串口号
Label7:
TLabel;
btRecStart:
TButton;//开始接受
btRecStop:
TButton;//停止
cmbbxBaudIn:
TComboBox;
Label8:
TLabel;
Label9:
TLabel;
Label10:
TLabel;
Label11:
TLabel;
btRecSave:
TButton;//保存
cmbbxTypeIn:
TComboBox;
cmbbxSerialOut:
TComboBox;/串口端号
Label13:
TLabel;
cmbbxBaudOut:
TComboBox;//波特率
rchdtSerialOut:
TRichEdit;//输入发送
btSendOut:
TButton;
dtCode1:
TEdit;
lbCode1:
TLabel;
lbCode2:
TLabel;
dtCode3:
TEdit;
cmbbxTypeOut:
TComboBox;//发送数据的格式
Label16:
TLabel;
Label51:
TLabel;
tmrSerialIn:
TTimer;
MSCommOut:
TMSComm;
MSCommIn:
TMSComm;
dtCode2:
TEdit;
dtCode4:
TEdit;
lbCode3:
TLabel;
lbCode4:
TLabel;
ImgTrace:
TImage;
Label17:
TLabel;
Label18:
TLabel;
Label19:
TLabel;
Label20:
TLabel;
Label21:
TLabel;
Label22:
TLabel;
Label23:
TLabel;
Label24:
TLabel;
Label25:
TLabel;
Label26:
TLabel;
lbShowAd0:
TLabel;
lbShowAd1:
TLabel;
lbShowAd4:
TLabel;
lbShowAd5:
TLabel;
lbShowAd2:
TLabel;
lbShowGps5:
TLabel;
lbShowGps1:
TLabel;
lbShowAd7:
TLabel;
lbShowAd6:
TLabel;
lbShowAd3:
TLabel;
Label37:
TLabel;
lbShowGps6:
TLabel;
lbShowGps4:
TLabel;
Label53:
TLabel;
Label54:
TLabel;
Label55:
TLabel;
lbShowGps0:
TLabel;
btSaveTrace:
TButton;
btLoadTrace:
TButton;
btSaveData:
TButton;
Label1:
TLabel;
lbShowModel:
TLabel;
Label3:
TLabel;
Label4:
TLabel;
Label5:
TLabel;
Label6:
TLabel;
Label14:
TLabel;
Label15:
TLabel;
Label39:
TLabel;
Label40:
TLabel;
lbShowPara0:
TLabel;
lbShowPara1:
TLabel;
lbShowPara2:
TLabel;
lbShowPara3:
TLabel;
lbShowPara4:
TLabel;
lbShowPara5:
TLabel;
lbShowPara6:
TLabel;
lbShowPara7:
TLabel;
Label49:
TLabel;
lbShowGps2:
TLabel;
Label57:
TLabel;
lbShowGps3:
TLabel;
Label59:
TLabel;
cmbbxModel:
TComboBox;
btSetModel:
TButton;
cmbbxParaNo:
TComboBox;
Label38:
TLabel;
Label60:
TLabel;
Label61:
TLabel;
dtParaValue:
TEdit;
btADInit:
TButton;
btSetPara:
TButton;
Label62:
TLabel;
rdgrpDataCode:
TRadioGroup;
dlgSaveData:
TSaveDialog;
dlgLoadTrace:
TOpenDialog;
dlgSaveTrace:
TSaveDialog;
rchdtTmp:
TRichEdit;
Label2:
TLabel;
TabSheet1:
TTabSheet;
chrtAcc:
TChart;
chrtGyro:
TChart;
srsGyroY:
TFastLineSeries;
srsGyroX:
TFastLineSeries;
srsGyroZ:
TFastLineSeries;
srsAcc1:
TFastLineSeries;
srsAcc2:
TFastLineSeries;
chrtHeight:
TChart;
srsHeight:
TFastLineSeries;
Label12:
TLabel;
btCharClear:
TButton;
tbshtSignal:
TTabSheet;
procedureFormCreate(Sender:
TObject);
procedurebtRecStartClick(Sender:
TObject);
procedurebtRecStopClick(Sender:
TObject);
procedurebtRecSaveClick(Sender:
TObject);
procedurebtSendOutClick(Sender:
TObject);
proceduretmrSerialInTimer(Sender:
TObject);
procedurebtSetModelClick(Sender:
TObject);
procedurebtSetParaClick(Sender:
TObject);
procedureFormDestroy(Sender:
TObject);
procedurebtSaveTraceClick(Sender:
TObject);
procedurebtLoadTraceClick(Sender:
TObject);
procedurebtADInitClick(Sender:
TObject);
procedurebtSaveDataClick(Sender:
TObject);
procedurebtCharClearClick(Sender:
TObject);
proceduredtCode1Change(Sender:
TObject);
proceduredtCode2Change(Sender:
TObject);
proceduredtCode3Change(Sender:
TObject);
proceduredtCode4Change(Sender:
TObject);
private
{Privatedeclarations}
public
{Publicdeclarations}
InitADDataFlag:
Boolean;
end;
/////////////////////////////////////////////////////////////////
{
串口接受线程
}
TSerialInThread=class(TThread)
private
SerialInput:
Variant;//保存该线程从串口获取得到的数据矩阵不同类型的值赋
Seriallength:
integer;//该线程需要处理的数据的个数
SerialStr:
String;//用于保存处理后数据的字符串变量
protected
procedureExecute;override;//需要重载
procedureGetData;//从串口获取数据的过程
procedureTransToStr;//转换为适合显示的字符串的过程
procedurePostData;//显示在用户界面的过程
end;
/////////////////////////////////////////////////////////////////
{
串口发送线程
}
TSerialOutThread=class(TThread)
private
DataOrCode:
Boolean;//是否要求输出指令,False表明输出数据
SerialOutput:
String;//发送数据时的数据矩阵
Seriallength:
integer;//发送数据时,数据长度
tmpVar:
Variant;//发送指令时的数据矩阵
CheckOk:
Boolean;//用户确定的数据或是指令是否有错误
protected
procedureExecute;override;//需要重载
procedureGetData;//从用户界面获取需要输出的数据或是指令代码
procedurePackData;//根据协议打包数据
procedurePackCode;//根据协议打包指令
procedurePostData;//发送给串口控件,实现数据的发送
end;
var
Form1:
TForm1;
implementation
{$R*.dfm}
const
GpsDataCountMax:
integer=20;//GPS数据包中数据的个数
ParaDataCountMax:
integer=9;//参数数据包中数据的个数
ADDataCountMax:
integer=16;//传感器数据包中数据的个数
var
{
实现线程互斥的句柄。
}
hMutex:
THandle=0;//串口接受数据的线程使用的互斥句柄声明一个全局的互斥量句柄变量
hMutex2:
THandle=0;//串口发送数据的线程使用的互斥句柄
{
用于指令上下传的全局变量
}
ReceiveCharFlag:
Boolean;//是否以字符接受串口,False表示以数据接受
ParaDataFlag:
Boolean;//正在截取参数数据包的标志
GPSDataFlag:
Boolean;//正在截取GPS数据包的标志
ADDataFlag:
Boolean;//正在截取传感器数据包的标志
ParaNewDataFlag:
Boolean;//截取完参数的标志
GPSNewDataFlag:
Boolean;//截取完GPS数据包的标志
ADNewDataFlag:
Boolean;//截取完传感器数据包的标志
ParaDataCount:
Integer;//截取参数数据包的计数器
ADDataCount:
Integer;//截取传感器数据包的计数器
GpsDataCount:
Integer;//截取GPS数据包的计数器
DownStr:
String;//用于保存串口下传的所有数据
GpsStr:
String;//保存GPS数据包的数据
ADStr:
String;//保存传感器数据包的数据
ParaDataArray:
array[0..8]ofByte;//接受参数数据包的数组
GpsDataArray:
array[0..19]ofByte;//接受GPS数据包的数组
ADDataArray:
array[0..15]ofByte;//接受传感器数据包的数组
ADDataDblArray:
array[0..7]ofdouble;//传感器实际的采样值
ADDataArrayMean:
array[0..13]ofByte;//保存传感器静态均值的数组。
//不考虑系统电压。
ParaStrArray:
array[0..3]ofString;//显示参数数据的字符串数组
GpsStrArray:
array[0..6]ofString;//显示GPS数据的字符串数组
ADStrArray:
array[0..7]ofString;//显示传感器的字符串数组
{
用于指令上下传的全局变量
}
CodeOutStr:
array[1..4]ofString;//当前上传的指令代码
CodeInStr:
array[0..3]ofString;//下传返回的指令代码
{
用于绘图的全局变量
}
gpsMeta:
TMetaFile;//用于保存轨迹图像的对象
posXArray,posYArray:
arrayofdouble;//保存当前飞行轨迹点的数组
posXArrayLoad,posYArrayLoad:
arrayofdouble;//保存载入的轨迹点的数组
posLength:
Integer;//当前飞行轨迹点的总数
posLengthLoad:
Integer;//当前飞行轨迹点的总数
{
函数hex()是将0~f字符转换为0~15的整数。
}
functionhex(c:
String):
Integer;
var
x:
integer;
begin
if(c='0')or(c='')then
x:
=0
elseifc='1'then
x:
=1
elseifc='2'then
x:
=2
elseifc='3'then
x:
=3
elseifc='4'then
x:
=4
elseifc='5'then
x:
=5
elseifc='6'then
x:
=6
elseifc='7'then
x:
=7
elseifc='8'then
x:
=8
elseifc='9'then
x:
=9
elseif((c='a')or(c='A'))then
x:
=10
elseif(c='b')or(c='B')then
x:
=11
elseif(c='c')or(c='C')then
x:
=12
elseif(c='d')or(c='D')then
x:
=13
elseif(c='e')or(c='E')then
x:
=14
elseif(c='f')or(c='F')then
x:
=15
else
x:
=-1;
Result:
=x;
end;
functionHexToInt(S:
String):
Integer;
var
tmpInt1,tmpInt2:
Integer;
begin
ifLength(S)=1then
begin
Result:
=hex(S[1]);
end
elseifLength(S)=2then
begin
tmpInt1:
=hex(S[1]);
tmpInt2:
=hex(S[2]);
if(tmpInt1=-1)or(tmpInt2=-1)then
Result:
=-1
else
Result:
=tmpInt1*16+tmpInt2;
end
else
Result:
=-1;
end;
functionGetMaxValue(x,y,x1,y1:
ArrayofDouble;len,len1:
Integer):
double;
var
i:
Integer;
begin
result:
=0;
fori:
=0tolen-1do
begin
ifabs(x[i])>resultthen
result:
=abs(x[i]);
ifabs(y[i])>resultthen
result:
=abs(y[i]);
end;
fori:
=0tolen1-1do
begin
ifabs(x1[i])>resultthen
result:
=abs(x1[i]);
ifabs(y1[i])>resultthen
result:
=abs(y1[i]);
end;
end;
/////////////////////////////////////////////////////////////////
{绘制飞行轨迹的函数
红色轨迹是载入的,
蓝色的轨迹是当前轨迹点
1.posXArray,posYArray是当前轨迹点的坐标,
posLength是当前轨迹点的个数
2.posXArrayLoad,posYArrayLoad是载入的轨迹点的坐标,
posLengthLoad是载入的轨迹点的个数
}
procedureDrawAxis;
var
i,x,y,wid,h:
Integer;
pstep,ratio,maxV:
double;
can:
TMetaFileCanvas;
begin
can:
=TMetaFileCanvas.Create(gpsMeta,0);//建立一个画布对象
gpsMeta.Width:
=Form1.ImgTrace.Width;//确定画布对应图像的大小
gpsMeta.Height:
=Form1.ImgTrace.Height;
wid:
=gpsMeta.Width;
h:
=gpsMeta.Height;
{
确定直角坐标的最大值,取10,100,200,500,1000,2000,5000,10000,50000,100000的最小值
缺省状态取100
}
maxV:
=GetMaxValue(posXArray,posYArray,posXArrayLoad,posYArrayLoad,posLength,posLengthLoad);
ifmaxV=0then
maxV:
=100;
ifmaxV<=10then
begin
maxV:
=10;
end
elseifmaxV<=100then
begin
maxV:
=100;
end
elseifmaxV<=200then
maxV:
=200
elseifmaxV<=500then
maxV:
=500
elseifmaxV<=1000then
begin
maxV:
=1000;
end
elseifmaxV<=2000then
maxV:
=2000
elseifmaxV<=5000then
maxV:
=5000
elseifmaxV<=10000then
begin
maxV:
=10000;
end
elseifmaxV<=50000then
maxV:
=50000
elseifmaxV<=100000then
begin
maxV:
=100000;
end
else
begin
maxV:
=1000000;
end;
can.Pen.Color:
=clBlack;
can.Pen.Style:
=psSolid;
can.MoveTo(0,hdiv2);
can.LineTo(wid,hdiv2);
can.MoveTo(widdiv2,0);
can.LineTo(widdiv2,h);
can.Font.Height:
=10;
can.Font.Name:
='Arial';
{
绘制坐标的最大刻度值
}
can.TextOut(0,hdiv2+1,IntToStr(-1*round(maxV)));
can.TextOut(wid-can.TextWidth(IntToStr(round(maxV))),
hdiv2+1,IntToStr(round(maxV)));
can.TextOut(widdiv2+3,
h-can.TextHeight(IntToStr(-1*round(maxV))),IntToStr(-1*round(maxV)));
can.TextOut(widdiv2+1,0,IntToStr(round(maxV)));
{
绘制坐标的刻度,每个座标轴上有21条刻线
}
pstep:
=wid/20;
fori:
=0to21do
begin
can.MoveTo(round(pstep*i),hdiv2-2);
can.LineTo(round(pstep*i),hdiv2);
can.MoveTo(widdiv2,round(pstep*i));
can.LineTo(widdiv2+2,round(pstep*i));
end;
{
绘制载入的轨迹,颜色为红色
}
ifposLengthLoad>0then
begin
can.Pen.Color:
=clRed;