日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > > 大橙子瘋嵌入式


前言

之前介紹的狀態(tài)機是有限狀態(tài)機(FSM),這篇介紹一下分層狀態(tài)機(HSM)的理解。

分層狀態(tài)機是一種用于描述系統(tǒng)行為和控制流的模型,它將系統(tǒng)劃分為多個層級,并將每個層級表示為一個狀態(tài)機。每個狀態(tài)機描述了一個特定的狀態(tài)集合以及狀態(tài)之間的轉移規(guī)則。每個狀態(tài)機都有自己的輸入和輸出,可以與其他狀態(tài)機進行交互,從而形成整個系統(tǒng)的行為。

分層狀態(tài)機的設計有助于降低系統(tǒng)復雜度,并且能夠更好地組織系統(tǒng)的功能和行為。在分層狀態(tài)機中,每個狀態(tài)機負責處理一個特定的子任務或功能,這使得系統(tǒng)更易于理解和維護。
在分層狀態(tài)機中,高層狀態(tài)機負責協(xié)調和控制下層狀態(tài)機的行為。高層狀態(tài)機可以通過向下層狀態(tài)機發(fā)送命令或事件來觸發(fā)狀態(tài)轉換,下層狀態(tài)機可以將其處理結果返回給上層狀態(tài)機,以便上層狀態(tài)機作出相應的決策。

區(qū)別

分層狀態(tài)機(HSM)和有限狀態(tài)機(FSM)是兩種不同的模型,雖然它們都用于描述系統(tǒng)的行為和控制流,但它們之間還是存在一些區(qū)別的。

  1. 層次結構不同:分層狀態(tài)機是將系統(tǒng)劃分為多個層級,并將每個層級表示為一個狀態(tài)機,每個狀態(tài)機有自己的輸入和輸出,可以與其他狀態(tài)機進行交互,形成整個系統(tǒng)的行為。而有限狀態(tài)機則是單層的結構,描述系統(tǒng)在特定條件下的狀態(tài)和狀態(tài)之間的轉移。

  2. 狀態(tài)數(shù)量不同:分層狀態(tài)機中的狀態(tài)數(shù)量通常比有限狀態(tài)機更多。由于分層狀態(tài)機的每個層級都有自己的狀態(tài)集合,因此整個系統(tǒng)的狀態(tài)集合是各層狀態(tài)集合的并集。而有限狀態(tài)機只有一個狀態(tài)集合,狀態(tài)數(shù)量相對較少。

  3. 狀態(tài)之間的轉移規(guī)則不同:在分層狀態(tài)機中,狀態(tài)之間的轉移規(guī)則可以根據(jù)不同的層級進行定義,每個狀態(tài)機有自己的轉移規(guī)則。而有限狀態(tài)機的狀態(tài)之間的轉移規(guī)則通常是全局統(tǒng)一的。

  4. 功能不同:分層狀態(tài)機通常用于描述復雜系統(tǒng)的行為和控制流,其設計目的是為了降低系統(tǒng)的復雜度并更好地組織系統(tǒng)的功能和行為。而有限狀態(tài)機通常用于描述簡單的控制流程或者算法。

總之,分層狀態(tài)機和有限狀態(tài)機雖然都是描述系統(tǒng)行為和控制流的模型,但是它們的層次結構、狀態(tài)數(shù)量、狀態(tài)之間的轉移規(guī)則和應用場景等方面存在較大的不同

舉例說明

假設有一個自動售貨機,它需要根據(jù)用戶選擇的按鈕來售出對應的商品。我們可以使用有限狀態(tài)機和分層狀態(tài)機分別來實現(xiàn)這個自動售貨機。

首先,我們來看一下如何使用有限狀態(tài)機來實現(xiàn)自動售貨機。假設我們有三個商品可以售賣,分別是飲料、糖果和薯片,對應的按鈕分別為A、B和C。那么,我們可以定義以下狀態(tài):

  • 初始狀態(tài):待命狀態(tài)

  • 狀態(tài)1:等待用戶選擇按鈕

  • 狀態(tài)2:出貨狀態(tài)

