?? profibus.c
字號:
}
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 + -