2010-08-19 4 views
0

안녕하세요 ..C에서 함수 포인터를 사용하여 FSM을 구현하는 방법의 예가 필요합니다.FSM의 함수 포인터

+0

FSM은 Finite State Machine을 의미한다고 가정합니다. 함수 포인터가 필요한 것은 무엇입니까? 목표가 무엇인지에 대한 좀 더 자세한 정보는 유용한 예제를 얻는 데 도움이 될 것입니다. – rubenvb

+2

(1) 매우 까다 롭습니다. (2) FSM은 무엇을 의미합니까? (3) 우리에게 보여줄 수있는 코드와 함께 현재 붙어있는 포인터가 있습니까? (4)이 숙제가 있습니까? (그렇다면 질문을 편집하여'숙제 '라는 태그를 붙이십시오.) – stakx

+0

@stakx : 틀림없이 전제가없는 가정을하고 싶습니다. ... – leppie

답변

3

내가 이벤트 핸들러에 대한 포인터의 배열을 초기화 말할 것 C.

+0

답변을 주셔서 감사합니다. – priya

0

에 유한 상태 기계를 구현하는 방법에 대한 this simple example 참조 : 는 여기에 내가 state machine c "function pointer"에 대한 인터넷 검색에 의해 발견 기존의 예입니다. 따라서 배열의 각 요소는 열거 형의 특정 이벤트에 대한 함수 포인터입니다. foo이 이벤트로 초기화 된 함수 포인터의 배열이면 이벤트가 발생할 때 foo[event]()을 호출하십시오.

함수 포인터를 먼저 호출하기 위해 코딩을 시도해보십시오. 다음으로 배열로 이동하여 더 많은 의문점이있는 경우 다시 돌아올 수 있습니다.

처음에는 기능 포인터 here에 대해 읽을 수 있습니다.

+0

답변을 주셔서 감사합니다. – priya

1

다음은 ARDUINO에서 함수 포인터를 사용하는 데 대한 간단한 데모입니다. 이 예제에서는 동시성을 허용하지 않습니다. main() 내부에서 설정과 루프를 작성하면 정상 C로 완벽하게 전송 가능
각 상태는 void() 함수입니다. 각 상태 함수는 입력을 읽고 출력을 설정합니다. 이 작업이 완료되면 함수가 즉시 반환됩니다. 그것은 다시 직접 호출됩니다. 이 함수는 반환 직전에 leave 함수를 호출하여 상태 전이를 담당합니다. 각 상태 함수에는 시간 기록을위한 정적 long 변수가 있어야합니다.
글로벌 변수 상태는 설정 루틴의 초기 상태를 가리 키도록 설정됩니다. 여러 상태에서 계시를하고 싶었 기 때문에 2 가지 함수로 상태 천이를 구현했습니다 :

void enter (long * stateTime) 상태 함수를 입력 할 때 가장 먼저 호출해야합니다. 비활성 끝이 시간을 유지하는 경우 상태를 활성화합니다.

void leave (void (* next)(), long * statetime), 전역 상태 포인터를 변경하고 현재 상태를 비활성화합니다.

void (*state)();//function pointer for state machine 
long prevMillis = 0;//timekeeper 
const int LEDPIN = 13; 
int counter1 = 0; 

void enter(long *statetime){ 
    if(*statetime==-1){//check for passive state 
    prevMillis = millis();//set timemark when entering state 
    }//if(statetime==0) 
    *statetime = millis()-prevMillis;//keep time 
}//enter() 

void leave(void (*next)(), long *statetime){ 
    *statetime=-1;//set state to passive 
    state=next;//point to next state 
}//leave() 

void off500ms(){ 
    static long stateMillis;//timer for this state 
    enter(&stateMillis);//update timer 
    digitalWrite(LEDPIN, LOW); 
    if(stateMillis>499){//check if time is up 
    leave(on500ms, &stateMillis); 
    }//if(stateMillis>499) 
}//off500ms() 

void off2s(){ 
    static long stateMillis;//timer for this state 
    enter(&stateMillis);//update timer 
    digitalWrite(LEDPIN, LOW); 
    if(stateMillis>1999){//check if time is up 
    leave(on500ms, &stateMillis); 
    }//if(stateMillis>499) 
}//off2s() 

void on500ms(){ 
    static long stateMillis;//timer for this state 
    enter(&stateMillis);//update timer 
    digitalWrite(LEDPIN, HIGH); 
    if(stateMillis >499){//time is up 
    if(++counter1==6){//number of blinks 
     leave(off2s, &stateMillis); 
     counter1=0;//reset counter 
    }else{//if(++counter1==6) 
     leave(off500ms, &stateMillis); 
    }//if(++counter1==6) 
    }//if(stateMills>499) 
}//on500ms 

