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

📄 profibus.c

📁 SPC3 SETUP PROGRAMS SP C3 SETUP PROGRAMS
💻 C
📖 第 1 页 / 共 5 页
字号:
        //  otevreny handle je pozadavek zpracovavan.
        //
        PB->ActualHID = ReadHIDfromRB( Request );        

        PB_DbgPrintL2( "PB: Zpracovavani pozadavku pro HID=%d:\n",
                       PB->ActualHID );

        PB_ProcessRequest( PB, Request );
      }
      else
        PB_ChangeMasterState( PB, Check_Access_Time );

      break;

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

    case Check_Access_Time:
      PB->LastUseTokenEntryTicks = PB->UseTokenEntryTicks;
      if ( PB->RLL_Status == RLL_WaitNextCycle )
        PB->RLL_Status = RLL_TestNext;
      PB_ChangeMasterState( PB, Pass_Token );
      break;

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

    case Pass_Token:
      //
      // Pri prechodu ze stavu Check_Access_Time (tzn. master zapojen do log.
      // kruhu, probiha datova vymena) vyprsi-li odpocitavadlo G je aktualizovana
      // dalsi polozka v GAPu
      //
      
      if ( PB->LastState == Check_Access_Time )
      {
        NextToTest = GAPL_NextToTest( &PB->GAPL );        
        
        if ( NextToTest == -1 )
        {
          //
          // mezi TS a NS nelezi zadne stanice
          //
          PB_SendToken( PB, PB->NS, PB->TS );
          PB_ChangeMasterState( PB, Check_Token_Pass );
          break;
        }       
        
        if ( PB->G_CountDown <= 0 )
        {
          PB->G_CountDown = PB->G;
          PB_SendRequestFDLStatuswithReply( PB, NextToTest );
          PB_ChangeMasterState( PB, Await_Status_Resp );
          break;
        }
        else
        {
          PB->G_CountDown--;
          PB_SendToken( PB, PB->NS, PB->TS );
          PB_ChangeMasterState( PB, Check_Token_Pass );
          break;
        }
      }

      //
      // Navrat po otestovani dalsi stanice z GAPu. Je vyslan token dalsi stanici.
      // NS se muze rovnat TS.
      //
      if ( PB->LastState == Await_Status_Resp )
      {
        PB_SendToken( PB, PB->NS, PB->TS ); // dalsi master ovsem nemusi token prevzit - nutno testovat
        PB_ChangeMasterState( PB, Check_Token_Pass );
        break;
      }

      //
      // Studeny start logickeho kruhu. Prebirame iniciativu na sbernici a 
      // zaciname s vytvarenim GAPu.
      //
      if ( PB->LastState == Claim_Token )
      {
        GAPL_Clear( &PB->GAPL );
        GAPL_RestartTest( &PB->GAPL );
        PB_DbgPrintL3( "PB: Prebirame iniciativu na sbernici...\n" );                                
        PB->StationStatus = Master_in_logical_ring;
        PB_SendToken( PB, PB->TS, PB->TS );
        PB_SendToken( PB, PB->TS, PB->TS );
        PB_SendRequestFDLStatuswithReply( PB, GAPL_NextToTest( &PB->GAPL ) );                                
        // neprepiname do Await_Status_Resp, ale pri vytvareni GAPLu zustavame
        // v Pass_Token
        break;
      }
      break;  

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

    case Check_Token_Pass:
      if ( PB->NS == PB->TS )
        PB_ChangeMasterState( PB, Active_Idle );    // Na sbernici neni jiny master
      else
      {
        PB_SetTimeOut( PB, PB->tsl, TO_StartTxEmpty );  // Cekame na overeni spravneho predani tokenu
      }
      break;
  }
  // tady uz by nemelo nic byt...
  // vypadavaji tu ChangeMasterState(...) z rekurze...
}



//*****************************************************************************
//**  Vola se pokud je prijat znak - zajistuje vytvareni vstupniho bufferu,
//**  vyhledani validnich ramcu a jejich predani k dalsimu zpracovani.
//**  Fce je volana z nizsi vrstvy.
//**
//**  Parametry:
//**  ----------
//**  ch - prijaty znak
//*****************************************************************************

