Tłumaczenie Delphi na C++

0

Witam. Mam problem tego typu, że w projekcie C++ muszę wykorzystać kod z delphi, ale potrafię w całości tego przetłumaczyć :-( Czy ktoś by mógł podjąć wyzwanie i przetłumaczyć na C++??
Załączam kod

unit sbus;
interface

//{$DEFINE DUMP_DATA}

uses cport,sysutils
{$IFDEF DUMP_DATA}
 ,tapp1
{$ENDIF}
;

const

 {########################## PCD CONSTANTS ####################################}

 PCD_HISTORY_TIME_SHIFT = $3f000000; // time field of history record from PCD has this shift

 {###### PCD COMMANDS CODES #####}
 PCD_CMD_SET_TIME             = 1; //unconditional set time
 PCD_CMD_GET_ERRORS           = 3;
 PCD_CMD_DELETE_ERRORS        = 4;
 PCD_CMD_SYNC_TIME            = 5;
 PCD_CMD_SET_SYNC_TIME_MODE   = 6;

 PCD_CMD_SET_SYNC_TIME_MODE_0 = 0;  //time sync disabled
 PCD_CMD_SET_SYNC_TIME_MODE_1 = 1; //pulse on PCD input
 PCD_CMD_SET_SYNC_TIME_MODE_2 = 2; //SBUS command

 PCD_CMD_GET_HDATA       = 9;
 PCD_CMD_DELETE_HDATA    = 10;
 PCD_CMD_ERASE_ALL_DATA  = 11;
 PCD_CMD_GET_ACTDIGDATA  = 12;
 PCD_CMD_GET_ACTANADATA  = 13;
 PCD_CMD_GET_ACTANADATA2 = 14;
 PCD_CMD_GET_ACTANADATA3 = 15;
 //PCD configuration constants
 PCD_CONF_INT = 5;  //small data scan interval value in [s]

 //addresses of registers in PCD
 PCD_CMD_REG       = 3325;
 PCD_CMD_ACK_REG   = 3324;
 PCD_CMD_DATA_BASE = 3326;

 PCD_TIME_REG = 1;

 PCD_CONF_BASE = 100;    //base address of configuration data
 PCD_CONF_DIGCNTRS_BASE = PCD_CONF_BASE;
 PCD_CONF_ANAL_BASE = PCD_CONF_DIGCNTRS_BASE + 1025;
 PCD_CONF_DIGINPUTS_BASE = PCD_CONF_ANAL_BASE +1025;
 PCD_DATA_OFFSET = 3;

 //offsets from base PCD_CONF_BASE
 PCD_CONF_ADDR = 0;
 PCD_CONF_INTS = 2;
 PCD_CONF_INTB = 1;
 PCD_CONF_DESC1= 12;
 PCD_CONF_DESC2= 13;
 PCD_CONF_DESC3= 14;
 PCD_CONF_DESC4= 15;

 PCD_CONF_MASK = 1; //mask for digital inputs

 //base PCD_CONF_BASE + PCD_DATA_OFFSET
 //for digital counters
 PCD_DATA_PULSES_S = 1;
 PCD_DATA_PULSES_B = 0;
 //for analog inputs
 PCD_DATA_A_VAL    = 1;
 PCD_DATA_A_AVG    = 0;
 PCD_DATA_A_MIN_A  = 2;
 PCD_DATA_A_MAX_A  = 3;
 PCD_DATA_A_MIN_P  = 4;
 PCD_DATA_A_MAX_P  = 5;

{########################## SBUS CONSTANTS ####################################}

 SBUS_RETRY_CNT            = 3;  //number of retransmission retries
 SBUS_MAX_INTRAFRAME_BREAK = 5;  //maximum break length in the middle of the frame
 //SBUS functions CODES
 SBUS_READ_DATA_BLOCK  = $96;
 SBUS_READ_REGISTER    = $06;
 SBUS_WRITE_REGISTER   = $0E;

 //getFrame results
 GFR_TIMEOUT          = $8000; //transmission timeout
 GFR_CRC_ERR          = $8001;
 GFR_RETRY            = $8002;
 GFR_COM_PORT_CLOSED  = $8003;
 GFR_COM_WRITE_ERROR  = $8004;
 GFR_COM_CLEAR_ERROR  = $8005;
 GFR_COM_ERROR        = $8006;
 GFR_COM_READ_ERROR   = $8004;
 GFR_OK               = $0001; //command executed OK
 GFR_COMMAND_REJECTED = $0002; //transmission OK, command rejected by PCD
 GFR_WAIT             = $0003;

 //DUMP_DATA params
 DD_WR        = 1; //dump WRITE-to-COM data
 DD_RD        = 2;
 DD_ERROR     = 3;
 DD_DEBUG     = 4; //dump data readen from COM
 DD_RETRY     = 5;
 DD_TOUT      = 6;

 //single gate structure
type
stGate = record
  Station:BYTE;        // station number
  Func:BYTE;           // READ_REGISTER etc.
  Address:WORD;        // of register/data block
  DBNumber:WORD;       // DATABLOCK commands
  DBElement:WORD;
  Count:WORD;          // no of elements (base 1)
  RXTimeout:integer;   // timeout for first rx char in 20 ms units
  value:array [0..31] of integer; //output data
    //internal data
  wait_for: BYTE ;
  ReplySize:WORD;      // expected reply size
end;

{**************************************************************************
* PUT SBUS COMMAND
* ========================
* INPUT -> comPort - properly opened serial port
*                G - properly filled command structure
*         respBuff - buffer for incoming reply
* OUTPUT -> result code one of:
*           GFR_TIMEOUT , GFR_OK , GFR_COMMAND_REJECTED
*           GFR_COM_WRITE_ERROR , GFR_COM_CLEAR_ERROR , GFR_COM_READ_ERROR
***************************************************************************}
function SBUSPut(comPort:TcomPort;var G:stGate;RespBuff:PByteArray):WORD;

{**************************************************************************
* CONVERT INTEL TO MOTOROLA ENDIAN (AND VICE VERSA)
***************************************************************************}
function intI2intM(intel:integer):longword;

//###############################################################################

implementation

const
 SBUS_RX_Sync    =0;
 SBUS_RX_Attrib  =1;
 SBUS_RX_Data    =2;


function intI2intM(intel:integer):longword;
var
 x:longword;
begin
 x:=intel;
 intel:= (x shr 24) or (x shl 24) or ((x and $00FF0000) shr 8) or ((x and $0000FF00) shl 8);
 result:=intel;
end;

//calculate CRC en-block
function SBUS_CountCRC16(Buff: PByteArray ;DataLen: BYTE) : WORD ;
var
 CRC: WORD;
 i,j: BYTE;
begin
 CRC:=0;
 j:=0;
while j<DataLen do begin
 CRC := CRC xor WORD(Buff[j] shl 8);
 inc(j);
 for i:=0 to 7 do begin
  if (CRC and $8000) = $8000 then CRC:= (CRC shl 1) xor $1021
   else CRC:= (CRC shl 1);
 end;
end;
//swap bytes to motorola
result:= ((CRC shl 8)and $ffff) or (CRC shr 8);
end;


//crc calculation byte by byte
function addCRC(b:BYTE;CRC:WORD):WORD;
var
 i:integer;
begin
 CRC := CRC xor WORD(b shl 8);
 for i:=0 to 7 do begin
  if (CRC and $8000) = $8000 then CRC:= (CRC shl 1) xor $1021
   else CRC:= (CRC shl 1);
 end;
 result:=CRC;
end;


function SBUSSendFrame(comPort:TcomPort; buffer:PByteArray; message_length:BYTE):boolean;
var
  i:BYTE ;
  Buff:array [0..255] of BYTE;
  pBuff,pCRC:^BYTE;
  buff_len:BYTE;
  CRC:WORD;
begin
  result:=true;
  buff_len:=2;    //for $B5 $00
  pBuff:=@Buff;
  pBuff^:=$b5; inc(pBuff);
  pBuff^:=$00; inc(pBuff);   //telegram

  buff_len:=buff_len + message_length;

   for i:=0 to message_length-1 do
    begin
     case buffer[i] of
       $b5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$00; inc(pBuff);
             inc(buff_len);
            end;
       $c5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$01; inc(pBuff);
             inc(buff_len);
            end;
       else begin
             pBuff^:=buffer[i]; inc(pBuff);
            end;
     end;
    end;

  CRC:=SBUS_CountCRC16(@Buff,buff_len); //calculate CRC from encoded message

  pCRC:=@CRC;
  for i:=0 to 1 do begin//encode CRC itself too
   case pCRC^ of
       $b5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$00; inc(pBuff);
             buff_len:=buff_len+2;
            end;
       $c5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$01; inc(pBuff);
             buff_len:=buff_len+2;
            end;
       else begin
             pBuff^:=pCRC^; inc(pBuff);
             inc(buff_len);
            end;
   end; //case
   inc(pCRC);
  end;
  try
   comPort.Write(Buff,buff_len);  // Send it out...
  except
   on EComPort do result:=false;
  end;
{$ifdef DUMP_DATA}
  dumpData(@Buff,buff_len,DD_WR);
{$endif}
end;


function ComMakeQuery(comPort:TcomPort;var G:stGate):boolean;
var
 Frame:array [0..255] of BYTE;
 toSend:integer;
begin
    toSend:=0; //for unknown commands
    Frame[0]:=G.Station;
    Frame[1]:=G.Func;                //Command

    case G.Func of
     SBUS_READ_DATA_BLOCK :
      begin
       toSend:=7;
       Frame[2]:=G.count-1;
       Frame[3]:=BYTE(G.DBNumber shr 8);
       Frame[4]:=BYTE(G.DBNumber);
       Frame[5]:=BYTE(G.DBElement shr 8);
       Frame[6]:=BYTE(G.DBElement);
       G.ReplySize:= (G.count)*4;
      end;
     SBUS_READ_REGISTER:
      begin
       toSend:=5;
       Frame[2]:=G.count-1;
       Frame[3]:=BYTE(G.Address shr 8);
       Frame[4]:=BYTE(G.Address);
       G.ReplySize:= (G.count)*4;
      end;
     SBUS_WRITE_REGISTER:
      begin
       Frame[2]:=G.count*4+1;
       toSend:=5+(g.count*4);
       Frame[3]:=BYTE(G.Address shr 8);
       Frame[4]:=BYTE(G.Address);
       move(G.value[0],Frame[5],g.count*4);
       G.ReplySize:= 2;
      end;
     end; //case
    result:=SBUSSendFrame(comPort, @Frame,toSend);
end;


//---------------------------------------------------------------------------
// expCnt -   expected answer length
// nReceived - length of received chars buffer
function SBUSGetFrame(var expCnt:BYTE; BuffOut:PByteArray ;var FramePos: BYTE ;
                      BuffIn:PBYTEArray ;nReceived :BYTE; var CRC:WORD;
                      var huntMode:boolean;var wait_for:BYTE): integer ;
var
 i,rx_char:BYTE;
 inCRC:boolean;
begin
 i:=0;
 inCRC:=false;
 result:=GFR_Wait;

 while(i<nReceived) do begin
  rx_char:=BuffIn[i];

  case (wait_for) of
      SBUS_RX_Sync: begin
          	     if (rx_char=$b5) then begin
      	              FramePos:=0; CRC:=0; huntMode:= FALSE;
                      CRC:=addCRC(rx_char,CRC);
	      	      BuffOut[FramePos]:=rx_char; inc(FramePos);
          	      wait_for:=SBUS_RX_Attrib;
	             end;
  	            end;
      SBUS_RX_Attrib: begin
	      	       BuffOut[FramePos]:=rx_char; inc(FramePos);
                       CRC:=addCRC(rx_char,CRC);
                       case (rx_char) of
                        1: begin            //response
                            wait_for:=SBUS_RX_Data;
                           end;
                        2: begin            //ack
                            expCnt:=2+2;
                            wait_for:=SBUS_RX_Data;
                           end;
                        else wait_for:=SBUS_RX_Sync;
                       end;
                      end;
      SBUS_RX_Data: begin
                     if (expCnt<=2) then inCRC:=TRUE;
                     if (rx_char<>$c5) then begin
                      if huntMode then begin
                       case rx_char of
                        $00: BuffOut[FramePos]:=$b5;
                        $01: BuffOut[FramePos]:=$c5;
                        else begin//error in data stream
                              result:=GFR_Crc_Err;
                              break;
                             end;
                       end; //case
                       dec(expCnt);
                       inc(FramePos); huntMode:=FALSE;
                      end else begin
                       dec(expCnt); //ESC char
   	      	       BuffOut[FramePos]:=rx_char; inc(FramePos);
                      end
                     end else huntMode:=TRUE;

                     if inCRC then begin
                      if not huntMode then CRC:=addCRC(BuffOut[FramePos-1],CRC);
                     end else begin
                      CRC:=addCRC(rx_char,CRC);
                     end;

                     if (expCnt=0) then begin
		      if CRC <> $0000 then begin
                       result:=GFR_Crc_Err;
                       break;
                      end;
 	              wait_for:=SBUS_RX_Sync;
                      result:=GFR_OK;
                      break;
                     end;
                    end;

	  end; //end switch
    inc(i);
  end; //while
 end;


function ComGetResponse(comPort:TcomPort;G:stGate;RespBuff:PByteArray):integer;
var
 len,lenx:integer;
 Pos,RecCnt,no_rx,got:BYTE;
 BuffIn: array [0..255] of BYTE;
 stat,CRC:WORD;
 Events:TComEvents;
 huntMode:boolean;
begin
 try
   Pos:=0;
   no_rx:=g.RXTimeout;   //in 20ms increments, wait for first rx char
   stat:= GFR_Wait;
   RecCnt:=G.ReplySize+2;//include CRC
   G.wait_for:=SBUS_RX_Sync;
   repeat
     Events:=[evRxChar];
     comPort.WaitForEvent(Events,20);
     if (Events=[evRxChar]) then begin
        len:=comPort.InputCount();
        no_rx:=SBUS_MAX_INTRAFRAME_BREAK; //reload timer, allow short break in transmission

        while (len>0) do begin
         if len>255 then lenx:=255 else lenx:=len; // don't overflow
         len:=len-lenx;
         got:=comPort.Read(BuffIn,lenx);
{$ifdef DUMP_DATA}
         dumpData(@BuffIn,got,DD_DEBUG);
{$endif}
         stat:=SBUSGetFrame(RecCnt,RespBuff, Pos, @BuffIn, got,CRC,huntMode,G.wait_For);
        end;

      end else dec(no_rx);
    until ((stat=GFR_OK) or (stat=GFR_Crc_Err) or (no_rx=0));

   if (no_rx=0) then stat:=GFR_TimeOut;
{$ifdef DUMP_DATA}
  if (stat=GFR_Crc_Err) then dumpData(RespBuff,Pos,DD_ERROR)
   else if (stat=GFR_OK) then dumpData(RespBuff,Pos,DD_RD)
    else if (stat=GFR_TimeOut) then dumpData(RespBuff,Pos,DD_TOUT);
{$endif}
  if (RespBuff[1]=$02) and (RespBuff[3]=$01) then stat:= GFR_COMMAND_REJECTED;
  result:= stat;
 except
  on EComPort  do result:=  GFR_COM_READ_ERROR;
 end;
end;


function SBUSPut(comPort:TcomPort;var G:stGate;RespBuff:PByteArray):WORD;
var
 RetryCnt:integer;
 stat:WORD;
begin
  if comPort.Connected then begin
   RetryCnt:=SBUS_RETRY_CNT;
   stat:=GFR_COM_ERROR;
   repeat
    dec(RetryCnt);
    try
     comPort.clearbuffer(TRUE,TRUE);
    except
     on EComPort do begin
                  stat:= GFR_COM_CLEAR_ERROR;
                  break;
                 end;
    end;
    if not ComMakeQuery(comPort,G) then begin
     stat:= GFR_COM_WRITE_ERROR;
     break;
    end;
    stat:=ComGetResponse(comPort,G,RespBuff);
{$ifdef DUMP_DATA}
    if (stat<>GFR_OK) then dumpData(nil,1,DD_RETRY);
{$endif}
   until ((stat=GFR_OK) or (stat=GFR_COMMAND_REJECTED) or (RetryCnt=0));
   if ((RetryCnt=0) and (stat<>GFR_OK) and (stat<>GFR_COMMAND_REJECTED)) then stat:=GFR_TimeOut;
  end else stat:= GFR_COM_PORT_CLOSED;
  result:=stat;
end;

end.

Bardzo proszę o pomoc, ale znając życie to pewnie nikt nie zrobi tego, bo troszke tego jest :(

0

Właśnie, to dość długi kawał kodu, powiedz lepiej, czego nie rozumiesz ;-)

0

Łatwiej zrobić z tego dll i potem użyć w innym języku.

0

dll to dobre wyjście.

Podejrzewam, że to jakiś gotowy kod z neta. Jeżeli tak to pewnie napisany przez obcokrajowca. A tam większe prawdopodobieństwo, że w necie jest też wersja w c++ :)

0

w c++ tego sie nie dostanie, fart ze mam to chociaz w delphi :) Moze ktoś powiedzieć jak się robi dll??
A odnośnie tego czego nie kumam to już wypisuję przykłady :)

unit sbus;
interface

//{$DEFINE DUMP_DATA}

uses cport,sysutils
{$IFDEF DUMP_DATA}
 ,tapp1
{$ENDIF}
;
implementation      // o samo implementation sie teraz rozchodzi

const
 SBUS_RX_Sync    =0;
 SBUS_RX_Attrib  =1;
 SBUS_RX_Data    =2;

intel:= (x shr 24) or (x shl 24) or ((x and $00FF0000) shr 8) or ((x and $0000FF00) shl 8);

CRC := CRC xor WORD(Buff[j] shl 8);

function SBUS_CountCRC16(Buff: PByteArray ;DataLen: BYTE) : WORD ;

function SBUSSendFrame(comPort:TcomPort; buffer:PByteArray; message_length:BYTE):boolean;
var
  i:BYTE ;
  Buff:array [0..255] of BYTE;
  pBuff,pCRC:^BYTE;
  buff_len:BYTE;
  CRC:WORD;
begin
  result:=true;                        //dlaczego tutaj juz jest result?? to chyba odpowiednik "return", tak??
  buff_len:=2;    //for $B5 $00
  pBuff:=@Buff;
  pBuff^:=$b5; inc(pBuff);
  pBuff^:=$00; inc(pBuff);   //telegram

CRC:=SBUS_CountCRC16(@Buff,buff_len); //calculate CRC from encoded messag

case pCRC^ of

try
   comPort.Write(Buff,buff_len);  // Send it out...
  except
   on EComPort do result:=false;
  end;
{$ifdef DUMP_DATA}
  dumpData(@Buff,buff_len,DD_WR);
{$endif}
function SBUSGetFrame(var expCnt:BYTE; BuffOut:PByteArray ;var FramePos: BYTE ;
                      BuffIn:PBYTEArray ;nReceived :BYTE; var CRC:WORD;
                      var huntMode:boolean;var wait_for:BYTE): integer ;
{$ifdef DUMP_DATA}
         dumpData(@BuffIn,got,DD_DEBUG);
{$endif}
         stat:=SBUSGetFrame(RecCnt,RespBuff, Pos, @BuffIn, got,CRC,huntMode,G.wait_For);
        end;

      end else dec(no_rx);
    until ((stat=GFR_OK) or (stat=GFR_Crc_Err) or (no_rx=0));

   if (no_rx=0) then stat:=GFR_TimeOut;
{$ifdef DUMP_DATA}
  if (stat=GFR_Crc_Err) then dumpData(RespBuff,Pos,DD_ERROR)
   else if (stat=GFR_OK) then dumpData(RespBuff,Pos,DD_RD)
    else if (stat=GFR_TimeOut) then dumpData(RespBuff,Pos,DD_TOUT);
{$endif}
  if (RespBuff[1]=$02) and (RespBuff[3]=$01) then stat:= GFR_COMMAND_REJECTED;
  result:= stat;
 except
  on EComPort  do result:=  GFR_COM_READ_ERROR;
 end;
    try
     comPort.clearbuffer(TRUE,TRUE);
    except
     on EComPort do begin
                  stat:= GFR_COM_CLEAR_ERROR;
                  break;
                 end;
    end;
    if not ComMakeQuery(comPort,G) then begin
     stat:= GFR_COM_WRITE_ERROR;
     break;
    end;
    stat:=ComGetResponse(comPort,G,RespBuff);
{$ifdef DUMP_DATA}
    if (stat<>GFR_OK) then dumpData(nil,1,DD_RETRY);
{$endif}
   until ((stat=GFR_OK) or (stat=GFR_COMMAND_REJECTED) or (RetryCnt=0));
   if ((RetryCnt=0) and (stat<>GFR_OK) and (stat<>GFR_COMMAND_REJECTED)) then stat:=GFR_TimeOut;
  end else stat:= GFR_COM_PORT_CLOSED;
  result:=stat;
end;

i ostatnia rzecz begin
for i:=2 to g.ReplySize + 2 - 1 do s:= s + inttohex(RespBuff[i],2) +'.'; // a tej petli juz w ogole nie kumam +2-1 mnie tak myli ze szok
memo1.Lines.SetText(PChar(s));
end; //GFR_OK


Wiem że tego jest troszke, ale po prostu nie zajmowałem sie delphi i nie wszystkie rzeczy kumam. Będę wdzięczny za okazałą pomoc :)
0

