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

📄 frame.c

📁 SPC3 SETUP PROGRAMS SP C3 SETUP PROGRAMS
💻 C
字号:
//-----------------------------------------------------------------------------
// $Id: frame.c,v 1.0.0                                             2004/01/13
//-----------------------------------------------------------------------------
//
//      ProfiM - PROFIBUS MASTER DRIVER FOR WINDOWS NT/2000
//
// Author:  
//      Pavel Trnka, CTU FEE
//      trnkap@seznam.cz
// With help and advices from:
//      Ing. Petr Smolik, CTU FEE
//      Ing. Pavel Pisa, CTU FEE
//      Ing. Pavel Burget, CTU FEE
//
//-----------------------------------------------------------------------------
//
// Popis:
// ------
//   Funkce pro praci s ramci sbernice Profibus.
//
//
// Funkce volane z vnejsku:
// ---------------------------
//
//   PBFrame_DecodeFrame - urci typ ramce a dekoduje jej do jednotlivych
//               promennych
//   PBFrame_FindFrame   - hleda vyskyt platneho ramce v bufferu a jako
//               vysledek vraci jeho polohu a delku
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

#include "NTDDK.H"

#include "vardef.h"
#include "frame.h"

//*****************************************************************************

void PBFrame_Init( PTPBFrame PBF )
{
  PBF->Valid = FALSE;
}


//*****************************************************************************
//**  Urci typ ramce a dekoduje jej do promennych struktury
//**
//*****************************************************************************

// POZOR - Indexy do Stringu zacinaji na jednicce, nikoliv na nule!