void PB_RxByte( PTProfibus PB, UCHAR ch )
{
  int     length;
  int     i;
  int     StartIndex;
  BOOLEAN TakeNextFrame;

 
  if ( !PB )   
  {
    DbgPrint( "PB: RxByte Error - PB pointer is NULL!" );
    return;
  }        
  
/*  
  if ( ( PB->MasterState == Await_Data_Resp || PB->MasterState == Await_Status_Resp ) 
       && PB->TimeOutState == TO_Running )
    PB_StopTimeOut( PB ); // casovac deaktivovan prijmem prvniho znaku 
        //jeste je potreba testovat spravnost ramce a pripadne generovat timeout
*/    
    
  if ( PB->InBufLen<0 || PB->InBufLen >= INBUF_SIZE )
  {
    DbgPrint("PB: InBuf Error - out of range!");
    return;
  }
  

  PB->InBuf[PB->InBufLen] = ch;
  PB->InBufLen++;
  
  
  if ( PB->InBufLen >= INBUF_SIZE )
  {
    DbgPrint("PB: InBuf Overflow!");
    PB->InBufLen = INBUF_SIZE - 1;
    return;
  }

  
  do
  {
    TakeNextFrame = FALSE;

    if ( PBFrame_FindFrame( PB->InBuf, PB->InBufLen, &length ) )  // hleda na zacatku prijatych dat ramec a v length vraci jeho delku
    {
      PBFrame_DecodeFrame( &PB->RxFrame,
                           PB->InBuf,
                           PB->InBufLen,
                           PB->TS,
                           PB->default_sap );
      //InBuf.Delete(1,length);
      if ( length <= PB->InBufLen )
        for ( i = 0; i < PB->InBufLen - length; i++ )
          PB->InBuf[i] = PB->InBuf[i + length]; // odstraneni zpracovaneho framu
      PB->InBufLen -= length;                        
      TakeNextFrame = TRUE;

      //                              
      // vyplneni falesnych parametru pro ShortAcknowledge (muze nekde delat neplechu)
      //
      if ( PB->RxFrame.FrameType == FT_ShortAcknowledge )
      {
        if ( PB->MasterState == Await_Data_Resp )
        {
          PB->RxFrame.DA = (UBYTE) PB->TS;
          PB->RxFrame.SA = PB->ActualRequest->application_block.rem_add.station;
        }
        else
        {
          //
          // Nejsme-li ve stavu cekani na odpoved priradime ramci SA jinou nez
          // TS (ramec typu ShortAcknowldge neobsahuje zdrojovou a cilovou adresu
          // a tudiz nemusi byt jasne pro koho je - stanice vi, ze je ramec pro
          // ni pokud ma token a ceka na odpoved - problem muze byt pri propojeni
          // mastera na sbernici).
          // Hodnota TS+1 je falesna, ale hodnota mimo 0..HSA by mohla zpusobit
          // chybu nekde jinde.
          //
          PB->RxFrame.DA = (UBYTE) PB->TS + 1;          
          if ( PB->RxFrame.DA > PB->HSA )
            PB->RxFrame.DA = 0;
          PB->RxFrame.SA = (UBYTE) PB->TS + 1;          
          if ( PB->RxFrame.SA > PB->HSA )
            PB->RxFrame.SA = 0;
          //
          // Mozna by bylo jednodussi a stacilo by nastavi RxFrame.Valid na FALSE
          //             
        }
      }

      //
      // Format ramce je spravny - muzeme ho spracovat
      //
      if ( PB->RxFrame.Valid )
      {
        //
        // Na sbernici vysila duplicitni stanice ve stavu Listen_Token
        //
        if ( PB->RxFrame.SA == PB->TS && PB->MasterState == Listen_Token )
        {
          PB->DuplicitAddressCounter++;
          if ( PB->DuplicitAddressCounter >= 2 )
          {
            PB_DbgPrintL3( "PB: Na sbernici vysila stanice s duplicitni adresou %d!",
                           PB->TS );
            PB_DbgPrintL3( "PB: Prechod do stavu Offline..." );                                        
            PB->DuplicitAddressCounter = 0;
            PB_ChangeMasterState( PB, Offline );
            return;
          }
        }
        
        //
        // Znovuspusteni time-outu k detekci rozpadu logickeho kruhu 
        // ve stavu Active_Idle
        //
        if ( PB->MasterState == Active_Idle )
        {
          PB_StopTimeOut( PB );
          // Melo by nasledovat
          //PB_SetTimeOut( PB, Tto, TO_StartNow );  
        }

        //
        // Na sbernici vysila duplicitni stanice ve stavu Active_Idle          
        //
        if ( PB->RxFrame.SA == PB->TS && PB->MasterState == Active_Idle )
        {
          PB_DbgPrintL3( "PB: Na sbernici vysila stanice s duplicitni adresou!" );
          PB_DbgPrintL3( "PB: Prechod do stavu Listen_Token..." );                                        
          PB_ChangeMasterState( PB, Listen_Token );
          return;
        }
        
        //
        // Prijat token
        //
        if ( PB->RxFrame.FrameType == FT_Token )
        {
          PB_ReceivedToken( PB, PB->RxFrame.DA, PB->RxFrame.SA );
          return;
        }

        //
        // Overeni spravneho odeslani Tokenu - NS stanice vysila ramec
        // Pokud jako prvni ramec od NS byl Token pro nas, tak byl jiz
        // zpracovan vyse.
        //
        if ( PB->MasterState == Check_Token_Pass && PB->RxFrame.SA == PB->NS )
        {
          PB_StopTimeOut( PB );
          PB_ChangeMasterState( PB, Active_Idle );
          //
          // Zde nesmi byt return - prvni ramec, ktery NS stanice vysila
          // totiz muze take byt pro nas
          //
          //return;
        }                                

        //
        // Prijaty ramec je pro nas
        //
        if ( PB->RxFrame.DA == PB->TS ||
             PB->RxFrame.FrameType == FT_ShortAcknowledge )
        {
          if ( PB->RxFrame.FrameType == FT_Reply ||
               PB->RxFrame.FrameType == FT_ShortAcknowledge )
          {
            PB_ReceivedReply( PB );   // prisla odpoved na nas pozadavek
          }
          else
            PB_ReceivedRequest( PB );   // prisel pozadavek z vnejsku

        }
      }
    }
    else    // nenalezen zadny platny pocatek framu SDx nebo SC - odriznuti pocatku znaku v bufferu az dalsimu SDx nebo SC
    {
      StartIndex = PBFrame_FindStartDelimiter( PB->InBuf, PB->InBufLen );
      if ( StartIndex != -1 && StartIndex != 1 )
      {
        StartIndex--; // dedictvi Stringu
        for ( i = 0; i < PB->InBufLen - StartIndex; i++ )
          PB->InBuf[i] = PB->InBuf[i + StartIndex]; // odstraneni zpracovaneho framu
        PB->InBufLen -= StartIndex;
      }
    }
    
  // pro jistotu
  if ( PB->InBufLen >= INBUF_SIZE )
  {
    DbgPrint("PB: InBuf Overflow2!");
    PB->InBufLen = INBUF_SIZE - 1;
    return;
  }
    
  }   
  while ( TakeNextFrame && PB->InBufLen > 0 );
}



