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

📄 profibus.c

📁 SPC3 SETUP PROGRAMS SP C3 SETUP PROGRAMS
💻 C
📖 第 1 页 / 共 5 页
字号:
        if ( PB->LastState == Listen_Token )
        {
          PB_DbgPrintL3( "PB: Master %d prijat do logickeho ringu!", PB->TS );
        }

        PB->StationStatus = Master_in_logical_ring;

        /*if (PB->PS == -1) { */
        PB->PS = _SA; 
        LAS_VymazStanice( &PB->LAS, PB->TS, _SA ); /*}*/

        if ( PB->NS == -1 )
        {
          PB->NS = LAS_NextStation( &PB->LAS, PB->TS ); 
          GAPL_UpdateNS( &PB->GAPL, PB->NS );
                                                                     
        }        /*prace s GAPL muze zacit*/


        PB_StopTimeOut( PB );
        PB_ChangeMasterState( PB, Use_Token );
        break;
      }
      break;

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

    case Await_Data_Resp:
      //
      // V tomto stavu by Token nemel prijit
      //
      PB_ChangeMasterState( PB, Active_Idle );
      break;
  }
}


//*****************************************************************************
//**  Master prijal z vnejsku pozadavek na FDL Status - odeslani odpovedi.
//**  Prechod na stav Active_Idle pokud je master ve stavu Listen_Token a ma
//**  jiz vytvoren LAS.
//**
//*****************************************************************************

void PB_ReceivedRequestFDLStatuswithReply( PTProfibus PB, int _SA )
{
  switch ( PB->MasterState )
  {
    case Listen_Token:
      PB_SendFrameNoData( PB, _SA, PB->TS, ( PB->StationStatus << 4 ) + 0, FALSE );
      if ( PB->StationStatus == Master_ready )
      {
        //PB->StationStatus=Master_in_logical_ring; // pozor - puvodne zde - bylo presunuto az do prijmuti prvniho tokenu pro nas
        PB_ChangeMasterState( PB, Active_Idle );
      }
      break;

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

    case Active_Idle:
      PB_SendFrameNoData( PB, _SA, PB->TS, ( PB->StationStatus << 4 ) + 0, FALSE );
      break;
  }
}



//*****************************************************************************
//**  Vyslani retezce datovych bytu (ramce) na sbernici. Na zacatek ramce
//**  jsou pripojeny tri synchronizacni znaky, ktere pozdeji v nizsi vrstve
//**  zpusobi zarazeni casove mezery (SYN) pred vyslanim tohoto ramce.
//**
//**  Parametry:
//**  ----------
//**  frame  - ukazatel na buffer s daty
//**  length - delka dat k vyslani
//**  UseSYN - urcuje zda bude pred ramcem 33Tbitova synchronizacni pauza
//*****************************************************************************

void PB_Send( PTProfibus PB, PUCHAR frame, int length, BOOLEAN UseSYN )
{
  
  int   i;
  int   pos;
  UCHAR TypeBuffer[DEF_BUFFER_SIZE]; 
  UCHAR Buffer[DEF_BUFFER_SIZE];   

  pos = 0;
  
  if ( length <= DEF_BUFFER_SIZE )
  {
    if ( UseSYN )
      for ( i = 0; i < 3; i++ )
      {
        Buffer[pos] = SYN_BYTE;
        TypeBuffer[pos] = SYN_CHAR;
        pos++;
      }

    for ( i = 0; i < length; i++ )
    {
      Buffer[pos] = frame[i];
      TypeBuffer[pos] = DATA_CHAR;
      pos++;
    }

    ProfiM_SendOut( PB->DeviceExtension, Buffer, TypeBuffer, pos );
  }
  
}



//*****************************************************************************
//**  Vyslani ramce bez dat.
//**
//**  Parametry:
//**  ----------
//**  _DA    - Destination Address
//**  _SA    - Source Address
//**  _FC    - Frame Control
//**  UseSYN - urcuje zda bude pred ramcem 33Tbitova synchronizacni pauza
//*****************************************************************************

void PB_SendFrameNoData( PTProfibus PB, int _DA, int _SA, int _FC, BOOLEAN UseSYN )
{
  UCHAR _frame[6], *frame;    // dedictvi Stringu
  frame = _frame - 1;

  frame[1] = DelimiterSD1;
  frame[2] = (UBYTE) _DA;
  frame[3] = (UBYTE) _SA;
  frame[4] = (UBYTE) _FC;
  frame[5] = ( UCHAR ) ( ( _DA + _SA + _FC ) % 0x100 );
  frame[6] = DelimiterED;

  PB_Send( PB, _frame, 6, UseSYN );
}