Mam prośbę....byłby ktoś tak miły i zrobiłby dll z tego i wrzucił na jakiś serwer??

I jeszcze żeby ktoś wytłumaczył ostatni kod.

0

w c++ tego sie nie dostanie, fart ze mam to chociaz w delphi Moze ktoś powiedzieć jak się robi dll??

po pierwsze, w module sbus.pas musisz ustawić konwencję wywołania dla wszystkich eksportowanych funkcji, np.

function SBUSSendFrame(bla bla bla):boolean; cdecl;

albo

function SBUSSendFrame(bla bla bla):boolean; stdcall;

i z taką samą konwencją je potem importować w C.

sama dll-ka sprowadzi się do

library biblioteka;

uses cport;

exports
  SBUS_CountCRC16,
  SBUSSendFrame,     // i tak dalej
  SBUSGetFrame;

end.

Z tym, że to ci się skompiluje do .dll - Delphi nie tworzy potrzebnego w C pliku .lib
Jak odtworzyć brakujący .lib gdy mamy .dll to już poszukaj instrukcji dla swojego kompilatora.
Powyższa biblioteka importuje wszystko z modułu cport i upublicznia funkcje wymienione w sekcji exports.
Ale może też (przed "exports") zawierać własne funkcje.

unit sbus;
interface

//{$DEFINE DUMP_DATA}

uses cport,sysutils
{$IFDEF DUMP_DATA}
 ,tapp1
{$ENDIF}

przykładowy moduł w Delphi ma podstawowy format:

UNIT nazwa_modulu;

INTERFACE
{ tutaj deklaracje publiczne: stałe, typy, klasy i nagłówki funkcji
  które mają być widoczne na zewnątrz unitu }

procedure foo;  // tylko nagłówek

IMPLEMENTATION
{ deklaracje prywatne : stałe, typy i klasy widoczne tylko w tej części unitu.
  tutaj są również ciała wszystkich funkcji. }

procedure bar; { procedura bar nie jest widoczna na zewnątrz unitu, }
begin            { bo nie ma jej w sekcji interface }
  // ...
end;

procedure foo;
begin
  bar;
end;

END.
intel:= (x shr 24) or (x shl 24) or ((x and $00FF0000) shr 8) or ((x and $0000FF00) shl 8);

$00FF0000 to 0x00FF0000
shr to >>
or to | albo ||
and to & albo &&

CRC := CRC xor WORD(Buff[j] shl 8);
CRC ^= (WORD)(Buff[j] << 8);
function SBUS_CountCRC16(Buff: PByteArray ;DataLen: BYTE) : WORD ;
WORD SBUS_CountCRC16(PByteArray Buff; BYTE DataLen)
result:=true;  //dlaczego tutaj juz jest result?? to chyba odpowiednik "return", tak??

tak, nadaje wartość, ale nie kończy funkcji.

CRC:=SBUS_CountCRC16(@Buff,buff_len); //calculate CRC from encoded messag

@ to pobranie adresu, czyli &Buff

case pCRC^ of
switch(*pCRC)
function SBUSGetFrame(var expCnt:BYTE; BuffOut:PByteArray ;var FramePos: BYTE ;
                      BuffIn:PBYTEArray ;nReceived :BYTE; var CRC:WORD;
                      var huntMode:boolean;var wait_for:BYTE): integer ;
int SBUSGetFrame(BYTE &expCnt, PByteArray BuffOut, BYTE &FramePos,
                      PBYTEArray BuffIn, BYTE nReceived, WORD &CRC,
                      bool &huntMode, BYTE &wait_for)
for i:=2 to g.ReplySize + 2 - 1 do s:= s + inttohex(RespBuff[i],2) +'.';          // a tej petli juz w ogole nie kumam +2-1 mnie tak myli ze szok

nie ma w tym żadnego haczyka. pętla przebiega od 2 do g.ReplySize+2-1.

for (i=2; i <= g.ReplySize+2-1; i++)
0

Dziekuje bardzo za odpowiedź i pomoc :) Zaraz się wezmę za to i spróbuję to zrobić :)

0

Aha, mam pytanie, o co chodzi z ustawianiem konwencji, bo nie bardzo rozumiem (pierwszy raz spotykam sie z tą definicją, poza Konwencją Genewską :P) ? ?

0
procedure bar; { procedura bar nie jest widoczna na zewnątrz unitu, }
begin            { bo nie ma jej w sekcji interface }
  // ...
end;

co ma w tej procedurze się znajdować?? bo nie wiem.....

0

To co potrzebujesz. A w ogóle przecież to był tylko przykład jak tworzyć moduły.

0

Teraz inne pytanie.....w schemacie pliku dll nie ma zmiennych globalnych itd, gdzie je dopisac i jak sie do nich potem dobrać?

0

zrobiłem cos takiego, ale błędy wyskakują.....co jest nie tak?? Jak zrobić zmienne dostępne globalnie?? też przez export??

library sbus;


//{$DEFINE DUMP_DATA}

uses cport,sysutils
{$IFDEF DUMP_DATA}
 ,tapp1
{$ENDIF}
;
const

 {########################## PCD CONSTANTS ####################################}

 PCD_HISTORY_TIME_SHIFT = $3f000000; // time field of history record from PCD has this shift

 {###### PCD COMMANDS CODES #####}
 PCD_CMD_SET_TIME             = 1; //unconditional set time
 PCD_CMD_GET_ERRORS           = 3;
 PCD_CMD_DELETE_ERRORS        = 4;
 PCD_CMD_SYNC_TIME            = 5;
 PCD_CMD_SET_SYNC_TIME_MODE   = 6;

 PCD_CMD_SET_SYNC_TIME_MODE_0 = 0;  //time sync disabled
 PCD_CMD_SET_SYNC_TIME_MODE_1 = 1; //pulse on PCD input
 PCD_CMD_SET_SYNC_TIME_MODE_2 = 2; //SBUS command

 PCD_CMD_GET_HDATA       = 9;
 PCD_CMD_DELETE_HDATA    = 10;
 PCD_CMD_ERASE_ALL_DATA  = 11;
 PCD_CMD_GET_ACTDIGDATA  = 12;
 PCD_CMD_GET_ACTANADATA  = 13;
 PCD_CMD_GET_ACTANADATA2 = 14;
 PCD_CMD_GET_ACTANADATA3 = 15;
 //PCD configuration constants
 PCD_CONF_INT = 5;  //small data scan interval value in [s]

 //addresses of registers in PCD
 PCD_CMD_REG       = 3325;
 PCD_CMD_ACK_REG   = 3324;
 PCD_CMD_DATA_BASE = 3326;

 PCD_TIME_REG = 1;

 PCD_CONF_BASE = 100;    //base address of configuration data
 PCD_CONF_DIGCNTRS_BASE = PCD_CONF_BASE;
 PCD_CONF_ANAL_BASE = PCD_CONF_DIGCNTRS_BASE + 1025;
 PCD_CONF_DIGINPUTS_BASE = PCD_CONF_ANAL_BASE +1025;
 PCD_DATA_OFFSET = 3;

 //offsets from base PCD_CONF_BASE
 PCD_CONF_ADDR = 0;
 PCD_CONF_INTS = 2;
 PCD_CONF_INTB = 1;
 PCD_CONF_DESC1= 12;
 PCD_CONF_DESC2= 13;
 PCD_CONF_DESC3= 14;
 PCD_CONF_DESC4= 15;

 PCD_CONF_MASK = 1; //mask for digital inputs

 //base PCD_CONF_BASE + PCD_DATA_OFFSET
 //for digital counters
 PCD_DATA_PULSES_S = 1;
 PCD_DATA_PULSES_B = 0;
 //for analog inputs
 PCD_DATA_A_VAL    = 1;
 PCD_DATA_A_AVG    = 0;
 PCD_DATA_A_MIN_A  = 2;
 PCD_DATA_A_MAX_A  = 3;
 PCD_DATA_A_MIN_P  = 4;
 PCD_DATA_A_MAX_P  = 5;

{########################## SBUS CONSTANTS ####################################}

 SBUS_RETRY_CNT            = 3;  //number of retransmission retries
 SBUS_MAX_INTRAFRAME_BREAK = 5;  //maximum break length in the middle of the frame
 //SBUS functions CODES
 SBUS_READ_DATA_BLOCK  = $96;
 SBUS_READ_REGISTER    = $06;
 SBUS_WRITE_REGISTER   = $0E;

 //getFrame results
 GFR_TIMEOUT          = $8000; //transmission timeout
 GFR_CRC_ERR          = $8001;
 GFR_RETRY            = $8002;
 GFR_COM_PORT_CLOSED  = $8003;
 GFR_COM_WRITE_ERROR  = $8004;
 GFR_COM_CLEAR_ERROR  = $8005;
 GFR_COM_ERROR        = $8006;
 GFR_COM_READ_ERROR   = $8004;
 GFR_OK               = $0001; //command executed OK
 GFR_COMMAND_REJECTED = $0002; //transmission OK, command rejected by PCD
 GFR_WAIT             = $0003;

 //DUMP_DATA params
 DD_WR        = 1; //dump WRITE-to-COM data
 DD_RD        = 2;
 DD_ERROR     = 3;
 DD_DEBUG     = 4; //dump data readen from COM
 DD_RETRY     = 5;
 DD_TOUT      = 6;

 //single gate structure
type
stGate = record
  Station:BYTE;        // station number
  Func:BYTE;           // READ_REGISTER etc.
  Address:WORD;        // of register/data block
  DBNumber:WORD;       // DATABLOCK commands
  DBElement:WORD;
  Count:WORD;          // no of elements (base 1)
  RXTimeout:integer;   // timeout for first rx char in 20 ms units
  value:array [0..31] of integer; //output data
    //internal data
  wait_for: BYTE ;
  ReplySize:WORD;      // expected reply size
end;

{**************************************************************************
* PUT SBUS COMMAND
* ========================
* INPUT -> comPort - properly opened serial port
*                G - properly filled command structure
*         respBuff - buffer for incoming reply
* OUTPUT -> result code one of:
*           GFR_TIMEOUT , GFR_OK , GFR_COMMAND_REJECTED
*           GFR_COM_WRITE_ERROR , GFR_COM_CLEAR_ERROR , GFR_COM_READ_ERROR
***************************************************************************}
//function SBUSPut(comPort:TcomPort;var G:stGate;RespBuff:PByteArray):WORD;

{**************************************************************************
* CONVERT INTEL TO MOTOROLA ENDIAN (AND VICE VERSA)
***************************************************************************}
//function intI2intM(intel:integer):longword;

//###############################################################################


const
 SBUS_RX_Sync    =0;
 SBUS_RX_Attrib  =1;
 SBUS_RX_Data    =2;


function intI2intM(intel:integer):longword;stdcall;
var
 x:longword;
begin
 x:=intel;
 intel:= (x shr 24) or (x shl 24) or ((x and $00FF0000) shr 8) or ((x and $0000FF00) shl 8);
 result:=intel;
end;

//calculate CRC en-block
function SBUS_CountCRC16(Buff: PByteArray ;DataLen: BYTE) : WORD ; stdcall;
var
 CRC: WORD;
 i,j: BYTE;
begin
 CRC:=0;
 j:=0;
while j<DataLen do begin
 CRC := CRC xor WORD(Buff[j] shl 8);
 inc(j);
 for i:=0 to 7 do begin
  if (CRC and $8000) = $8000 then CRC:= (CRC shl 1) xor $1021
   else CRC:= (CRC shl 1);
 end;
end;
//swap bytes to motorola
result:= ((CRC shl 8)and $ffff) or (CRC shr 8);
end;


//crc calculation byte by byte
function addCRC(b:BYTE;CRC:WORD):WORD;stdcall;
var
 i:integer;
begin
 CRC := CRC xor WORD(b shl 8);
 for i:=0 to 7 do begin
  if (CRC and $8000) = $8000 then CRC:= (CRC shl 1) xor $1021
   else CRC:= (CRC shl 1);
 end;
 result:=CRC;
end;


function SBUSSendFrame(comPort:TcomPort; buffer:PByteArray; message_length:BYTE):boolean ;stdcall;
var
  i:BYTE ;
  Buff:array [0..255] of BYTE;
  pBuff,pCRC:^BYTE;
  buff_len:BYTE;
  CRC:WORD;
begin
  result:=true;
  buff_len:=2;    //for $B5 $00
  pBuff:=@Buff;
  pBuff^:=$b5; inc(pBuff);
  pBuff^:=$00; inc(pBuff);   //telegram

  buff_len:=buff_len + message_length;

   for i:=0 to message_length-1 do
    begin
     case buffer[i] of
       $b5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$00; inc(pBuff);
             inc(buff_len);
            end;
       $c5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$01; inc(pBuff);
             inc(buff_len);
            end;
       else begin
             pBuff^:=buffer[i]; inc(pBuff);
            end;
     end;
    end;

  CRC:=SBUS_CountCRC16(@Buff,buff_len); //calculate CRC from encoded message

  pCRC:=@CRC;
  for i:=0 to 1 do begin//encode CRC itself too
   case pCRC^ of
       $b5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$00; inc(pBuff);
             buff_len:=buff_len+2;
            end;
       $c5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$01; inc(pBuff);
             buff_len:=buff_len+2;
            end;
       else begin
             pBuff^:=pCRC^; inc(pBuff);
             inc(buff_len);
            end;
   end; //case
   inc(pCRC);
  end;
  try
   comPort.Write(Buff,buff_len);  // Send it out...
  except
   on EComPort do result:=false;
  end;
{$ifdef DUMP_DATA}
  dumpData(@Buff,buff_len,DD_WR);
{$endif}
end;


function ComMakeQuery(comPort:TcomPort;var G:stGate):boolean;stdcall;
var
 Frame:array [0..255] of BYTE;
 toSend:integer;
begin
    toSend:=0; //for unknown commands
    Frame[0]:=G.Station;
    Frame[1]:=G.Func;                //Command

    case G.Func of
     SBUS_READ_DATA_BLOCK :
      begin
       toSend:=7;
       Frame[2]:=G.count-1;
       Frame[3]:=BYTE(G.DBNumber shr 8);
       Frame[4]:=BYTE(G.DBNumber);
       Frame[5]:=BYTE(G.DBElement shr 8);
       Frame[6]:=BYTE(G.DBElement);
       G.ReplySize:= (G.count)*4;
      end;
     SBUS_READ_REGISTER:
      begin
       toSend:=5;
       Frame[2]:=G.count-1;
       Frame[3]:=BYTE(G.Address shr 8);
       Frame[4]:=BYTE(G.Address);
       G.ReplySize:= (G.count)*4;
      end;
     SBUS_WRITE_REGISTER:
      begin
       Frame[2]:=G.count*4+1;
       toSend:=5+(g.count*4);
       Frame[3]:=BYTE(G.Address shr 8);
       Frame[4]:=BYTE(G.Address);
       move(G.value[0],Frame[5],g.count*4);
       G.ReplySize:= 2;
      end;
     end; //case
    result:=SBUSSendFrame(comPort, @Frame,toSend);
end;


//---------------------------------------------------------------------------
// expCnt -   expected answer length
// nReceived - length of received chars buffer
function SBUSGetFrame(var expCnt:BYTE; BuffOut:PByteArray ;var FramePos: BYTE ;
                      BuffIn:PBYTEArray ;nReceived :BYTE; var CRC:WORD;
                      var huntMode:boolean;var wait_for:BYTE): integer; stdcall;
var
 i,rx_char:BYTE;
 inCRC:boolean;
begin
 i:=0;
 inCRC:=false;
 result:=GFR_Wait;

 while(i<nReceived) do begin
  rx_char:=BuffIn[i];

  case (wait_for) of
      SBUS_RX_Sync: begin
          	     if (rx_char=$b5) then begin
      	              FramePos:=0; CRC:=0; huntMode:= FALSE;
                      CRC:=addCRC(rx_char,CRC);
	      	      BuffOut[FramePos]:=rx_char; inc(FramePos);
          	      wait_for:=SBUS_RX_Attrib;
	             end;
  	            end;
      SBUS_RX_Attrib: begin
	      	       BuffOut[FramePos]:=rx_char; inc(FramePos);
                       CRC:=addCRC(rx_char,CRC);
                       case (rx_char) of
                        1: begin            //response
                            wait_for:=SBUS_RX_Data;
                           end;
                        2: begin            //ack
                            expCnt:=2+2;
                            wait_for:=SBUS_RX_Data;
                           end;
                        else wait_for:=SBUS_RX_Sync;
                       end;
                      end;
      SBUS_RX_Data: begin
                     if (expCnt<=2) then inCRC:=TRUE;
                     if (rx_char<>$c5) then begin
                      if huntMode then begin
                       case rx_char of
                        $00: BuffOut[FramePos]:=$b5;
                        $01: BuffOut[FramePos]:=$c5;
                        else begin//error in data stream
                              result:=GFR_Crc_Err;
                              break;
                             end;
                       end; //case
                       dec(expCnt);
                       inc(FramePos); huntMode:=FALSE;
                      end else begin
                       dec(expCnt); //ESC char
   	      	       BuffOut[FramePos]:=rx_char; inc(FramePos);
                      end
                     end else huntMode:=TRUE;

                     if inCRC then begin
                      if not huntMode then CRC:=addCRC(BuffOut[FramePos-1],CRC);
                     end else begin
                      CRC:=addCRC(rx_char,CRC);
                     end;

                     if (expCnt=0) then begin
		      if CRC <> $0000 then begin
                       result:=GFR_Crc_Err;
                       break;
                      end;
 	              wait_for:=SBUS_RX_Sync;
                      result:=GFR_OK;
                      break;
                     end;
                    end;

	  end; //end switch
    inc(i);
  end; //while
 end;


function ComGetResponse(comPort:TcomPort;G:stGate;RespBuff:PByteArray):integer;stdcall;
var
 len,lenx:integer;
 Pos,RecCnt,no_rx,got:BYTE;
 BuffIn: array [0..255] of BYTE;
 stat,CRC:WORD;
 Events:TComEvents;
 huntMode:boolean;
begin
 try
   Pos:=0;
   no_rx:=g.RXTimeout;   //in 20ms increments, wait for first rx char
   stat:= GFR_Wait;
   RecCnt:=G.ReplySize+2;//include CRC
   G.wait_for:=SBUS_RX_Sync;
   repeat
     Events:=[evRxChar];
     comPort.WaitForEvent(Events,20);
     if (Events=[evRxChar]) then begin
        len:=comPort.InputCount();
        no_rx:=SBUS_MAX_INTRAFRAME_BREAK; //reload timer, allow short break in transmission

        while (len>0) do begin
         if len>255 then lenx:=255 else lenx:=len; // don't overflow
         len:=len-lenx;
         got:=comPort.Read(BuffIn,lenx);
{$ifdef DUMP_DATA}
         dumpData(@BuffIn,got,DD_DEBUG);
{$endif}
         stat:=SBUSGetFrame(RecCnt,RespBuff, Pos, @BuffIn, got,CRC,huntMode,G.wait_For);
        end;

      end else dec(no_rx);
    until ((stat=GFR_OK) or (stat=GFR_Crc_Err) or (no_rx=0));

   if (no_rx=0) then stat:=GFR_TimeOut;
{$ifdef DUMP_DATA}
  if (stat=GFR_Crc_Err) then dumpData(RespBuff,Pos,DD_ERROR)
   else if (stat=GFR_OK) then dumpData(RespBuff,Pos,DD_RD)
    else if (stat=GFR_TimeOut) then dumpData(RespBuff,Pos,DD_TOUT);
{$endif}
  if (RespBuff[1]=$02) and (RespBuff[3]=$01) then stat:= GFR_COMMAND_REJECTED;
  result:= stat;
 except
  on EComPort  do result:=  GFR_COM_READ_ERROR;
 end;
end;


function SBUSPut(comPort:TcomPort;var G:stGate;RespBuff:PByteArray):WORD;stdcall;
var
 RetryCnt:integer;
 stat:WORD;
begin
  if comPort.Connected then begin
   RetryCnt:=SBUS_RETRY_CNT;
   stat:=GFR_COM_ERROR;
   repeat
    dec(RetryCnt);
    try
     comPort.clearbuffer(TRUE,TRUE);
    except
     on EComPort do begin
                  stat:= GFR_COM_CLEAR_ERROR;
                  break;
                 end;
    end;
    if not ComMakeQuery(comPort,G) then begin
     stat:= GFR_COM_WRITE_ERROR;
     break;
    end;
    stat:=ComGetResponse(comPort,G,RespBuff);
{$ifdef DUMP_DATA}
    if (stat<>GFR_OK) then dumpData(nil,1,DD_RETRY);
{$endif}
   until ((stat=GFR_OK) or (stat=GFR_COMMAND_REJECTED) or (RetryCnt=0));
   if ((RetryCnt=0) and (stat<>GFR_OK) and (stat<>GFR_COMMAND_REJECTED)) then stat:=GFR_TimeOut;
  end else stat:= GFR_COM_PORT_CLOSED;
  result:=stat;
end;

export
      intI2intM,
      SBUS_CountCRC16,
      addCRC,
      SBUSSendFrame,
      ComMakeQuery,
      SBUSGetFrame,
      ComGetResponse;
//{$R *.RES}


begin
end.

bledy wyskakuja takie :
[Error] Project2.dpr(400): Not enough actual parameters //////dotyczy tej linii comPort.WaitForEvent(Events,20);
[Error] Project2.dpr(464): Declaration expected but identifier 'export' found //dotyczy wiadomo jakiej linii
export

co jest nie tak jesli mozna wiedzieć??

0

Kurde, takie pytanie, da ktoś rade to przerobić na DLL, bo jak próbuje tłumaczyć to to się załamuję :(?/
Proszę pomóżcie....

0

[Error] Project2.dpr(400): Not enough actual parameters //////dotyczy tej linii

comPort.WaitForEvent(Events,20);

Ja przy kompilacji miałem więcej błędów, prawdopodobnie wynikłych z niekompatybilnej wersji komponentu TComPort. Przydałaby się działająca wersja tej biblioteki (chociaż informacja, z jaką wersją komponentu należy to kompilować).

Declaration expected but identifier 'export' found

export

Literówka.

da ktoś rade to przerobić na DLL, bo jak próbuje tłumaczyć to to się załamuję
Chętnie, o ile uda się skompilować oryginalny, niezmieniony moduł. A na razie to nie idzie.

0

ja zrobilem coś takiego :) Jako drugi parametr podałem 1, bo przyjmuje int, znalazlem gdzies w dokumentacji :) i mi utworzyło plik .dll . Pytania teraz mam dwa :)

  1. jezeli stworzylo plik dll to oznacza ze zrobilo plik poprawnie i bede mogl na nim operowac??
  2. Jak odnosic się do stałych zawartych w pliku DLL, bo program który pisze ma je zawierac np
procedure TForm1.Button2Click(Sender: TObject);
var
 g:stGate;
 RespBuff:array[0..255] of BYTE;
 s:string;
 i:integer;
 res:WORD;
begin
 g.RXTimeout := rxspinedit6.AsInteger;
 g.Station := rxspinedit5.AsInteger;
 g.Count := rxspinedit1.asinteger;
 if combobox1.ItemIndex = 0 then begin //-- Read DATA_BLOCK
  g.Func := SBUS_READ_DATA_BLOCK;
  g.DBNumber := rxspinedit2.AsInteger;
  g.DBElement := rxspinedit3.AsInteger;
 end else begin  //------------------------ Read Register
  g.Func := SBUS_READ_REGISTER;
  g.Address := rxspinedit2.AsInteger;
 end;

 res:= SBUSPut(ComPort1,g,@RespBuff);

 case res of
  GFR_OK: //------------------------
   begin
    for i:=2 to g.ReplySize + 2 - 1 do s:= s + inttohex(RespBuff[i],2) +'.';
    memo1.Lines.SetText(PChar(s));
   end; //GFR_OK
  GFR_TIMEOUT://--------------------
    memo1.Lines.SetText('TIMEOUT');
  GFR_COMMAND_REJECTED://--------------------
    memo1.Lines.SetText('COMMAND_REJECTED');
  GFR_COM_PORT_CLOSED :
    memo1.Lines.SetText('COM PORT IS NOT OPENED');
  else
    memo1.Lines.SetText('COM PORT ERROR');
 end; //case
end;

To jest część kod w delphi, ktory tlumacze na C++ a w nim stale bedace zadeklarowane w dll

0

zapomnialem dodac, o co chodzilo z tym drugim parametrem
comPort.WaitForEvent(Events,20);
zamienilem na
comPort.WaitForEvent(Events,1,20);

0
Bartek85 napisał(a)

Aha, mam pytanie, o co chodzi z ustawianiem konwencji, bo nie bardzo rozumiem (pierwszy raz spotykam sie z tą definicją, poza Konwencją Genewską :P) ? ?

Różne języki programowania mają różną kolejność przekazywania parametrów do procedur i funkcji w dll. Ta kolejność musi być taka sama w definicji źródła które idzie do dll i w deklaracji w programie tych procedur zadeklarowanych jako external. Jeśli się tego nie zrobi, procedura dostanie niewłaściwe dane i będą błędy, może nawet trudne do wykrycia. Najczęściej stosuje się uniwersalny dodatek na końcu deklaracji procedury "stdcall". Należy go dodać do nagłówków procedur unitu w Delphi a w programie w języku C gdzie deklarujemy te procedury jako "external" trzeba też dać ten sam dodatek na końcu tych deklaracji.

I procedury które idą do dll zdaje się nie mogą mieć parametrów typu "string", więc trzeba je zamienić na PChar co może się wiązać z potrzebą zmiany kodu tych procedur, jeśli wcześniej używały one typu string, który był przekazywany bez konwersji typu jako parametr tych procedur.

0
  1. jezeli stworzylo plik dll to oznacza ze zrobilo plik poprawnie i bede mogl na nim operowac??
    To się okaże...
  1. Jak odnosic się do stałych zawartych w pliku DLL
    Tak samo jak do funkcji. Muszą być w "exports".
library a;

var i:longint;

exports i;

end.
0
library sbus;

uses cport,sysutils;
const

 {########################## PCD CONSTANTS ####################################}

 PCD_HISTORY_TIME_SHIFT = $3f000000; // time field of history record from PCD has this shift

 {###### PCD COMMANDS CODES #####}
 PCD_CMD_SET_TIME             = 1; //unconditional set time
 PCD_CMD_GET_ERRORS           = 3;
 PCD_CMD_DELETE_ERRORS        = 4;
 PCD_CMD_SYNC_TIME            = 5;
 PCD_CMD_SET_SYNC_TIME_MODE   = 6;

 PCD_CMD_SET_SYNC_TIME_MODE_0 = 0;  //time sync disabled
 PCD_CMD_SET_SYNC_TIME_MODE_1 = 1; //pulse on PCD input
 PCD_CMD_SET_SYNC_TIME_MODE_2 = 2; //SBUS command

 PCD_CMD_GET_HDATA       = 9;
 PCD_CMD_DELETE_HDATA    = 10;
 PCD_CMD_ERASE_ALL_DATA  = 11;
 PCD_CMD_GET_ACTDIGDATA  = 12;
 PCD_CMD_GET_ACTANADATA  = 13;
 PCD_CMD_GET_ACTANADATA2 = 14;
 PCD_CMD_GET_ACTANADATA3 = 15;
 //PCD configuration constants
 PCD_CONF_INT = 5;  //small data scan interval value in [s]

 //addresses of registers in PCD
 PCD_CMD_REG       = 3325;
 PCD_CMD_ACK_REG   = 3324;
 PCD_CMD_DATA_BASE = 3326;

 PCD_TIME_REG = 1;

 PCD_CONF_BASE = 100;    //base address of configuration data
 PCD_CONF_DIGCNTRS_BASE = PCD_CONF_BASE;
 PCD_CONF_ANAL_BASE = PCD_CONF_DIGCNTRS_BASE + 1025;
 PCD_CONF_DIGINPUTS_BASE = PCD_CONF_ANAL_BASE +1025;
 PCD_DATA_OFFSET = 3;

 //offsets from base PCD_CONF_BASE
 PCD_CONF_ADDR = 0;
 PCD_CONF_INTS = 2;
 PCD_CONF_INTB = 1;
 PCD_CONF_DESC1= 12;
 PCD_CONF_DESC2= 13;
 PCD_CONF_DESC3= 14;
 PCD_CONF_DESC4= 15;

 PCD_CONF_MASK = 1; //mask for digital inputs

 //base PCD_CONF_BASE + PCD_DATA_OFFSET
 //for digital counters
 PCD_DATA_PULSES_S = 1;
 PCD_DATA_PULSES_B = 0;
 //for analog inputs
 PCD_DATA_A_VAL    = 1;
 PCD_DATA_A_AVG    = 0;
 PCD_DATA_A_MIN_A  = 2;
 PCD_DATA_A_MAX_A  = 3;
 PCD_DATA_A_MIN_P  = 4;
 PCD_DATA_A_MAX_P  = 5;

{########################## SBUS CONSTANTS ####################################}

 SBUS_RETRY_CNT            = 3;  //number of retransmission retries
 SBUS_MAX_INTRAFRAME_BREAK = 5;  //maximum break length in the middle of the frame
 //SBUS functions CODES
 SBUS_READ_DATA_BLOCK  = $96;
 SBUS_READ_REGISTER    = $06;
 SBUS_WRITE_REGISTER   = $0E;

 //getFrame results
 GFR_TIMEOUT          = $8000; //transmission timeout
 GFR_CRC_ERR          = $8001;
 GFR_RETRY            = $8002;
 GFR_COM_PORT_CLOSED  = $8003;
 GFR_COM_WRITE_ERROR  = $8004;
 GFR_COM_CLEAR_ERROR  = $8005;
 GFR_COM_ERROR        = $8006;
 GFR_COM_READ_ERROR   = $8004;
 GFR_OK               = $0001; //command executed OK
 GFR_COMMAND_REJECTED = $0002; //transmission OK, command rejected by PCD
 GFR_WAIT             = $0003;

 //DUMP_DATA params
 DD_WR        = 1; //dump WRITE-to-COM data
 DD_RD        = 2;
 DD_ERROR     = 3;
 DD_DEBUG     = 4; //dump data readen from COM
 DD_RETRY     = 5;
 DD_TOUT      = 6;

 //single gate structure
type
stGate = record
  Station:BYTE;        // station number
  Func:BYTE;           // READ_REGISTER etc.
  Address:WORD;        // of register/data block
  DBNumber:WORD;       // DATABLOCK commands
  DBElement:WORD;
  Count:WORD;          // no of elements (base 1)
  RXTimeout:integer;   // timeout for first rx char in 20 ms units
  value:array [0..31] of integer; //output data
    //internal data
  wait_for: BYTE ;
  ReplySize:WORD;      // expected reply size
end;

{**************************************************************************
* PUT SBUS COMMAND
* ========================
* INPUT -> comPort - properly opened serial port
*                G - properly filled command structure
*         respBuff - buffer for incoming reply
* OUTPUT -> result code one of:
*           GFR_TIMEOUT , GFR_OK , GFR_COMMAND_REJECTED
*           GFR_COM_WRITE_ERROR , GFR_COM_CLEAR_ERROR , GFR_COM_READ_ERROR
***************************************************************************}
//function SBUSPut(comPort:TcomPort;var G:stGate;RespBuff:PByteArray):WORD;

{**************************************************************************
* CONVERT INTEL TO MOTOROLA ENDIAN (AND VICE VERSA)
***************************************************************************}
//function intI2intM(intel:integer):longword;

//###############################################################################


const
 SBUS_RX_Sync    =0;
 SBUS_RX_Attrib  =1;
 SBUS_RX_Data    =2;


function intI2intM(intel:integer):longword;stdcall;
var
 x:longword;
begin
 x:=intel;
 intel:= (x shr 24) or (x shl 24) or ((x and $00FF0000) shr 8) or ((x and $0000FF00) shl 8);
 result:=intel;
end;

//calculate CRC en-block
function SBUS_CountCRC16(Buff: PByteArray ;DataLen: BYTE) : WORD ; stdcall;
var
 CRC: WORD;
 i,j: BYTE;
begin
 CRC:=0;
 j:=0;
while j<DataLen do begin
 CRC := CRC xor WORD(Buff[j] shl 8);
 inc(j);
 for i:=0 to 7 do begin
  if (CRC and $8000) = $8000 then CRC:= (CRC shl 1) xor $1021
   else CRC:= (CRC shl 1);
 end;
end;
//swap bytes to motorola
result:= ((CRC shl 8)and $ffff) or (CRC shr 8);
end;


//crc calculation byte by byte
function addCRC(b:BYTE;CRC:WORD):WORD;stdcall;
var
 i:integer;
begin
 CRC := CRC xor WORD(b shl 8);
 for i:=0 to 7 do begin
  if (CRC and $8000) = $8000 then CRC:= (CRC shl 1) xor $1021
   else CRC:= (CRC shl 1);
 end;
 result:=CRC;
end;


function SBUSSendFrame(comPort:TcomPort; buffer:PByteArray; message_length:BYTE):boolean ;stdcall;
var
  i:BYTE ;
  Buff:array [0..255] of BYTE;
  pBuff,pCRC:^BYTE;
  buff_len:BYTE;
  CRC:WORD;
begin
  result:=true;
  buff_len:=2;    //for $B5 $00
  pBuff:=@Buff;
  pBuff^:=$b5; inc(pBuff);
  pBuff^:=$00; inc(pBuff);   //telegram

  buff_len:=buff_len + message_length;

   for i:=0 to message_length-1 do
    begin
     case buffer[i] of
       $b5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$00; inc(pBuff);
             inc(buff_len);
            end;
       $c5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$01; inc(pBuff);
             inc(buff_len);
            end;
       else begin
             pBuff^:=buffer[i]; inc(pBuff);
            end;
     end;
    end;

  CRC:=SBUS_CountCRC16(@Buff,buff_len); //calculate CRC from encoded message

  pCRC:=@CRC;
  for i:=0 to 1 do begin//encode CRC itself too
   case pCRC^ of
       $b5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$00; inc(pBuff);
             buff_len:=buff_len+2;
            end;
       $c5: begin
             pBuff^:=$c5; inc(pBuff);
             pBuff^:=$01; inc(pBuff);
             buff_len:=buff_len+2;
            end;
       else begin
             pBuff^:=pCRC^; inc(pBuff);
             inc(buff_len);
            end;
   end; //case
   inc(pCRC);
  end;
  try
   comPort.Write(Buff,buff_len);  // Send it out...
  except
   on EComPort do result:=false;
  end;
{$ifdef DUMP_DATA}
  dumpData(@Buff,buff_len,DD_WR);
{$endif}
end;


function ComMakeQuery(comPort:TcomPort;var G:stGate):boolean;stdcall;
var
 Frame:array [0..255] of BYTE;
 toSend:integer;
begin
    toSend:=0; //for unknown commands
    Frame[0]:=G.Station;
    Frame[1]:=G.Func;                //Command

    case G.Func of
     SBUS_READ_DATA_BLOCK :
      begin
       toSend:=7;
       Frame[2]:=G.count-1;
       Frame[3]:=BYTE(G.DBNumber shr 8);
       Frame[4]:=BYTE(G.DBNumber);
       Frame[5]:=BYTE(G.DBElement shr 8);
       Frame[6]:=BYTE(G.DBElement);
       G.ReplySize:= (G.count)*4;
      end;
     SBUS_READ_REGISTER:
      begin
       toSend:=5;
       Frame[2]:=G.count-1;
       Frame[3]:=BYTE(G.Address shr 8);
       Frame[4]:=BYTE(G.Address);
       G.ReplySize:= (G.count)*4;
      end;
     SBUS_WRITE_REGISTER:
      begin
       Frame[2]:=G.count*4+1;
       toSend:=5+(g.count*4);
       Frame[3]:=BYTE(G.Address shr 8);
       Frame[4]:=BYTE(G.Address);
       move(G.value[0],Frame[5],g.count*4);
       G.ReplySize:= 2;
      end;
     end; //case
    result:=SBUSSendFrame(comPort, @Frame,toSend);
end;


//---------------------------------------------------------------------------
// expCnt -   expected answer length
// nReceived - length of received chars buffer
function SBUSGetFrame(var expCnt:BYTE; BuffOut:PByteArray ;var FramePos: BYTE ;
                      BuffIn:PBYTEArray ;nReceived :BYTE; var CRC:WORD;
                      var huntMode:boolean;var wait_for:BYTE): integer; stdcall;
var
 i,rx_char:BYTE;
 inCRC:boolean;
begin
 i:=0;
 inCRC:=false;
 result:=GFR_Wait;

 while(i<nReceived) do begin
  rx_char:=BuffIn[i];

  case (wait_for) of
      SBUS_RX_Sync: begin
                       if (rx_char=$b5) then begin
                            FramePos:=0; CRC:=0; huntMode:= FALSE;
                      CRC:=addCRC(rx_char,CRC);
                            BuffOut[FramePos]:=rx_char; inc(FramePos);
                        wait_for:=SBUS_RX_Attrib;
                     end;
                      end;
      SBUS_RX_Attrib: begin
                             BuffOut[FramePos]:=rx_char; inc(FramePos);
                       CRC:=addCRC(rx_char,CRC);
                       case (rx_char) of
                        1: begin            //response
                            wait_for:=SBUS_RX_Data;
                           end;
                        2: begin            //ack
                            expCnt:=2+2;
                            wait_for:=SBUS_RX_Data;
                           end;
                        else wait_for:=SBUS_RX_Sync;
                       end;
                      end;
      SBUS_RX_Data: begin
                     if (expCnt<=2) then inCRC:=TRUE;
                     if (rx_char<>$c5) then begin
                      if huntMode then begin
                       case rx_char of
                        $00: BuffOut[FramePos]:=$b5;
                        $01: BuffOut[FramePos]:=$c5;
                        else begin//error in data stream
                              result:=GFR_Crc_Err;
                              break;
                             end;
                       end; //case
                       dec(expCnt);
                       inc(FramePos); huntMode:=FALSE;
                      end else begin
                       dec(expCnt); //ESC char
                                BuffOut[FramePos]:=rx_char; inc(FramePos);
                      end
                     end else huntMode:=TRUE;

                     if inCRC then begin
                      if not huntMode then CRC:=addCRC(BuffOut[FramePos-1],CRC);
                     end else begin
                      CRC:=addCRC(rx_char,CRC);
                     end;

                     if (expCnt=0) then begin
                      if CRC <> $0000 then begin
                       result:=GFR_Crc_Err;
                       break;
                      end;
                       wait_for:=SBUS_RX_Sync;
                      result:=GFR_OK;
                      break;
                     end;
                    end;

          end; //end switch
    inc(i);
  end; //while
 end;


function ComGetResponse(comPort:TcomPort;G:stGate;RespBuff:PByteArray):integer;stdcall;
var
 len,lenx:integer;
 Pos,RecCnt,no_rx,got:BYTE;
 BuffIn: array [0..255] of BYTE;
 stat,CRC:WORD;
 Events:TComEvents;
 huntMode:boolean;
begin
 try
   Pos:=0;
   no_rx:=g.RXTimeout;   //in 20ms increments, wait for first rx char
   stat:= GFR_Wait;
   RecCnt:=G.ReplySize+2;//include CRC
   G.wait_for:=SBUS_RX_Sync;
   repeat
     Events:=[evRxChar];
     comPort.WaitForEvent(Events,0,20);
     if (Events=[evRxChar]) then begin
        len:=comPort.InputCount();
        no_rx:=SBUS_MAX_INTRAFRAME_BREAK; //reload timer, allow short break in transmission

        while (len>0) do begin
         if len>255 then lenx:=255 else lenx:=len; // don't overflow
         len:=len-lenx;
         got:=comPort.Read(BuffIn,lenx);
{$ifdef DUMP_DATA}
         dumpData(@BuffIn,got,DD_DEBUG);
{$endif}
         stat:=SBUSGetFrame(RecCnt,RespBuff, Pos, @BuffIn, got,CRC,huntMode,G.wait_For);
        end;

      end else dec(no_rx);
    until ((stat=GFR_OK) or (stat=GFR_Crc_Err) or (no_rx=0));

   if (no_rx=0) then stat:=GFR_TimeOut;
{$ifdef DUMP_DATA}
  if (stat=GFR_Crc_Err) then dumpData(RespBuff,Pos,DD_ERROR)
   else if (stat=GFR_OK) then dumpData(RespBuff,Pos,DD_RD)
    else if (stat=GFR_TimeOut) then dumpData(RespBuff,Pos,DD_TOUT);
{$endif}
  if (RespBuff[1]=$02) and (RespBuff[3]=$01) then stat:= GFR_COMMAND_REJECTED;
  result:= stat;
 except
  on EComPort  do result:=  GFR_COM_READ_ERROR;
 end;
end;


function SBUSPut(comPort:TcomPort;var G:stGate;RespBuff:PByteArray):WORD;stdcall;
var
 RetryCnt:integer;
 stat:WORD;
begin
  if comPort.Connected then begin
   RetryCnt:=SBUS_RETRY_CNT;
   stat:=GFR_COM_ERROR;
   repeat
    dec(RetryCnt);
    try
     comPort.clearbuffer(TRUE,TRUE);
    except
     on EComPort do begin
                  stat:= GFR_COM_CLEAR_ERROR;
                  break;
                 end;
    end;
    if not ComMakeQuery(comPort,G) then begin
     stat:= GFR_COM_WRITE_ERROR;
     break;
    end;
    stat:=ComGetResponse(comPort,G,RespBuff);
{$ifdef DUMP_DATA}
    if (stat<>GFR_OK) then dumpData(nil,1,DD_RETRY);
{$endif}
   until ((stat=GFR_OK) or (stat=GFR_COMMAND_REJECTED) or (RetryCnt=0));
   if ((RetryCnt=0) and (stat<>GFR_OK) and (stat<>GFR_COMMAND_REJECTED)) then stat:=GFR_TimeOut;
  end else stat:= GFR_COM_PORT_CLOSED;
  result:=stat;
end;

exports
      intI2intM,
      SBUS_CountCRC16,
      addCRC,
      SBUSSendFrame,
      ComMakeQuery,
      SBUSGetFrame,
      ComGetResponse,
      PCD_CMD_SET_TIME,
      PCD_CMD_GET_ERRORS,
      PCD_CMD_DELETE_ERRORS,
      PCD_CMD_SYNC_TIME,
      PCD_CMD_SET_SYNC_TIME_MODE,

      PCD_CMD_SET_SYNC_TIME_MODE_0,
      PCD_CMD_SET_SYNC_TIME_MODE_1,
      PCD_CMD_SET_SYNC_TIME_MODE_2,

      PCD_CMD_GET_HDATA,
      PCD_CMD_DELETE_HDATA,
      PCD_CMD_ERASE_ALL_DATA,
      PCD_CMD_GET_ACTDIGDATA,
      PCD_CMD_GET_ACTANADATA,
      PCD_CMD_GET_ACTANADATA2,
      PCD_CMD_GET_ACTANADATA3,
      //PCD configuration constants
      PCD_CONF_INT,  //small data scan interval value in [s]

      //addresses of registers in PCD
      PCD_CMD_REG,
      PCD_CMD_ACK_REG,
      PCD_CMD_DATA_BASE,

      PCD_TIME_REG,

      PCD_CONF_BASE,  //base address of configuration data
      PCD_CONF_DIGCNTRS_BASE,
      PCD_CONF_ANAL_BASE,
      PCD_CONF_DIGINPUTS_BASE,
      PCD_DATA_OFFSET,

      //offsets from base PCD_CONF_BASE
      PCD_CONF_ADDR,
      PCD_CONF_INTS,
      PCD_CONF_INTB,
      PCD_CONF_DESC1,
      PCD_CONF_DESC2,
      PCD_CONF_DESC3,
      PCD_CONF_DESC4,

      PCD_CONF_MASK, //mask for digital inputs

      //base PCD_CONF_BASE + PCD_DATA_OFFSET
      //for digital counters
      PCD_DATA_PULSES_S,
      PCD_DATA_PULSES_B,
      //for analog inputs
      PCD_DATA_A_VAL,
      PCD_DATA_A_AVG,
      PCD_DATA_A_MIN_A,
      PCD_DATA_A_MAX_A,
      PCD_DATA_A_MIN_P,
      PCD_DATA_A_MAX_P,

      {########################## SBUS CONSTANTS ####################################}

      SBUS_RETRY_CNT,  //number of retransmission retries
      SBUS_MAX_INTRAFRAME_BREAK,  //maximum break length in the middle of the frame
      //SBUS functions CODES
      SBUS_READ_DATA_BLOCK,
      SBUS_READ_REGISTER,
      SBUS_WRITE_REGISTER,

      //getFrame results
      GFR_TIMEOUT, //transmission timeout
      GFR_CRC_ERR,
      GFR_RETRY,
      GFR_COM_PORT_CLOSED,
      GFR_COM_WRITE_ERROR,
      GFR_COM_CLEAR_ERROR,
      GFR_COM_ERROR,
      GFR_COM_READ_ERROR,
      GFR_OK, //command executed OK
      GFR_COMMAND_REJECTED, //transmission OK, command rejected by PCD
      GFR_WAIT,

      //DUMP_DATA params
      DD_WR, //dump WRITE-to-COM data
      DD_RD,
      DD_DEBUG, //dump data readen from COM
      DD_RETRY,
      DD_TOUT,
      SBUS_RX_Sync,
      SBUS_RX_Attrib,
      SBUS_RX_Data,
      //single gate structure
      stGate;
//{$R *.RES}


begin
end.

Dobra, pytanie moje jest teraz takie, dlaczego sapie o stGate, oraz czy teraz bede miec dostep do "zmiennych" stalych ( bo const wszystkie). Aha, jeszcze jedno, czy to wydaje sie byc napisane poprawnie i jak w c++ odwołać sie do zmiennych i funkcji tu zawartych?/
Widze, że problem dobiega do końca co mnie bardzo cieszy i dziękuje za okazana pomoc :) [soczek]

0

Jaki jest odpowiednik tego w C++??, klasa, tak? Aha, i jeszcze jedno....jak wysylac bede z tej klasy z C++ do funkcji DLL napisanej w Delphi wykorzystującej typ poniżej to czy będzie poprawnie działać??

type
stGate = record
  Station:BYTE;        // station number
  Func:BYTE;           // READ_REGISTER etc.
  Address:WORD;        // of register/data block
  DBNumber:WORD;       // DATABLOCK commands
  DBElement:WORD;
  Count:WORD;          // no of elements (base 1)
  RXTimeout:integer;   // timeout for first rx char in 20 ms units
  value:array [0..31] of integer; //output data
    //internal data
  wait_for: BYTE ;
  ReplySize:WORD;      // expected reply size
end;
0

Ahh.. nie, stałych (const) nie eksportuj, tylko przepisz je do C++.

tak na szybko:

struct stGate {
  BYTE Station; // unsigned char
  BYTE Func;
  WORD Address;  // unsigned short
  WORD DBNumber;
  WORD DBElement;
  WORD Count;
  int RXTimeout;
  int value[32];
  BYTE wait_for;
  WORD ReplySize;
};

ale trzeba by porównać sizeof() w obu językach, bo może być różnica w wyrównaniu elementów (alignment)

0

OK, spoko ;) A teraz jeszcze ostatnie małe pytanie juz......zmienna typu BYTE jest w C++?? Bo pierwszy raz widze ;P Ale jesli chodzi o reszte to dziekuje za pomoc i na pewno mi sie teraz uda:)

0

jak dodasz #include <windows.h> to będzie.
to to samo co unsigned char.

0

aaaa, super :) Dobra, to biore sie do pracy :) Dzieki za pomoc, niedlugo napisze czy wszystko sie udalo :)

