2010-08-19 70 views
0

HI ..我想要一個如何在C中使用函數指針來實現FSM的例子。FSM中的函數指針

+0

我假設FSM意味着有限狀態機?你需要什麼函數指針?有關目標的更多信息將有助於獲得有用的示例。 – rubenvb 2010-08-19 09:38:51

+2

(1)非常苛刻你。 (2)FSM代表什麼? (3)您是否已經獲得了可以向我們顯示的任何代碼,以及您目前卡住的指針? (4)這功課嗎? (如果是這樣,請編輯你的問題,並添加標籤'家庭作業'。) – stakx 2010-08-19 09:39:39

+0

@stakx:你確定喜歡做無人認領的假設... – leppie 2010-08-19 09:44:06

回答

1

一個例子太大了,無法在這裏寫出答案。 下面是一個例子存在的,這是我用谷歌搜索state machine c "function pointer"發現:Implementing Efficient State Machines

+0

感謝您的回覆。 – priya 2010-08-20 05:28:55

0

我想說初始化指針的數組事件處理程序。因此,數組中的每個元素都是指向特定事件的函數指針,它是枚舉的一部分。 如果foo是您的函數指針數組,它被初始化爲事件,然後在發生任何事件時調用foo[event]()

試着先調用函數指針的編碼,接下來你可以移動到數組並返回到SO,如果有更多的疑問。

首先你可以閱讀函數指針here

+0

感謝您的回覆。 – priya 2010-08-20 05:28:30

1

這是一個在ARDUINO中使用函數指針的小示例。這個例子不允許併發。它可以完美地轉換爲普通的C,如果在主內寫入設置和循環()
每個狀態都是void()函數。每個狀態功能負責讀取輸入和設置輸出。完成後,該功能應立即返回。它將被直接再次調用。通過在返回之前立即調用離開函數,該函數還負責狀態轉換。每個狀態函數都應該有一個用於計時的靜態長變量。
將全局變量狀態設置爲指向安裝例程中的初始狀態。 我想在不同的狀態下計時,所以我通過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
國家

代碼躍遷可以通過陣列或開關情況下,可以利用。寫在if if指令下。

#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複製的。這是谷歌的第一個搜索結果。 https://gist.github.com/nmandery/1717405 並記住,從git hub複製。該stackoverflow的答案也從那裏複製。看看lookup_transition functiom ...我粘貼在這裏.. – 2017-05-28 22:29:35

+0

隨着loopup_transtion功能,我寫了測試的小UT碼也also.and不會很快結束..「只是複製」至少了解差異。並且你引用了你自己的想法並且覺得自己想要......學生需要... – 2017-05-28 22:34:56

+0

我不知道shino,爲什麼你不能看到區別。它被複制。這是開放的。但請找到丟失的查找功能和UT代碼... – 2017-05-28 22:36:21