//*****************************************************************************
//**  Sestaveni a vyslani ramce s promennou delkou dat.
//**
//**  Parametry:
//**  ----------
//**  _DA    - Destination Address
//**  _SA    - Source Address
//**  _DSAP  - Destination Service Access Point
//**  _SSAP  - Source Service Access Point
//**  _FC    - Frame Control
//**  _Data  - ukazatel na buffer s daty k vyslani
//**  length - delka vysilanych dat
//**  UseFC  - urcuje zda bude u ramce nastaven FCB (Frame Control Bit)
//**  UseSYN - urcuje zda bude pred ramcem 33Tbitova synchronizacni pauza
//*****************************************************************************

void PB_SendFrameVariableData( PTProfibus PB,
                               int _DA,
                               int _SA,
                               int _DSAP,
                               int _SSAP,
                               int _FC,
                               PUCHAR _Data,
                               int length,
                               BOOLEAN UseFC,
                               BOOLEAN UseSYN )
{
  UCHAR frame[300]; // will be enough
  int   end, i;
  int   L;
  UCHAR FCS;

  end = 7; // ukazatel na posledni nezpsany byte

  L = length + 3;
  if ( _DSAP != DEFAULT_SAP/*SAPNIL*/ )
  {
    L++; _DA += 128; frame[end++] = (UBYTE) _DSAP;
  }        
  if ( _SSAP != DEFAULT_SAP/*SAPNIL*/ )
  {
    L++; _SA += 128; frame[end++] = (UBYTE) _SSAP;
  }        

  if ( _FC & 0x40 )
  {
    _FC = _FC & 0xCF;
    if ( UseFC )  // Use Frame Control
    {
      if ( PB->GAPL.GAPL[0x7F & _DA].FCV )
        _FC = _FC | 0x10;     // pozor - k DA uz muze byt pridano DAE
      if ( PB->GAPL.GAPL[0x7F & _DA].FCB )
        _FC = _FC | 0x20;
      if ( PB->FrameRepeatCounter == 0 )
        GAPL_FCBToggle( &PB->GAPL, 0x7F & _DA ); // pokud >0 tak se jedna o opakovany dotaz
    }
  }
  else
  {
    // pokud se jedna o odpoved tak nastavi priznak stavu mastera
    _FC = _FC | ( 0x30 & ( PB->StationStatus << 4 ) );
  }

  frame[0] = DelimiterSD2;
  frame[1] = (UBYTE) L;
  frame[2] = (UBYTE) L;
  frame[3] = DelimiterSD2;
  frame[4] = (UBYTE) _DA;
  frame[5] = (UBYTE) _SA;
  frame[6] = (UBYTE) _FC;

  if ( length > 0 )
    for ( i = 0; i < length; i++ )
      frame[end++] = _Data[i];

  FCS = 0;
  for ( i = 4; i < 4 + L; i++ )
    FCS += frame[i];        

  frame[end++] = FCS % 0x100;
  frame[end++] = DelimiterED;

  //for (i=0; i<end; i++)  DbgPrint("Ramec: %d :  %x",i,frame[i]);        
  PB_Send( PB, frame, end, UseSYN );
}


//*****************************************************************************
//**  Vyslani zadosti o FDL Status stanici s adresou _DA
//**
//*****************************************************************************

void PB_SendRequestFDLStatuswithReply( PTProfibus PB, int _DA )
{
  //DbgPrint("PB: Stanice TS=%d vysila FDL_Status pozadavek stanici s adresou: %d",PB->TS, _DA);
  PB_SendFrameNoData( PB, _DA, PB->TS, 0x49, TRUE );
  PB_SetTimeOut( PB, PB->tsl, TO_StartTxEmpty );  
}




//*****************************************************************************
//**  Vyslani tokenu
//**
//**  Parametry:
//**  ----------
//**  _DA - Destination Address
//**  _SA - Source Address
//*****************************************************************************

void PB_SendToken( PTProfibus PB, int _DA, int _SA )
{
  UCHAR frame[3];

  frame[0] = DelimiterSD4;
  frame[1] = (UBYTE) _DA;
  frame[2] = (UBYTE) _SA;

  //if ( _DA != PB->TS )
  //  DbgPrint("PB: Vysilame token SA=%d DA=%d\n", _SA, _DA);
  PB_Send( PB, frame, 3, TRUE );
}