Dziekuje bardzo za okazana pomoc i poswiecony czas :)

Jeszcze jedno pytanie, tak na koniec, a wlasciwie dwa ;) Czego stosowac w obecnych czasach?? Visual Studiu czy moze Embarcadero CodeGear Rad Studio ( czy jakos tak sie nazywa)???
I drugie pytanie wiąże się z tym lepszym programem, a mianowicie chodzi o jakis dobry poradnik, bo w necie jest duzo, ale porozrzucane jak nie wiem co....

0

Przepraszam, ale przypomnial mi sie jeszczce jeden maly problem....
mianowicie, korzystam z "Klasy TStringList" do operacji na plikach i chce usunac np taki tekst

cos tam, cos tam
cos tam1, cos tam 2
cos tam3, cos tam4

I po usunieciu np lini drugiej kursor zostaje zostawiony na poczatku lini trzeciej, a chcialbym zeby byl na koncu drugiej. Jak probowalem wstawic BACKSPACE to w trzeciej lini wstawia mi jakis kwadracik, a kursor ustawia na poczatku czwartej linii. Jak temu zaradzic???

0

Visual Studiu czy moze Embarcadero
a czego chcesz... ;-) właśnie co wyszła nowa wersja Delphi/C++ XE.

Problemu z TStringList nie rozumiem. Ale to raczej temat na osobny wątek.

0

Dziekuje wszystkim za okazana pomoc :)
Pozdrawiam

0

Jesli mozna, to chcialem jeszcze prosic o przetlumaczenie czegos takiego, mozliwie szybko
function SBUSPut(comPort:TcomPort;var G:stGate;RespBuff:PByteArray):WORD;

przetlumaczylem to na:
WORD SBUSPut(TcomPort comPort , stGate G , PByteArray RespBuff);
ale wyskakuje mi taki blad

[BCC32 Error] Unit1.cpp(145): E2147 'TcomPort' cannot start a parameter declaration

0

i jesli mozna od razu to.....try
comPort.Write(Buff,buff_len); // Send it out...
except
on EComPort do result:=false;
end;
{$ifdef DUMP_DATA}
dumpData(@Buff,buff_len,DD_WR);
{$endif}

1 użytkowników online, w tym zalogowanych: 0, gości: 1