void PBFrame_DecodeFrame( PTPBFrame PBF,
                          PUCHAR frame,
                          int FrameLen,
                          int TS,
                          int DefaultSAP )
{
  int i;
  int data_pos  = 0; // ukazatel na pocatek dat ve framu - posune se pokud ma frame Address Extension        

  frame = frame - 1; // puvodne pouzivany String preveden na pole UCHAR (indexace se lisi o jednicku)                   

  PBF->Valid = FALSE;             

  //!!   String  frame=_frame+ AnsiString::StringOfChar('\x00', 30); // doplneni delky pro moznost primeho testovani znaku bez chyby - out of range
  //!! Nutno zajistit dostatecne dlouhy buffer  

  PBF->DA = frame[2];    // pokud je frame SD2 tak se jeste zmeni
  PBF->SA = frame[3];

  // delky uz by nemelo byt potreba kontrolovat

  if ( frame[1] == DelimiterSD4 && FrameLen >= 3 )                 // Token
  {
    PBF->FrameType = FT_Token;
    PBF->Data_length = 0;
    PBF->Valid = TRUE;
    return; /* !! */
  }


  if ( frame[1] == DelimiterSC && FrameLen >= 1 )                 // Short Acknowledge
  {
    PBF->FrameType = FT_ShortAcknowledge;
    PBF->Data_length = 0;
    PBF->Valid = TRUE;
    PBF->ACK = ACK_OK; //muzu u Short Acknowledge ?
    return; /* !! */
  }



  if ( frame[1] == DelimiterSD1 )                                      // Fixed length frame with NO data field
  {
    PBF->FC = frame[4];
    PBF->FCS = frame[5];
    PBF->ED = frame[6];
    PBF->Data_length = 0;
    // jeste pridat test na FCS (ED uz otestovan)
    PBF->Valid = TRUE;
  }


  if ( frame[1] == DelimiterSD3 )                                      // Fixed length frame WITH Data field
  {
    PBF->FC = frame[4];
    PBF->FCS = frame[13];
    PBF->ED = frame[14];

    data_pos = 5;
    PBF->Data_length = 8;

    //vycucnout data - az nakonec - jeste je treba zjistit offset pokud je Address Extension

    PBF->Valid = TRUE;
  }

  if ( frame[1] == DelimiterSD2 )                                      // Variable length frame WITH Data field
  {
    PBF->LE = frame[2];
    PBF->LEr = frame[3];

    if ( PBF->LE == PBF->LEr && PBF->LE >= 4 && frame[4] == DelimiterSD2 )
    {
      PBF->DA = frame[5];
      PBF->SA = frame[6];
      PBF->FC = frame[7];

      data_pos = 8;
      PBF->Data_length = PBF->LE - 3; // snad OK?

      //vycucnout data - az nakonec - jeste je treba zjistit offset pokud je Address Extension

      PBF->Valid = TRUE;
    }
  }

  if ( ( PBF->DA & 0x7F ) == BROADCAST )
    PBF->DA = (UBYTE) TS;  // zpusob jak vyresit prijem broadcastu

  //pokud nema frame SAPy tak nastavi defaultni
  PBF->DSAP = (UBYTE) DefaultSAP;
  PBF->SSAP = (UBYTE) DefaultSAP;
  if ( frame[1] == DelimiterSD2 || frame[1] == DelimiterSD3 )   // dekodovani Address Extension
  {
    if ( PBF->DA & 0x80 )
    {
      if ( frame[data_pos] & 0x80 )
      {
        data_pos++; PBF->Data_length--; PBF->DSAP = frame[data_pos];
      }
      else if ( !( frame[data_pos] & 0x40 ) )
        PBF->DSAP = frame[data_pos];
      data_pos++;PBF->Data_length--;
      PBF->DA = PBF->DA & 0x7F;
    }
    if ( PBF->SA & 0x80 )
    {
      if ( frame[data_pos] & 0x80 )
      {
        data_pos++; PBF->Data_length--; PBF->SSAP = frame[data_pos];
      }
      else if ( !( frame[data_pos] & 0x40 ) )
        PBF->SSAP = frame[data_pos];
      data_pos++;PBF->Data_length--;
      PBF->SA = PBF->SA & 0x7F;
    }

    // vycucnuti dat
    for ( i = 0; i < PBF->Data_length; i++ )
      PBF->Data[i] = frame[i + data_pos];  // puvodne bylo Data[i+1], ale ted by to melo byt spravne
  }


  if ( PBF->Valid && ( PBF->ED != DelimiterED /*|| !test CRC*/ ) )
  {
    PBF->Valid = FALSE;
  }


  if ( PBF->Valid )
  {
    /* dekoduj FC apod.*/
    PBF->FC &= 0x7F;       // odriznuti rezervovaneho osmeho bitu - nejspis neni potreba

    if ( PBF->FC & 0x40 )  //  Request, Send/Request Frame
    {
      switch ( ( PBF->FC & 0x0F ) )
      {
        case 4:
          PBF->FrameType = FT_SDNLow; break;
        case 6:
          PBF->FrameType = FT_SDNHigh;  break;                      
        case 9:
          PBF->FrameType = FT_RequestFDLStatuswithReply;  break;
        case 12:
          PBF->FrameType = FT_SRDLow; break;
        case 13:
          PBF->FrameType = FT_SRDHigh;  break;                      
        case 14:
          PBF->FrameType = FT_RequestIdentwithReply;  break;
        case 15:
          PBF->FrameType = FT_RequestLSAPStatuswithReply; break;                                                                  
        default:
          PBF->Valid = FALSE; // TODO - je to OK?
      }
      //if ((PBF->FC & 0x0F)==9) PBF->FrameType=FT_RequestFDLStatuswithReply;
    }
    else            // Acknowledgement, Response Frame
    {
      PBF->FrameType = FT_Reply;
      PBF->ACK = /*TACK*/ PBF->FC & 0x0F;
      PBF->StnType = /*TStationStatus*/ ( PBF->FC & 0x30 ) >> 4 ;
    }
  }
}


//*****************************************************************************
//**  Urci jestli dany retezec obsahuje na zacatku platny ramec (platnost se
//**  urcuje pouze tim jestli zacina platnym Start Delimeterm a konci End
//**  Delimiterem). Urci jak je tento ramec dlouhy (vyhledanim End Delimiteru).
//*****************************************************************************