//*****************************************************************************
//**  Vraci aktualni pocet ticku v Performance Counteru.
//**
//*****************************************************************************

__int64 GetCurrentTicks()
{
  LARGE_INTEGER t, f;
  t = KeQueryPerformanceCounter( &f );    // funkce jadra
  //DbgPrint ("Cas : %d\n", t.QuadPart);          
  return t.QuadPart;
}


//*****************************************************************************
//**  Spusti odpocet time-outu.
//**
//*****************************************************************************

void PB_StartTimeOut( PTProfibus PB )
{
  if ( PB->TimeOutState != TO_Running )
  {
    PB->TimeOutState = TO_Running;
    PB_SendNextTimingChars( PB, PB->TO_Interval / 11 ); // posilame hned velky pocet znaku
  }
}


//*****************************************************************************
//**  Zastavi odpocet time-outu a vymaze z vysilaciho bufferu vsechny casovaci
//**  znaky.
//**
//*****************************************************************************

void PB_StopTimeOut( PTProfibus PB )
{
  if ( PB->TimeOutState == TO_Running )
  {
    PB->TimeOutState = TO_Stopped;    
    ProfiM_ClearTimingChars( PB->DeviceExtension ); 
  }    
  PB->TimeOutState = TO_Stopped;      
}



//*****************************************************************************
//**  Nastavi odpocitavani time-outu a pokud je podminka StartCondition
//**  TO_StartNow tak jej i okamzite spusti. Je-li podminka rovna TO_StartTxEmpty
//**  dojde ke spusteni odpoctu time-outu az po vyslani celeho datoveho ramce
//**  z vysilaciho bufferu.
//**
//**  Parametry:
//**  ----------
//**  _interval    - pozadovany interval v Tbit(ech)
//**  StartCondition - viz. vyse  
//**
//*****************************************************************************

void PB_SetTimeOut( PTProfibus PB,
                    int _interval,
                    TTimeOutStartCondition StartCondition )
{
  PB->LastTicks = GetCurrentTicks();
  PB->TO_Interval = _interval;

  switch ( StartCondition )
  {
    case TO_StartNow:
      PB->TimeOutTicks = PB->LastTicks + PB->TO_Interval * PB->Tbit;
      PB_StartTimeOut( PB );
      break;
    case TO_StartTxEmpty:
      PB->TimeOutState = TO_WaittingTxEmpty;
      break;
  }
}


//*****************************************************************************
//**  Umoznuje pokracovani v odpoctu time-outu i po jeho zastaveni. Vyuzivano
//**  pokud je potreba odpocet zastavit vyslanim odpovedi na sbernici (nemohou
//**  byt vysilany casovaci znaky)
//**
//*****************************************************************************

void PB_ContinueTimeOut( PTProfibus PB )
{
  PB->TO_Interval = ( int ) ( PB->TimeOutTicks - GetCurrentTicks() ) /
                    PB->Tbit;    // zbyly interval
  if ( PB->TO_Interval > 0 )
    PB_StartTimeOut( PB );
  else
    PB_TimeTick( PB );
}


//*****************************************************************************
//**  Vysle na sbernici "pocet" casovacich znaku - po vyslani vsech je zavola-
//**  na funkce PB_TimeTick
//**
//*****************************************************************************

void PB_SendNextTimingChars( PTProfibus PB, int pocet )
{
  
  int   i;
  UCHAR Buffer[DEF_BUFFER_SIZE];
  UCHAR TypeBuffer[DEF_BUFFER_SIZE]; 

  //DbgPrint("PB: Pocet pozadovanych casovacich znaku: %d\n",pocet);  
  if ( pocet == 0 )
    pocet = 1;  // alespon jeden casovaci znak;

  //
  // Pokud je pocet casovacich znaku vetsi nez se vejde do bufferu, je tento
  // pocet zkracen. Dodrzeni pozadovaneho intervalu je zajisteno pripadnym
  // opetovnym naplnenim bufferu casovacimi znaky na zacatku PB_TimeTick
  //
  if ( pocet > DEF_BUFFER_SIZE )
    pocet = DEF_BUFFER_SIZE - 10;


  for ( i = 0; i < pocet; i++ )
  {
    Buffer[i] = TIMING_BYTE;
    TypeBuffer[i] = TIMING_CHAR;
  }

  ProfiM_SendOut( PB->DeviceExtension, Buffer, TypeBuffer, pocet );
  
}

⌨️ 快捷键说明

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