今天用Moxa的pcomm.dll实现了对多个串口的监听,每个串口约3秒产生427个字节,包括了110节电池的电压。而且每个串口同时产生。如果不进行数据保存,没有问题,一旦将数据保存到sqlserver中 ,就出现以下问题:Project output/batteryMonitor.exe faulted with message:'access violation at 0X400022d9:write of address 0x00000001'.Process stopped.use Step or Run to continue
下面是我的主要代码:unit Monitor_Data;
interface
uses
uMyPublic,SysUtils,forms,adodb,DateUtils,Windows,Classes,ActiveX;
type
TMonitor_Data = class (Tobject)
private
Adoconn:TAdoconnection ;
adoqry:Tadoquery;
crcBuf:array[0..1000] of byte;
Mondate:TdateTime;
Rec_data:array of double;
cs:TRTLCriticalSection;
procedure SetFBatt_count(aValue:integer);
procedure SetFInsulate_Count(aValue:integer);
procedure SetFDcm_count(aValue:integer);
procedure Save_Batt_Vol_data();
public
FSuccessFul:boolean;//表示数据是否处于处理中...
FPortNo:integer;//表示那个串口的数据
constructor Create ;
destructor Destroy; virtual;
procedure opinion_style(Fbuf:array of byte) ;//判断是那个类型
procedure transact_Batt_vol_byte(iLength:integer);//处理电池数据
published
end;
var
MonitorData:array of TMonitor_Data;
implementation
uses uPublic;
const
abHead:array[0..11] of byte=($aa,$55,$aa,$55,$aa,$55,$eb,$90,$eb,$90,$eb,$90);
{ TMonitor }
constructor TMonitor_Data.Create;
begin
FSuccessFul:=false;
//InitializeCriticalSection(cs) ;
end;
destructor TMonitor_Data.Destroy;
begin
//DeleteCriticalSection(cs);
end;
//-------------------------
{判断数据类型}
//-------------------------
procedure TMonitor_Data.opinion_style(Fbuf: array of byte);
var
Log_buf:array[0..60] of byte ;
iLengTh:integer;
i:integer;
begin
Mondate:= Now ;
FSuccessFul:=true;
//判断头文件
Move(Fbuf[0],crcBuf[0],12);
if CompareMem(@crcbuf[0],@abhead[0],12) then
begin
FSuccessFul:=false;
exit;
end;
//遥测数据
if ( Fbuf[12] <> byte($71) ) and ( Fbuf[13] <> byte($61) ) then
begin
FSuccessFul:=false;
exit;
end;
iLengTh:=strToInt(IntToHex(FBuf[14],2));//遥测长度
for i:=low(crcBuf) to high(crcBuf) do
crcBuf
:= $00 ;
Move(Fbuf[24],crcBuf[0],(iLengTh-1)*6);
if FBuf[19] = $01 then
transact_Batt_vol_byte(iLengTh-1) ;
FSuccessFul:=false;
end;
//-------------------------
{处理蓄电池电压数据}
//-------------------------
procedure TMonitor_Data.transact_Batt_vol_byte(iLength:integer);
var
i:integer;
begin
setLength(Rec_data,ilength*2);
Rec_data[0]:=GetCommVol(crcBuf[2],crcBuf[1],1);//组压
Rec_data[1]:=GetCommVol(crcBuf[4],crcBuf[3],2);//温度
Rec_data[2]:=StrToFloat(intToHex(crcBuf[7],2));//市电
if StrToInt(intToHex(crcBuf[7],2)) < 0 then
Rec_data[3]:=GetCommVol(crcBuf[10],crcBuf[9],2)* -1 //电流
else
Rec_data[3]:=GetCommVol(crcBuf[10],crcBuf[9],2); //电流
for i:= 2 to iLength -1 do
begin
//if not CheckCrc8(Fbuf,i*6) then
//exit;
Rec_data[i*2] := GetCommVol(crcBuf[i*6+2],crcBuf[i*6+1],2);
Rec_data[i*2+1]:= GetCommVol(crcBuf[i*6+4],crcBuf[i*6+3],2);
application.ProcessMessages ;
end;
// EnterCriticalSection(CS);
Save_Batt_Vol_data;
// LeaveCriticalSection(CS);
end;
//-------------------------
{保存蓄电池电压}
//-------------------------
procedure TMonitor_Data.Save_Batt_Vol_data;
var
i:integer;
begin
try
//CoInitialize( nil );
adoconn:=TAdoconnection.create(Nil);
adoqry:= TAdoquery.create(nil);
adoqry.connection:=Adoconn;
adoqry.CursorLocation:=clUseServer;
adoconn.ConnectionString := 'Provider=SQLOLEDB.1;Password=sa;Persist Security Info=True;User ID=sa;Initial Catalog=test;Data Source=WCH';
adoconn.Connected :=true;
adoconn.BeginTrans ;
for i:= 4 to high(Rec_data)-1 do
begin
adoqry.Close;
adoqry.SQL.Clear ;
adoqry.SQL.Add('insert into Batt_History_detail_Log');
adoqry.SQL.Add('(zd_id,Group_Id,Batt_Id,Batt_Vol,Mon_Date,Mon_Time)');
adoqry.SQL.Add('valueszd_id,:Group_Id,:Batt_Id,:Batt_Vol,:Mon_Date,:Mon_Time)');
adoqry.Parameters.ParamByName('zd_id').Value := format('%.3d',[FportNo]);
adoqry.Parameters.ParamByName('Group_Id').Value := '01' ;
adoqry.Parameters.ParamByName('Batt_Id').Value := format('%.3d',[i-3]);
adoqry.Parameters.ParamByName('Batt_Vol').Value :=Rec_data;
adoqry.Parameters.ParamByName('Mon_Date').Value :=dateOf(MonDate);
adoqry.Parameters.ParamByName('Mon_Time').Value :=timeof(MonDate);
try
adoqry.ExecSQL ;
except
adoconn.RollbackTrans ;
exit;
end;
end;
adoconn.CommitTrans ;
finally
adoqry.Free;
adoconn.Free;
//CoUninitialize;
end;
end;
end.
//----------------------------------------------
//以下是pcomm事件触发程序,iport表示那个串口,
//问题出现在数据保存到数据库是发生错误,
//当四个串口以3s为周期,同时上传数据,运行10分钟左右就有以下错误产生
//----------------------------------------------
procedure CntIrq(iPort:LongInt);stdcall;
var
Mon_array:array of byte;
rLen:LongInt;
i:integer;
begin
setLength(Mon_array ,1400);
rlen := sio_read(iPort,@Mon_array[0] ,1400); //读取数据
If rlen = 0 Then Exit; //若无数据则跳出
for i:=low(sio_read_port) to high(sio_read_port) do
begin
if sio_read_port.Port = iPort then
begin
frmMain.Grid_Port_Info.Cells[2,i+1]:=intToStr(rLen)+':'+dateTimeToStr(now) ;
if MonitorData = nil then
MonitorData:=TMonitor_Data.Create ;
if MonitorData.FSuccessFul then
begin
exit ;
end;
MonitorData.FPortNo := iPort ;
MonitorData.opinion_style(Mon_array);
break;
end;
end;
end;
//------------------------
//打开串口
//------------------------
procedure TFrom1.button1click(sender:Tobject)
begin
setLength(sio_read_port,7);
setLength(MonitorData,7);
sio_read_port[0]:= TSio_read_Port.Create ;
sio_read_port[0].Port := 3 ;
sio_read_port[1]:= TSio_read_Port.Create ;
sio_read_port[1].Port := 4 ;
sio_read_port[2]:= TSio_read_Port.Create ;
sio_read_port[2].Port := 5 ;
sio_read_port[3]:= TSio_read_Port.Create ;
sio_read_port[3].Port := 6 ;
sio_read_port[4]:= TSio_read_Port.Create ;
sio_read_port[4].Port := 7 ;
sio_read_port[5]:= TSio_read_Port.Create ;
sio_read_port[5].Port := 8 ;
sio_read_port[6]:= TSio_read_Port.Create ;
sio_read_port[6].Port := 9 ;
for i:=low(sio_read_port) to high(sio_read_port) do
begin
try
Grid_Port_Info.Cells[0,i+1]:='COM' + intToStr(sio_read_port.Port);
if sio_read_port.OpenPort then
Grid_Port_Info.Cells[1,i+1]:='COM口已经打开'
else
Grid_Port_Info.Cells[1,i+1]:='COM口打开失败' ;
except
sio_read_port.closePort ;
continue;
end;
end;
end;