根據(jù)這些狀態(tài),我們可以設計狀態(tài)轉移規(guī)則如下:

  • 待命狀態(tài):如果用戶按下按鈕A、B或C,則轉移到等待用戶選擇按鈕狀態(tài)。

  • 等待用戶選擇按鈕狀態(tài):如果用戶按下按鈕A,則轉移到出貨狀態(tài)1;如果用戶按下按鈕B,則轉移到出貨狀態(tài)2;如果用戶按下按鈕C,則轉移到出貨狀態(tài)3。

  • 出貨狀態(tài)1:出售飲料,并轉移到待命狀態(tài)。

  • 出貨狀態(tài)2:出售糖果,并轉移到待命狀態(tài)。

  • 出貨狀態(tài)3:出售薯片,并轉移到待命狀態(tài)。

流程圖:

接下來,我們來看一下如何使用分層狀態(tài)機來實現(xiàn)自動售貨機。首先,我們可以將自動售貨機分解成三個層次:選擇商品層、支付層和出貨層。每個層次都有自己的狀態(tài)和狀態(tài)轉移規(guī)則,如下所示:

  • 選擇商品層:等待用戶選擇按鈕狀態(tài)

  • 支付層:等待用戶支付狀態(tài)

  • 出貨層:出貨狀態(tài)

然后,我們可以進一步細化每個層次的狀態(tài)和狀態(tài)轉移規(guī)則,如下所示:

  • 選擇商品層:

    • 初始狀態(tài):待命狀態(tài)

    • 狀態(tài)1:等待用戶選擇按鈕

    • 轉移規(guī)則:如果用戶按下按鈕A、B或C,則轉移到等待用戶支付狀態(tài),并保存用戶選擇的商品。

  • 支付層:

    • 初始狀態(tài):待命狀態(tài)

    • 狀態(tài)1:等待用戶支付

    • 轉移規(guī)則:如果用戶完成支付,則轉移到出貨狀態(tài),并發(fā)送出貨指令。

  • 出貨層:

    • 初始狀態(tài):待命狀態(tài)

    • 狀態(tài)1:等待出貨指令

    • 狀態(tài)2:正在出貨

    • 轉移規(guī)則:如果接收到出貨指令,則轉移到正在出貨狀態(tài),并執(zhí)行出貨操作;如果出貨操作完成,則轉移到待命狀態(tài)。

流程圖:

需要注意的是,有限狀態(tài)機和分層狀態(tài)機都可以用于自動售貨機的設計,選擇哪種方法取決于具體的需求和復雜度。如果系統(tǒng)相對簡單,可以使用有限狀態(tài)機。如果需要管理多個子系統(tǒng)、處理多個事件和狀態(tài),可以考慮使用分層狀態(tài)機。

最重要的是,在實際應用中,理解分層狀態(tài)機的關鍵是正確地設計狀態(tài)轉移邏輯和事件處理函數(shù)。如果狀態(tài)轉移邏輯不正確,可能會導致狀態(tài)機無法正確響應事件;如果事件處理函數(shù)不正確,可能會導致狀態(tài)機無法正確處理事件。因此,在設計分層狀態(tài)機時,需要認真考慮狀態(tài)轉移和事件處理的邏輯,并進行充分的測試和驗證。

代碼參考

有限狀態(tài)機

有限狀態(tài)機可以使用switch/case或if/else語句實現(xiàn)狀態(tài)轉移,并在每個狀態(tài)轉移時執(zhí)行相應的操作。