//*****************************************************************************
//**  Vola se pokud na sbernici dochazi k predavani tokenu. Zajistuje vytvareni
//**  a udrzbu LASu ve stavu Listen_Token a prijmuti tokenu pokud je pro TS
//**  (This Station) - tj. pro nas.
//**  V LASu pracuje pouze se stanicemi typu master.
//**
//**  Parametry:
//**  ----------
//**  _DA - adresa stanice pro kterou je Token urcen (nemusi byt jenom pro nas,
//**    tato fce zpracovava vsechny Tokeny vyslane na sbernici
//**  _SA - adresa puvodce Tokenu
//*****************************************************************************

void PB_ReceivedToken( PTProfibus PB, int _DA, int _SA )
{
//  DbgPrint("PB: Stanice %d prijala token (DA=%d SA=%d).", PB->TS, _DA, _SA);
  
  switch ( PB->MasterState )
  {
    case Offline:
      break;

      //---------------------------------------                         

    case Listen_Token:
      //
      // deaktivace Timeoutu pro Claim_Token pokud prisel token (melo by se mozna deaktivovat i driv [jenom od prijmu znaku?? ] )
      // nekde by se ovsem mel rozebehnout dalsi time-out... 
      //
      PB_StopTimeOut( PB );  


      if ( !LAS_Complete( &PB->LAS ) )
      {
        //
        // Vytvareni LASu a detekce dvou shodnych obehu tokenu
        // 
        if ( LAS_CreatingAdd( &PB->LAS, _SA ) )
        {
          // LAS complete
          PB->StationStatus = Master_ready;
          PB_DbgPrintL2( "PB: Dva identicke obehy tokenu - LAS completed!" );
        }
      }
      else
      {
        //
        // LAS hotov - ted pouze updatovani a cekani na povereni od PS
        //
        LAS_Update( &PB->LAS, _SA );
      }


      break;

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

    case Check_Token_Pass:  
    case Active_Idle:
      if ( _SA == PB->PS && _DA == PB->NS )     // Stanice byla nasilne vyrazena z ringu
      {
        PB_DbgPrintL3( "PB: Master byl nasilne vyrazen z ringu!" );
        PB_ChangeMasterState( PB, Listen_Token );
        break;
      }

      LAS_Update( &PB->LAS, _SA );
      LAS_VymazStanice( &PB->LAS, _DA, _SA );  // Update LASu nejlepe vymazanim stanic mezi SA a DA - snad OK

      if ( _DA == PB->TS )  // Token je pro nas
      {
        //DbgPrint("PB: Stanice %d prijala token (DA=%d SA=%d - PS=%d).", PB->TS, _DA, _SA, PB->PS);        
        if ( PB->PS != -1 && PB->PS != _SA )
        {
          // jeste by tu mohlo byt overeni jestli opakovani je od te same stanice
          PB->IgnoreTokenCounter++;
          if ( PB->IgnoreTokenCounter >= 2 )
            PB->IgnoreTokenCounter = 0; // a pokracuje se dale
          else
            break;
        }
        //DbgPrint("PB: Stanice %d prijala token (DA=%d SA=%d) S3.", PB->TS, _DA, _SA);        

⌨️ 快捷键说明

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