void setup(){ 
    pinMode(LEDPIN, OUTPUT); 
    state = on500ms;//set initial state 
}/setup() 

void loop(){ 
    state();//start FSM 
}//loop 
0

주 트란 지션 코드는 배열 또는 스위치 케이스로 하나 활용 될 수있다. else 지시문에 따라 작성됩니다.

#include <stdio.h> 
#include <stdlib.h> 

int entry_state(void); 
int foo_state(void); 
int bar_state(void); 
int exit_state(void); 

enum state_codes lookup_transitions(enum state_codes, enum ret_codes); 

/* array and enum below must be in sync! */ 
int (* state[])(void) = { entry_state, foo_state, bar_state, exit_state}; 
enum state_codes { entry, foo, bar, end}; 

enum ret_codes { ok, fail, repeat}; 
struct transition { 
    enum state_codes src_state; 
    enum ret_codes ret_code; 
    enum state_codes dst_state; 
}; 
/* transitions from end state aren't needed */ 
struct transition state_transitions[] = { 
    {entry, ok,  foo}, 
    {entry, fail, end}, 
    {foo, ok,  bar}, 
    {foo, fail, end}, 
    {foo, repeat, foo}, 
    {bar, ok,  end}, 
    {bar, fail, end}, 
    {bar, repeat, foo}}; 

int main(int argc, char *argv[]) { 
    enum state_codes cur_state = entry; 
    enum ret_codes rc; 
    int (* state_fun)(void); 

    for (;;) { 
     state_fun = state[cur_state]; 
     rc = state_fun(); 
     if (end == cur_state) 
      break; 
     cur_state = lookup_transitions(cur_state, rc); 
    } 

    return EXIT_SUCCESS; 
} 

/* 
* lookup_transition() function has time complexity of class O(n). 
* We can optimize it. 
* */ 
enum state_codes 
lookup_transitions(enum state_codes cur_state, enum ret_codes rc) 
{ 
#if 0 
    switch (cur_state) { 
     case entry: 
      cur_state = ((rc == ok) ? (foo) : (end)); 
      break; 
     case foo: 
      cur_state = ((rc == ok) ? (bar) : ((rc == fail) ? (end) : (foo))); 
      break; 
     default: 
      cur_state = ((rc == ok) ? (end) : ((rc == fail) ? (end) : (foo))); 
      break; 
    } 

    return cur_state; 
#else 
    char arr_size = (sizeof(state_transitions)/sizeof(state_transitions[0])); /* This can be shifted to main function to avoid redundant job. */ 
    char count; 

    for (count = 0; count < arr_size; count++) { 
     if ((state_transitions[count].src_state == cur_state) && (state_transitions[count].ret_code == rc)) { 
      return (state_transitions[count].dst_state); 
     } 
    } 
#endif 
} 

int entry_state(void) 
{ 
    int st; 
    enum ret_codes rc; 

    printf("YOU ARE IN ENTRY STATE.\nEnter 0/1: "); 

    scanf("%d", &st); 

    rc = ((st == 1) ? (fail) : (ok)); 
    return rc; 
} 

int foo_state(void) 
{ 
    int st; 
    enum ret_codes rc; 

    printf("YOU ARE IN FOO STATE.\nEnter 0/1/2: "); 

    scanf("%d", &st); 

    rc = ((st == 0) ? (ok) : ((st == 2) ? (repeat) : (fail))); 
    return rc; 
} 

int bar_state(void) 
{ 
    int st; 
    enum ret_codes rc; 

    printf("YOU ARE IN BAR STATE.\nEnter 0/1/2: "); 

    scanf("%d", &st); 

    rc = ((st == 0) ? (ok) : ((st == 2) ? (repeat) : (fail))); 
    return rc; 
} 

int exit_state(void) 
{ 
    printf("YOU ARE IN EXIT STATE.\n"); 

    exit(EXIT_SUCCESS); 
} 
+0

아니 github 웹 사이트에서 복사됩니다 .. 그리고 난 lookup_transtion 코드에 썼습니다. 거의 모든 사람들이 github에서 복사된다는 것을 알고 있습니다. 그것이 Google의 첫 번째 검색 결과입니다. https://gist.github.com/nmandery/1717405 git hub에서 복사 한 내용을 유의하십시오. 그 stackoverflow 대답도 거기에서 복사됩니다. lookup_transition functiom보세요 ... 여기에 붙여 넣었습니다. –

+0

loopup_transtion 함수와 함께 테스트 용 작은 UT 코드를 작성했으며 너무 빨리 결론을 내리지 않습니다. 그리고 당신은 자신의 아테네와 같은 toper .. 느낌이 학생을 위해 필요합니다 ... –

+0

나는 차이를 볼 수없는 이유는 shino을 몰라요. 복사됩니다. 열려있어. 하지만 누락 된 조회 기능과 UT 코드를 찾으십시오. –