#include  #include  enum State
{
 ST_IDLE,
 ST_WAIT_SELECT,
 ST_WAIT_PAY,
 ST_DISPENSE
}; enum Button
{
 BTN_NONE,
 BTN_A,
 BTN_B,
 BTN_C
}; enum State current_state = ST_IDLE; enum Button current_button = BTN_NONE; void update_fsm(enum Button button) { switch (current_state)
 { case ST_IDLE: if (button != BTN_NONE)
 {
 current_button = button;
 current_state = ST_WAIT_SELECT; printf("商品選擇: %c\n", button);
 } break; case ST_WAIT_SELECT: if (button == BTN_NONE)
 {
 current_state = ST_WAIT_PAY; printf("等待支付...\n");
 } break; case ST_WAIT_PAY: if (button == BTN_NONE)
 {
 current_state = ST_DISPENSE; printf("出貨中...\n");
 } break; case ST_DISPENSE: if (button == BTN_NONE)
 {
 current_state = ST_IDLE; printf("出售完成\n");
 } break;
 }
} int main() {
 update_fsm(BTN_NONE);
 update_fsm(BTN_A);
 update_fsm(BTN_NONE);
 update_fsm(BTN_NONE);
 update_fsm(BTN_NONE);
 update_fsm(BTN_NONE); return 0;
}

分層狀態(tài)機

而分層狀態(tài)機中由于更加復雜,單純地采用switch/case或if/else語句已經不太適合不同狀態(tài)機及其子狀態(tài)的轉移,最好的方式是采用表驅動的方式去實現(xiàn),然后在數(shù)組表中定義每個狀態(tài)機及其子狀態(tài),并且有回調函數(shù)用來處理每個狀態(tài)機及其子狀態(tài)的處理等,提高系統(tǒng)的可維護性和可擴展性。

由于實現(xiàn)較為復雜,以下代碼僅供參考,不具體實現(xiàn)

#include  #include  #include  // 狀態(tài)機狀態(tài)枚舉 typedef enum {
 STATE_IDLE,
 STATE_WAITING_FOR_COIN,
 STATE_WAITING_FOR_SELECTION,
 STATE_DISPENSING,
 STATE_COUNT
} state_t; // 事件枚舉 typedef enum {
 EVENT_INSERT_COIN,
 EVENT_MAKE_SELECTION,
 EVENT_DISPENSE,
 EVENT_COUNT
} event_t; // 狀態(tài)轉移條件函數(shù)類型定義 typedef bool (*condition_func_t)(void); // 狀態(tài)機狀態(tài)結構體定義 typedef struct { void (*enter_func)(void); // 進入狀態(tài)函數(shù) void (*exit_func)(void); // 退出狀態(tài)函數(shù) void (*poll_func)(void); // 事件輪詢處理函數(shù) condition_func_t (*cond_func)(void); // 轉移條件函數(shù) } state_info_t; // 狀態(tài)轉移表 static const int transition_table[STATE_COUNT][EVENT_COUNT] = { // EVENT_INSERT_COIN    EVENT_MAKE_SELECTION    EVENT_DISPENSE { STATE_WAITING_FOR_COIN, STATE_IDLE,           STATE_IDLE           }, // STATE_IDLE { STATE_WAITING_FOR_COIN, STATE_WAITING_FOR_SELECTION, STATE_IDLE }, // STATE_WAITING_FOR_COIN { STATE_WAITING_FOR_COIN, STATE_WAITING_FOR_SELECTION, STATE_DISPENSING }, // STATE_WAITING_FOR_SELECTION { STATE_WAITING_FOR_COIN, STATE_WAITING_FOR_SELECTION, STATE_IDLE } // STATE_DISPENSING }; // 狀態(tài)機狀態(tài)數(shù)組 static const state_info_t state_table[STATE_COUNT] = { // 進入狀態(tài)函數(shù)            退出狀態(tài)函數(shù)               事件輪詢處理函數(shù)                轉移條件函數(shù) { NULL, NULL, NULL, NULL }, // STATE_IDLE { wait_for_coin_enter, wait_for_coin_exit, wait_for_coin_poll, wait_for_coin }, // STATE_WAITING_FOR_COIN { wait_for_select_enter, wait_for_select_exit, wait_for_select_poll, waiting_for_select }, // STATE_WAITING_FOR_SELECTION { dispensing_enter, dispensing_exit, dispensing_poll, dispensing } // STATE_DISPENSING }; // 當前狀態(tài) static state_t current_state = STATE_IDLE;




本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
關閉