calc.c
来自「CNC 的开放码,EMC2 V2.2.8版」· C语言 代码 · 共 752 行 · 第 1/2 页
C
752 行
}/* Element : Monostable (2x2 Blocks) */void CalcTypeMonostable(int x,int y,StrRung * UpdateRung){ StrMonostable * Monostable; Monostable = &MonostableArray[UpdateRung->Element[x][y].VarNum]; // directly connected to the "left"? if yes, ON ! if (x==0) { Monostable->Input = 1; } else { Monostable->Input = StateOnLeft(x-1,y,UpdateRung); } /* detecting impulse on input, the monostable is not retriggerable */ if (Monostable->Input && !Monostable->InputBak && (Monostable->Value==0) ) { Monostable->OutputRunning = 1; Monostable->Value = Monostable->Preset; } if (Monostable->Value>0) Monostable->Value = Monostable->Value - InfosGene->MsSinceLastScan; else Monostable->OutputRunning = 0; Monostable->InputBak = Monostable->Input; UpdateRung->Element[x][y].DynamicOutput = Monostable->OutputRunning;}/* Element : Counter (2x4 Blocks) */void CalcTypeCounter(int x,int y,StrRung * UpdateRung){ StrCounter * Counter = &CounterArray[ UpdateRung->Element[x][y].VarNum ]; // directly connected to the "left"? if yes, ON ! if ( x==0 ) { Counter->InputReset = 1; Counter->InputPreset = 1; Counter->InputCountUp = 1; Counter->InputCountDown = 1; } else { Counter->InputReset = StateOnLeft(x-1,y,UpdateRung); Counter->InputPreset = StateOnLeft(x-1,y+1,UpdateRung); Counter->InputCountUp = StateOnLeft(x-1,y+2,UpdateRung); Counter->InputCountDown = StateOnLeft(x-1,y+3,UpdateRung); } if ( Counter->InputCountUp && Counter->InputCountUpBak==0 ) { Counter->ValueBak = Counter->Value; Counter->Value++; if ( Counter->Value>9999 ) Counter->Value = 0; } if ( Counter->InputCountDown && Counter->InputCountDownBak==0 ) { Counter->ValueBak = Counter->Value; Counter->Value--; if ( Counter->Value<0 ) Counter->Value = 9999; } if ( Counter->InputPreset ) { Counter->ValueBak = Counter->Value; Counter->Value = Counter->Preset; } if ( Counter->InputReset ) { Counter->ValueBak = Counter->Value; Counter->Value = 0; } Counter->InputCountUpBak = Counter->InputCountUp; Counter->InputCountDownBak = Counter->InputCountDown; Counter->OutputDone = ( Counter->Value==Counter->Preset )?1:0; Counter->OutputEmpty = ( Counter->Value==9999 && Counter->ValueBak==0 )?1:0; Counter->OutputFull = ( Counter->Value==0 && Counter->ValueBak==9999 )?1:0; UpdateRung->Element[x][y].DynamicOutput = Counter->OutputEmpty; UpdateRung->Element[x][y + 1].DynamicOutput = Counter->OutputDone; UpdateRung->Element[x][y + 2].DynamicOutput = Counter->OutputFull;}/* Element : Compar (3 Horizontal Blocks) */char CalcTypeCompar(int x,int y,StrRung * UpdateRung){ char State; char StateElement; StateElement = EvalCompare(ArithmExpr[UpdateRung->Element[x][y].VarNum].Expr); UpdateRung->Element[x][y].DynamicState = StateElement; if (x==2) { State = StateElement; } else { UpdateRung->Element[x-2][y].DynamicInput = StateOnLeft(x-2,y,UpdateRung); State = StateElement && UpdateRung->Element[x-2][y].DynamicInput; } UpdateRung->Element[x][y].DynamicOutput = State; return State;}/* Element : Operate (3 Horizontal Blocks) */char CalcTypeOutputOperate(int x,int y,StrRung * UpdateRung){ char State; State = StateOnLeft(x-2,y,UpdateRung); if (State) MakeCalc(ArithmExpr[UpdateRung->Element[x][y].VarNum].Expr,FALSE /* verify mode */); UpdateRung->Element[x][y].DynamicInput = State; UpdateRung->Element[x][y].DynamicState = State; return State;}int RefreshRung(StrRung * Rung, int * JumpTo, int * CallTo){ int x,y; int JumpToRung = -1; int SectionToCall = -1; for (x=0;x<RUNG_WIDTH;x++) { for(y=0;y<RUNG_HEIGHT;y++) { switch(Rung->Element[x][y].Type) { /* MLD,16/5/2001,V0.2.8 , fixed for drawing */ case ELE_FREE: case ELE_UNUSABLE: if (StateOnLeft(x,y,Rung)) Rung->Element[x][y].DynamicInput = 1; else Rung->Element[x][y].DynamicInput = 0; break; /* End fix */ case ELE_INPUT: CalcTypeInput(x,y,Rung,FALSE,FALSE); break; case ELE_INPUT_NOT: CalcTypeInput(x,y,Rung,TRUE,FALSE); break; case ELE_RISING_INPUT: CalcTypeInput(x,y,Rung,FALSE,TRUE); break; case ELE_FALLING_INPUT: CalcTypeInput(x,y,Rung,TRUE,TRUE); break; case ELE_CONNECTION: CalcTypeConnection(x,y,Rung); break; case ELE_TIMER: CalcTypeTimer(x,y,Rung); break; case ELE_MONOSTABLE: CalcTypeMonostable(x,y,Rung); break; case ELE_COUNTER: CalcTypeCounter(x,y,Rung); break; case ELE_COMPAR: CalcTypeCompar(x,y,Rung); break; case ELE_OUTPUT: CalcTypeOutput(x,y,Rung,FALSE); break; case ELE_OUTPUT_NOT: CalcTypeOutput(x,y,Rung,TRUE); break; case ELE_OUTPUT_SET: CalcTypeOutputSetReset(x,y,Rung,FALSE); break; case ELE_OUTPUT_RESET: CalcTypeOutputSetReset(x,y,Rung,TRUE); break; case ELE_OUTPUT_JUMP: JumpToRung = CalcTypeOutputJump(x,y,Rung); // TODO : abort the refresh of the rung immediately... break; case ELE_OUTPUT_CALL: SectionToCall = CalcTypeOutputCall(x,y,Rung); break; case ELE_OUTPUT_OPERATE: CalcTypeOutputOperate(x,y,Rung); break; } } } *JumpTo = JumpToRung; *CallTo = SectionToCall; // TODO : tell if the rung isn't finished : if found Call, immediately abort // and return here to finish the end, after the sub-routine has been called... return TRUE;}// we refresh all the rungs of one section.// we can (J)ump to another rung in the same section.// we can (C)all a sub-routine (a section) and at the end of it, returns to the// next rung.// All the sections 'main' are refreshed in the order defined.// TODO : if we have a mad Jump (infinite loop) we must make something !#define SR_STACK 25void RefreshAllRungs(unsigned long period){ int NumRung; int Goto; int SectionForCallSR; int Done; int ScanMainSection; int CurrentSection; StrSection * pSection; int SubRoutinesStack[ SR_STACK ]; int RungsStack[ SR_STACK ]; int SubRoutineDepth = 0;//TODO: times measures should be moved directly in the module task#ifdef __RTL__ long StartTime = gethrtime();#endif#if defined( RTAI ) && defined( MODULE ) long StartTime = rt_get_cpu_time_ns();#endif InfosGene->NsSinceLastScan += period; InfosGene->MsSinceLastScan = InfosGene->NsSinceLastScan / 1000000; InfosGene->NsSinceLastScan %= 1000000; CycleStart(); for ( ScanMainSection=0; ScanMainSection<NBR_SECTIONS; ScanMainSection++ ) { CurrentSection = ScanMainSection; pSection = &SectionArray[ CurrentSection ]; // current section defined and is a main-section (not a sub-routine) // and in Ladder language ? if ( pSection->Used && pSection->SubRoutineNumber==-1 && pSection->Language==SECTION_IN_LADDER ) { Done = FALSE; NumRung = pSection->FirstRung; do { RefreshRung(&RungArray[NumRung], &Goto, &SectionForCallSR); if ( SectionForCallSR!=-1 ) { if ( SectionArray[ SectionForCallSR ].Used && SectionArray[ SectionForCallSR ].SubRoutineNumber>=0 ) { if ( SubRoutineDepth<SR_STACK-1 ) { // saving current section context SubRoutineDepth++; SubRoutinesStack[ SubRoutineDepth ] = CurrentSection; if ( NumRung!=pSection->LastRung ) { RungsStack[ SubRoutineDepth ] = RungArray[NumRung].NextRung; } else { // at the end of the sub-routine, this section is already finished RungsStack[ SubRoutineDepth ] = -1; } // now starting the sub-routine section... CurrentSection = SectionForCallSR; pSection = &SectionArray[ CurrentSection ]; NumRung = pSection->FirstRung;//printf("-> sub-routine called : SR : Sec=%d, Rung =%d\n", CurrentSection, NumRung ); } else { debug_printf("Refresh rungs aborted - too much sub-routine calls in series !?"); } } else { debug_printf("Refresh rungs aborted - call to a sub-routine undefined or programmed as main !!!"); } } else if ( Goto!=-1 ) { if (!RungArray[Goto].Used) { Done = TRUE; debug_printf("Refresh rungs aborted - jump to an undefined rung found in rung No%d...\n",Goto); } NumRung = Goto; } else { if (NumRung == pSection->LastRung) { // if this section is a sub-routine, we make a return... if ( pSection->SubRoutineNumber>=0 ) { int ReturnFound = FALSE; do { if ( SubRoutineDepth>0 ) { // previous section already finished ? if ( RungsStack[ SubRoutineDepth ]!=-1 ) { CurrentSection = SubRoutinesStack[ SubRoutineDepth ]; pSection = &SectionArray[ CurrentSection ]; NumRung = RungsStack[ SubRoutineDepth ]; ReturnFound = TRUE;//printf( "-> return from sub-routine to : Sec=%d, Rung =%d\n", CurrentSection, NumRung ); } else { // the previous main section was already finished... if ( SectionArray[ SubRoutinesStack[ SubRoutineDepth ] ].SubRoutineNumber==0 ) { Done = TRUE; ReturnFound = TRUE;//printf( "-> return from sub-routine with previous main section done...\n" ); } else {//printf( "-> return from sub-routine with sub-routine already done... searching again...\n" ); } } SubRoutineDepth--; } else { debug_printf("Refresh rungs aborted - return of sub-routine without call before !?"); } } while( !ReturnFound ); } else { // last rung found for a main section Done = TRUE; } } else NumRung = RungArray[NumRung].NextRung; } } while(!Done); }#ifdef SEQUENTIAL_SUPPORT // current section defined and is in sequential language if ( pSection->Used && pSection->Language==SECTION_IN_SEQUENTIAL ) { RefreshSequentialPage( pSection->SequentialPage ); }#endif }// for( ) CycleEnd();//TODO: times measures should be moved directly in the module task#ifdef __RTL__ InfosGene->DurationOfLastScan = gethrtime() - StartTime;// rtl_printf("Time elapsed for refresh = %u nsec\n",gethrtime()-StartTime);#endif#if defined( RTAI ) && defined ( MODULE ) InfosGene->DurationOfLastScan = rt_get_cpu_time_ns() - StartTime;#endif}void CopyRungToRung(StrRung * RungSrc,StrRung * RungDest){ memcpy(RungDest,RungSrc,sizeof(StrRung));}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?