高分相送!用Timer事件接受串口数据 后退出系统弹出错误!然后在运行时弹出runtime error 216 at 0040348A错误

解决方案 »

  1.   

    你GetLastError看看 返回的错误代码如果是 216 则:216 The image file %1 is valid, but is for a machine type other than the current machine.  ERROR_EXE_MACHINE_TYPE_MISMATCH 
    Runtime errors fall into the following categories: I/O errors, numbered 100 through 149
    Fatal errors, numbered 200 through 255
    Operating system errors
      

  2.   

    不用用TIMER取数据,用微软的串口取数控件
      

  3.   

    返回的信息是:Project EcdisGPS.exe raised exception calss EAccessViolation with message 'Access violation at address 00404300 in module 'EcdisGPS.exe'.Read of address 55FFFFF8' .Process stopped .Use Step or Run to continue.
      

  4.   

    我的程序原码(应该就是这里有问题)是:
    procedure TfrmMain.TimerAlarmTimer(Sender: TObject);
    var
      vTmp:variant; //接受数据变量
      ovTmp:olevariant; //接受数据变量
      iCount:integer;  //缓冲区中待接收的字符数
      arrAddress:integer;//船只特征数组下标
      sGroupNo:string; //
      sAddress:string; //船只地址
      Cc:array[1..19]of string;
      latitude1,latitude2,longitude1,longitude2:double; //经、纬度变量
      sTime,sMinute,sSecond:string; //时间变量
      i,DataLen :integer;  //循环变量
      dspeed1,dspeed2:double;   //速度计算变量
    begin
      iCount := MSCommAlarm.InBufferCount;
      while iCount > 0  do
        begin
          ovTmp :=MSCommAlarm.Input;
          //清空接收缓冲区
          MSCommAlarm.InBufferCount := 0 ;
          vTmp:=VarArrayCreate([0,iCount - 1],varByte);
          vTmp := ovTmp;
          for i:= 0 to iCount - 1 do
            begin
              serBuffer[serhead]:= vTmp[i];
              serhead := (serhead + 1) mod serlen;
              iCount := iCount - 1;
            end;
        end;
     //没有接受到祯头
      if  ((serHead - serEnd + serlen) mod serlen) < 2 then  exit; //
      if  serBuffer[serEnd] <> 86 then  serEnd := serEnd + 1;  //第一个字母不是 'V',尾指针加一
     //接受到祯头并且第一个字符为‘V’,获得该祯数据后面的字节数。
      DataLen :=serBuffer[(serEnd + 1) mod serlen] + 1;    //该祯数据的长度
      //不够一祯数据时退出
      if ((serHead - serEnd + serlen) mod serlen) < DataLen then  exit;
     //够一祯数据时,对数据进行处理
      //组号、船只平台号
      sGroupNo := inttostr((serBuffer[(serEnd + 2) mod serlen] + serBuffer[(serEnd + 3) mod serlen]*256) div 360 + 1);
      sAddress := inttostr((serBuffer[(serEnd + 2) mod serlen] + serBuffer[(serEnd + 3) mod serlen]*256) mod 360);
     //纬度1
      Cc[1]:= trim(inttostr(serBuffer[(serEnd + 4) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 4) mod serlen] mod 16));
      Cc[2]:= trim(inttostr(serBuffer[(serEnd + 5) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 5) mod serlen] mod 16));
      Cc[3]:= trim(inttostr(serBuffer[(serEnd + 6) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 6) mod serlen] mod 16));
      //经度1  '1'+
      Cc[4]:= '1'+ trim(inttostr(serBuffer[(serEnd + 7) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 7) mod serlen] mod 16));
      Cc[5]:= trim(inttostr(serBuffer[(serEnd + 8) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 8) mod serlen] mod 16));
      Cc[6]:= trim(inttostr(serBuffer[(serEnd + 9) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 9) mod serlen] mod 16));
      //方向1
      Cc[7]:= trim(inttostr(serBuffer[(serEnd + 10) mod serlen]*2)) + '度';
      //速度
      dspeed1 := serBuffer[(serEnd + 11) mod serlen]/10;
     // Cc[8]:= inttostr(ispeed/10);
      // 纬度2
      Cc[9]:= trim(inttostr(serBuffer[(serEnd + 12) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 12) mod serlen] mod 16));
      Cc[10]:= trim(inttostr(serBuffer[(serEnd + 13) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 13) mod serlen] mod 16));
      Cc[11]:= trim(inttostr(serBuffer[(serEnd + 14) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 14) mod serlen] mod 16));
      //经度2  '1'+
      Cc[12]:=  '1'+ trim(inttostr(serBuffer[(serEnd + 15) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 15) mod serlen] mod 16));
      Cc[13]:= trim(inttostr(serBuffer[(serEnd + 16) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 16) mod serlen] mod 16));
      Cc[14]:= trim(inttostr(serBuffer[(serEnd + 17) mod serlen] div 16)) + trim(inttostr(serBuffer[(serEnd + 17) mod serlen] mod 16));
      //方向2
      Cc[15]:= trim(inttostr(serBuffer[(serEnd + 18) mod serlen]*2)) + '度';
      //速度2
      dspeed2:=serBuffer[(serEnd + 19) mod serlen] / 10;
      //Cc[16]:=inttostr() ;
      // 经、纬度有效位
      Cc[17]:= inttostr(serBuffer[(serEnd + 20) mod serlen] div 16);
      Cc[18]:= inttostr(serBuffer[(serEnd + 20) mod serlen] mod 16);
      //高位
      if  Cc[17] = '1' then
          Cc[17]:= '有'
      else if  Cc[17] = '6' then
          Cc[17]:= '无'
      else
          Cc[17]:= ' ' ;
      //低位
      if  Cc[18] = '1' then
          Cc[18]:= '有'
      else if  Cc[18] = '6' then
          Cc[18]:= '无'
      else
          Cc[18]:= ' ';
      //警报类型
      case serBuffer[(serEnd + 21) mod serlen] of
        0: Cc[19]:='报警';
        1: Cc[19]:='跟踪';
        else
          Cc[19]:= ' ';
      end;
     latitude1 := strtoint(Cc[1]) + strtoint(Cc[2])/60 + strtoint(Cc[3])/6000 ;
     longitude1 := strtoint(Cc[4]) + strtoint(Cc[5])/60 + strtoint(Cc[6])/6000 ;
     latitude2 := strtoint(Cc[9]) + strtoint(Cc[10])/60 + strtoint(Cc[11])/6000 ;
     longitude2 := strtoint(Cc[12]) + strtoint(Cc[13])/60 + strtoint(Cc[14])/6000 ; //将接受的数据存入GPSRecord,station记录表中
     if  Cc[17] = '有' then
      begin
        with ADOQeMain do
          begin
            SQL.Clear;
            SQL.Add('insert into GPSRecord (station,groupno,ryear,rtime,longitude,latitude,direction,speed,state) values ("'+sAddress+'","'+sGroupNo+'",ryear,DateTime,x1,y1,rDirection,rSpeed,rState)');
            Parameters.ParamByName('ryear').Value := DateToStr(Date);
            Parameters.ParamByName('DateTime').Value :=timetostr(time)  ;
            Parameters.ParamByName('x1').Value := longitude1;
            Parameters.ParamByName('y1').Value := latitude1;
            Parameters.ParamByName('rDirection').Value := Cc[7];
            Parameters.ParamByName('rSpeed').Value := dspeed1;
            Parameters.ParamByName('rState').Value := Cc[19];
            ExecSQL;
          end;
     end;
     if  Cc[18] = '有' then
      begin
      //获取时间:当前时间 - 15秒
        sTime :=timetostr(time);
        sMinute:= copy(sTime,9,2);
        sSecond := copy(sTime,12,2);
        if strtoint(sSecond) < 15 then
         begin
          sMinute := inttostr(strtoint(sMinute) - 1);
          sSecond := inttostr(strtoint(sSecond) + 45);
         end
        else
         begin
           sSecond := inttostr(strtoint(sSecond) - 15);
         end;
        sTime := trim(copy(sTime,1,8)+ sMinute + ':' + sSecond);
      //插入记录
         with ADOQeMain do
           begin
             SQL.Clear;
             SQL.Add('insert into GPSRecord (station,groupno,ryear,rtime,longitude,latitude,direction,speed,state) values ("'+sAddress+'","'+sGroupNo+'",ryear,DateTime,x1,y1,rDirection,rSpeed,rState)');
             Parameters.ParamByName('ryear').Value := DateToStr(Date);
             Parameters.ParamByName('DateTime').Value := sTime;
             Parameters.ParamByName('x1').Value := longitude2;
             Parameters.ParamByName('y1').Value := latitude2;
             Parameters.ParamByName('rDirection').Value := Cc[15];
             Parameters.ParamByName('rSpeed').Value := dspeed2;
             Parameters.ParamByName('rState').Value := Cc[19];
             ExecSQL;
           end;
     end;//实时显示窗口中船只平台 的位置
    if Cc[18] = '有' then
      begin
         arrAddress := serBuffer[serEnd + 2] + serBuffer[serEnd + 3] * 256;
         with fArray[arrAddress] do
            begin
            fFeature.Point.Set(longitude2, latitude2);
            fFeature.Update;
            sDirection := Cc[15];
            dSpeed := dspeed2;
            dLatitude:= latitude2 ;
            dLongitue := longitude2 ;
            end;
      end
    else if Cc[17] = '有' then
      begin
        arrAddress :=serBuffer[serEnd + 2] + serBuffer[serEnd + 3] * 256;
         with fArray[arrAddress] do
            begin
            fFeature.Point.Set(longitude1,latitude1);
            fFeature.Update;
            sDirection := Cc[7];
            dSpeed := dspeed1;
            dLatitude:= latitude1 ;
            dLongitue := longitude1 ;
            end;
      end;
      //移动缓冲区指针
      serEnd := (serEnd + Datalen) mod serlen;
     // VarClear(vTmp);
     // VarClear(ovTmp);
    end;
      

  5.   

    216的问题:应用程序释放已经释放了的内存,超过了内存缓冲取界限,在SysUtils结束后,堆的破坏休息才可以被检测到.就会报告错误了。你可以在程序还没有结束之前进行调试,把SysUtils单元在uses申明中的位置遇动到前面,尝试把它列在工程文件的开头处(ShareMem之后),这样的话你处理完错误以后才退出.
      

  6.   

    问题出现在这条语句(我把该条语句注释掉,就没有问题了)
     serBuffer[serhead]:= vTmp[i];
    定义如下
    vTmp:variant;
    vTmp:=VarArrayCreate([0,iCount - 1],varByte);
    vTmp := ovTmp;
    serBuffer:array [1..serlen] of byte;
    不明白这样怎么回出问题?
      

  7.   

    to :longtusoft(神灯之主)
    用oncomm事件读数据效果很差,而且容易丢数据。
    用timer事件,在认为做一个环形的接受缓冲区。节省资源也不会丢数据。