BOOLEAN PBFrame_FindFrame( PUCHAR buffer, int BufLen, int *length )
{
  buffer = buffer - 1; // puvodne pouzivany String preveden na pole UCHAR (indexace se lisi o jednicku)

  if ( BufLen > 0 )
    if ( buffer[1] == DelimiterSD1 ||
         buffer[1] == DelimiterSD2 ||
         buffer[1] == DelimiterSD3 ||
         buffer[1] == DelimiterSD4 ||
         buffer[1] == DelimiterSC )
    {
      if ( buffer[1] == DelimiterSD1 && BufLen >= 6 )
        if ( buffer[6] == DelimiterED )
        {
          *length = 6; return TRUE;
        }

      if ( buffer[1] == DelimiterSD2 )
      {
        int L, EDpos;
        if ( BufLen >= 2 )
        {
          L = buffer[2];
          EDpos = 4 + L + 2;
          if ( BufLen >= EDpos )
            if ( buffer[EDpos] == DelimiterED )
            {
              *length = EDpos;
              return TRUE;
            }
        }
      } // pozor ED uz muze patrit k jinemu framu pokud je SD2 ramec poruseny

      if ( buffer[1] == DelimiterSD3 && BufLen >= 14 )
        if ( buffer[14] == DelimiterED )
        {
          *length = 14; return TRUE;
        }  // pozor testovani ED na 14 muze byt zradne a znicit napr dobry buffer po spatnem typu SD3

      if ( buffer[1] == DelimiterSD4 && BufLen >= 3 )
      {
        *length = 3; return TRUE;
      }

      if ( buffer[1] == DelimiterSC && BufLen >= 1 )
      {
        *length = 1; return TRUE;
      }
    }

  return FALSE;
}


//*****************************************************************************
//**  Hleda v retezci vyskyt nektereho ze Start Delimiteru. Pri nalezeni vrati
//**  jeho pozici v buffer. Pokud zadny neni nalezen vraci -1.
//**
//*****************************************************************************

int PBFrame_FindStartDelimiter( PUCHAR buffer, int BufLen )
{
  int i;

  buffer = buffer - 1; // puvodne pouzivany String preveden na pole UCHAR (indexace se lisi o jednicku)

  for ( i = 1; i <= BufLen; i++ )
  {
    if ( buffer[i] == DelimiterSD1 ||
         buffer[i] == DelimiterSD2 ||
         buffer[i] == DelimiterSD3 ||
         buffer[i] == DelimiterSD4 ||
         buffer[i] == DelimiterSC )
      return i;
  }
  return -1;
}


//*****************************************************************************
//**  Urci je-li dany znak platnym Start Delimiterem SDx (pro SC vraci take
//**  FALSE ).
//**
//*****************************************************************************

BOOLEAN IsStartDelimiterSDx( char ch )
{
  return ( ch == DelimiterSD1 ||
           ch == DelimiterSD2 ||
           ch == DelimiterSD3 ||
           ch == DelimiterSD4 );
}


/*
//*****************************************************************************
//**  Prevede retezec tvoreny sekvenci hexadecimalnich cisel na retezec bytu,
//**  kde kazdy odpovida jednomu hex. cislu.
//**
//**  format vstupniho retezce "xx xx xx...xx xx xx" napr. "1C CE 46 F2"
//*****************************************************************************

String HexStringToString(String hs)
{
  int     count;
  int     hi,lo,ch;

  if (hs.Length()>=2)
        if ( (hs.Length()-2)%3==0)
        {
                count=(hs.Length()-2)/3 + 1;
                String  s=AnsiString::StringOfChar(' ',count);

                for (int i=0; i<count; i++)
                {
                        ch=hs[i*3+1];
                        if (ch>='0' && ch<='9') hi=ch-'0';
                        if (ch>='a' && ch<='f') hi=ch-'a'+10;
                        if (ch>='A' && ch<='F') hi=ch-'A'+10;
                        ch=hs[i*3+2];
                        if (ch>='0' && ch<='9') lo=ch-'0';
                        if (ch>='a' && ch<='f') lo=ch-'a'+10;
                        if (ch>='A' && ch<='F') lo=ch-'A'+10;

                        s[i+1]=(hi<<4)+lo;
                }
                return s;
        }
  return "";
}


//*****************************************************************************
//**  Prevede data ulozena v retezci (po bytech) na retezec s hexadecimalnim
//**  vypisem dat
//**
//*****************************************************************************

String StringDataToHex(String frame)
{
    String  out="";
    for (int i=1; i<=frame.Length(); i++) out=out+IntToHex( ((unsigned char)(frame[i])) ,2)+" ";
    return out;
}



//*****************************************************************************
// UNSUSED ??

String BuildFrameNoData(int _DA, int _SA, int _FC)
{
  String s=AnsiString::StringOfChar(' ',6);
  s[1]=DelimiterSD1;
  s[2]=_DA;
  s[3]=_SA;
  s[4]=_FC;
  s[5]= (_DA+_SA+_FC)%256 ;
  s[6]=DelimiterED;
  return s;
}
*/
//*****************************************************************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -