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

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


前言

功能業(yè)務代碼寫多了,回看代碼會發(fā)現(xiàn)用if-else if-else用的越來越多,因為有很多場景需要區(qū)分,不同場景下的功能不一樣,因此需要通過if做判斷,場景一旦多了起來起來,用if-else if-else就會越來越多。

這里的if-else if-else通常是用來區(qū)分不同場景下的功能實現(xiàn),和上篇提到的表驅(qū)動編程還不太一樣。

為了避免這種情況,本編介紹一種開發(fā)方法--狀態(tài)機編程。

為什么需要狀態(tài)機編程?相信很多人在實現(xiàn)if判斷的時候,偶爾會出現(xiàn)不小心漏掉或者寫錯一些觸發(fā)條件,導致功能出現(xiàn)異常的問題,特別是一些復雜的邏輯條件,一大堆的&&/||/()等眼花繚亂的復雜邏輯,寫完之后恐怕自己都得檢查好一會,擔心是不是哪個條件不能正常觸發(fā)。狀態(tài)機通常采用switch-case實現(xiàn)。

那么狀態(tài)機的引入解決了哪些問題呢?

  • 當程序有多個狀態(tài)時,規(guī)范了程序的狀態(tài)轉(zhuǎn)換,避免了一些引入一些復雜的判斷邏輯。

  • 規(guī)范了程序在不同狀態(tài)下的實現(xiàn)和所能提供的能力。

  • 在能力上可以進行橫向擴展,提供新的狀態(tài)來完善現(xiàn)有邏輯

  • 邏輯清楚,實現(xiàn)過程會多考慮一些情況,方便定位問題所在

介紹

什么是狀態(tài)機?

狀態(tài)機是有限狀態(tài)自動機(FSM)的簡稱,是現(xiàn)實事物運行規(guī)則抽象而成的一個數(shù)學模型。

簡單理解就是:現(xiàn)實事物是有不同狀態(tài)的,比如燈,就有“亮”和“滅”兩種狀態(tài),再復雜抽象一點,增加一個“損壞”狀態(tài),那這屬于異常情況了。

概念

  • 現(xiàn)態(tài):當前所處的狀態(tài),一個狀態(tài)機至少要包含兩個狀態(tài),某一時刻只能是一種狀態(tài),比如剛才說到的燈,就有“亮”和“滅”兩種狀態(tài)

  • 條件:又稱事件,執(zhí)行某個操作的觸發(fā)條件或者口令,比如燈通過開關控制,操作開關就是一個事件

  • 動作:事件發(fā)生以后要執(zhí)行動作,比如開關按下開關,燈亮,松開則滅

  • 次態(tài):條件滿足后要遷往的新狀態(tài),比如開關按下后燈從當前滅的狀態(tài)變?yōu)榱恋臓顟B(tài)

用過"RTOS"的朋友應該也知道任務的幾種狀態(tài),任務的四種狀態(tài)分別是:就緒態(tài)、運行態(tài)、阻塞態(tài)、掛起態(tài),不會同時出現(xiàn)兩種及兩種以上的狀態(tài)存在,OS 根據(jù)當前的狀態(tài),和任務優(yōu)先級、滴答時鐘、主動睡眠等條件進行任務的狀態(tài)切換。

狀態(tài)機的動作類型

  • 進入動作:在進入狀態(tài)時進行

  • 退出動作:在退出狀態(tài)時進行

  • 輸入動作:依賴于當前狀態(tài) 和 輸入條件進行

  • 轉(zhuǎn)移動作:在進行特定轉(zhuǎn)移時進行

實現(xiàn)

首先,看一個簡單的例子,在不同場景下實現(xiàn)控制電機的功能:設備開機啟動三次電機、開關按下一次啟動一次、關機啟動三次電機。采用非狀態(tài)機的寫法,通過各種標志位去判斷設備是否需要控制電機,什么條件下退出等。

只是簡單的實現(xiàn)一下,可能其中也有一些狀態(tài)機的思想吧(畢竟狀態(tài)機編程思想已經(jīng)在腦海里,不可避免吧),不過我還是盡量還原我初次編程期間的實現(xiàn)這個功能的邏輯思想吧,勿怪。

/* 控制電機函數(shù) */ void MotorCtrlTask(void) { if (ctrlCnt)
 {
 MotorCtrl(ON);
 delay(1);
 MotorCtrl(OFF);
 } else {
 MotorCtrl(OFF);
 }
} int isPowerOn = true; int isPowerOff = false; int ctrlCnt = 0; void main(void) { while (1)
 { if (isPowerOn)
 {
 isPowerOn = false;
 ctrlCnt = 3;
 } if (keyPress)
 {
 keyPress = false;
 ctrlCnt = 1;
 } if (...) // 關機條件 { if (ctrlCnt == 0 && !isPowerOff && !isPowerOn)
 {
 isPowerOff = true;
 ctrlCnt = 3;
 }
 }

 MotorCtrlTask(); if (ctrlCnt > 0)
 ctrlCnt--; else { if (ctrlCnt == 0 && isPowerOff && !isPowerOn)
 { return;
 }
 }
 }
}

通過采用狀態(tài)機編程的方式,首先考慮的就是有三種狀態(tài):開機、關機和工作狀態(tài),先理清楚三種狀態(tài)之間轉(zhuǎn)換的條件和當前狀態(tài)需要執(zhí)行的相關功能,然而在實現(xiàn)過程中就會意識到還需要增加一種過渡狀態(tài):關機準備中(關機過程中需要執(zhí)行的一系列操作)。

只有邏輯清晰了,才會下意識的察覺少了一些東西了,特別是一些臨界處理等。

int sysState = POWER_OFF; // 默認關機狀態(tài) int ctrlCnt = 0; /* 控制電機函數(shù) */ void MotorCtrlTask(void) { if (ctrlCnt)
 {
 MotorCtrl(ON);
 delay(1);
 MotorCtrl(OFF);
 } else {
 MotorCtrl(OFF);
 }
} void main(void) { while (1)
 { switch (sysState)
 { case POWER_OFF: // 關機狀態(tài) sysState = POWER_ON; // 自動切換成開機狀態(tài) ctrlCnt = 3; break; case POWER_ON: // 開機過程狀態(tài) ... // 開機過程中的其他功能 if (ctrlCnt == 0) // 控制結束自動切換工作狀態(tài) {
 sysState = WORKING; break;
 } break; case WORKING: // 工作狀態(tài) if (...) // 關機條件 {
 sysState = POWER_OFF_READY;
 ctrlCnt = 3; break;
 } if (keyPress)
 {
 keyPress = false;
 ctrlCnt = 1;
 } break; case POWER_OFF_READY: // 關機準備中 ... // 關機準備中的其他功能 if (ctrlCnt == 0) // 控制結束自動退出 {
 sysState = POWER_OFF; return; // 退出程序 } break; default: break;
 }

 MotorCtrlTask(); if (ctrlCnt > 0)
 ctrlCnt--;
 }
}

總結:從上述兩份代碼看,你覺得哪一個邏輯更清晰呢?非狀態(tài)機實現(xiàn)方式還有一些異常處理沒有實現(xiàn),比如開機過程中在啟動三次調(diào)節(jié)電機過程中按下會有什么現(xiàn)象呢,為了避免這種情況又需要加入多少if條件判斷呢?

適用場景

狀態(tài)機應用范圍挺廣的,不止是在C語言中,其他都能使用,準確來說這個屬于一種編程思想。特別是業(yè)務功能,狀態(tài)機是常用的。

比如常常使用的模塊也有狀態(tài)機的身影:比如按鍵的按下和松開,按下又包括按下瞬間、多次按下、持續(xù)按下、松開瞬間和持續(xù)松開等

通常狀態(tài)機和表驅(qū)動可以結合使用,狀態(tài)機的現(xiàn)態(tài)、條件、動作和次態(tài)作為數(shù)據(jù),執(zhí)行這些狀態(tài)切換的作為邏輯。完全可以根據(jù)實際情況靈活使用。


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