chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

嵌入式軟件架構(gòu)設(shè)計(jì)之狀態(tài)機(jī)

汽車電子技術(shù) ? 來源:大橙子瘋嵌入式 ? 作者:大橙子瘋 ? 2023-02-15 15:49 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言

功能業(yè)務(wù)代碼寫多了,回看代碼會發(fā)現(xiàn)用if-else if-else用的越來越多,因?yàn)橛泻芏鄨鼍靶枰獏^(qū)分,不同場景下的功能不一樣,因此需要通過if做判斷,場景一旦多了起來起來,用if-else if-else就會越來越多。

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

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

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

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

  • 當(dāng)程序有多個(gè)狀態(tài)時(shí),規(guī)范了程序的狀態(tài)轉(zhuǎn)換,避免了一些引入一些復(fù)雜的判斷邏輯。
  • 規(guī)范了程序在不同狀態(tài)下的實(shí)現(xiàn)和所能提供的能力。
  • 在能力上可以進(jìn)行橫向擴(kuò)展,提供新的狀態(tài)來完善現(xiàn)有邏輯
  • 邏輯清楚,實(shí)現(xiàn)過程會多考慮一些情況,方便定位問題所在

介紹

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

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

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

概念

  • 現(xiàn)態(tài):當(dāng)前所處的狀態(tài),一個(gè)狀態(tài)機(jī)至少要包含兩個(gè)狀態(tài),某一時(shí)刻只能是一種狀態(tài),比如剛才說到的燈,就有“亮”和“滅”兩種狀態(tài)
  • 條件:又稱事件,執(zhí)行某個(gè)操作的觸發(fā)條件或者口令,比如燈通過開關(guān)控制,操作開關(guān)就是一個(gè)事件
  • 動(dòng)作:事件發(fā)生以后要執(zhí)行動(dòng)作,比如開關(guān)按下開關(guān),燈亮,松開則滅
  • 次態(tài):條件滿足后要遷往的新狀態(tài),比如開關(guān)按下后燈從當(dāng)前滅的狀態(tài)變?yōu)榱恋臓顟B(tài)

圖片

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

狀態(tài)機(jī)的動(dòng)作類型

  • 進(jìn)入動(dòng)作:在進(jìn)入狀態(tài)時(shí)進(jìn)行
  • 退出動(dòng)作:在退出狀態(tài)時(shí)進(jìn)行
  • 輸入動(dòng)作:依賴于當(dāng)前狀態(tài) 和 輸入條件進(jìn)行
  • 轉(zhuǎn)移動(dòng)作:在進(jìn)行特定轉(zhuǎn)移時(shí)進(jìn)行

實(shí)現(xiàn)

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

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

/* 控制電機(jī)函數(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 (...)  // 關(guān)機(jī)條件
        {
            if (ctrlCnt == 0 && !isPowerOff && !isPowerOn)
            {
                isPowerOff = true;
                ctrlCnt = 3;
            }
        }

        MotorCtrlTask();

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

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

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

int sysState = POWER_OFF; // 默認(rèn)關(guān)機(jī)狀態(tài)
int ctrlCnt = 0;

/* 控制電機(jī)函數(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: // 關(guān)機(jī)狀態(tài)
                sysState = POWER_ON; // 自動(dòng)切換成開機(jī)狀態(tài)
                ctrlCnt = 3;
                break;
            case POWER_ON:  // 開機(jī)過程狀態(tài)
                ... // 開機(jī)過程中的其他功能

                if (ctrlCnt == 0) // 控制結(jié)束自動(dòng)切換工作狀態(tài)
                {
                    sysState = WORKING;
                    break;
                }
                break;
            case WORKING:  // 工作狀態(tài)
                if (...) // 關(guān)機(jī)條件
                {
                    sysState = POWER_OFF_READY;
                    ctrlCnt = 3;
                    break;
                }

                if (keyPress)
                {
                    keyPress = false;
                    ctrlCnt = 1;
                }
                break;

            case POWER_OFF_READY:  // 關(guān)機(jī)準(zhǔn)備中
                ... // 關(guān)機(jī)準(zhǔn)備中的其他功能

                if (ctrlCnt == 0) // 控制結(jié)束自動(dòng)退出
                {
                    sysState = POWER_OFF;
                    return; // 退出程序
                }
                break;

            default:
                break;
        }

        MotorCtrlTask();

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

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

適用場景

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

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

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

代碼參考:

菜單 :菜單控制,可以這樣理解:當(dāng)前菜單界面為現(xiàn)態(tài)、菜單進(jìn)入和退出為條件、菜單切換時(shí)的函數(shù)執(zhí)行為動(dòng)作、上下級菜單理解為次態(tài),其中菜單選項(xiàng)表就靈活使用了狀態(tài)機(jī)和表驅(qū)動(dòng)的方式。

https://gitee.com/const-zpc/menu.git

ESP8266 :AT指令數(shù)據(jù)表,包含指令、期望響應(yīng)、時(shí)間和函數(shù)指針【后續(xù)的動(dòng)作】等,可以這樣理解:數(shù)組索引當(dāng)前值為現(xiàn)態(tài)、收到響應(yīng)和超時(shí)為條件、收到響應(yīng)或超時(shí)執(zhí)行的函數(shù)為動(dòng)作、數(shù)組索引的未來值為次態(tài)

https://gitee.com/const-zpc/esp8266
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 狀態(tài)機(jī)
    +關(guān)注

    關(guān)注

    2

    文章

    493

    瀏覽量

    28237
  • fsm
    fsm
    +關(guān)注

    關(guān)注

    0

    文章

    35

    瀏覽量

    12978
  • 數(shù)學(xué)模型
    +關(guān)注

    關(guān)注

    0

    文章

    83

    瀏覽量

    12260
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    嵌入式狀態(tài)機(jī)的幾種大牛才懂的操作

    狀態(tài)機(jī)嵌入式軟件中隨處可見,可能你會說狀態(tài)機(jī)有什么難的,不就是 switch 嗎? switch僅僅是最基礎(chǔ)的一個(gè)點(diǎn),關(guān)于狀態(tài)機(jī)的更多操作
    發(fā)表于 11-17 10:41 ?1721次閱讀
    <b class='flag-5'>嵌入式</b><b class='flag-5'>狀態(tài)機(jī)</b>的幾種大牛才懂的操作

    嵌入式軟件開發(fā)中常用的狀態(tài)機(jī)編程實(shí)現(xiàn)

    嵌入式軟件開發(fā)中,狀態(tài)機(jī)編程是一個(gè)十分重要的編程思想,它也是嵌入式開發(fā)中一個(gè)常用的編程框架。掌握了狀態(tài)機(jī)編程思想,可以更加邏輯清晰的實(shí)現(xiàn)復(fù)
    發(fā)表于 09-06 10:25 ?2734次閱讀

    為何要進(jìn)行嵌入式軟件架構(gòu)設(shè)計(jì)?如何設(shè)計(jì)?

    為何要進(jìn)行嵌入式軟件架構(gòu)設(shè)計(jì)?如何進(jìn)行嵌入式軟件架構(gòu)設(shè)計(jì)?
    發(fā)表于 11-01 06:31

    嵌入式狀態(tài)機(jī)編程的概念是什么

    干貨 | 嵌入式狀態(tài)機(jī)編程干貨篇文章描述了基本的狀態(tài)機(jī)編程概念,感覺還可以。如果在搭上事件驅(qū)動(dòng)框架,就可以寫一個(gè)簡單的RTOS了,這個(gè)OS可以作為一種不可剝奪型內(nèi)核。...
    發(fā)表于 12-22 06:25

    嵌入式軟件架構(gòu)設(shè)計(jì)資料分享

    作為程序員,我覺得如果要走的更遠(yuǎn)必須要成為工程師,畢竟年齡和資歷都擺在那里了。所以就讓我這個(gè)老程序員淺談一下嵌入式軟件架構(gòu)設(shè)計(jì)。我參考的也是一篇博文。原圖如下![在這里插入圖片描述](?x-oss-process=image/w
    發(fā)表于 12-24 07:09

    狀態(tài)機(jī)嵌入式系統(tǒng)中的應(yīng)用

    為了便于研究和描述狀態(tài)機(jī)嵌入式前后臺軟件系統(tǒng)中的應(yīng)用,本文將以移動(dòng)2G光纖直放站近端機(jī)的監(jiān)控軟件案例來闡述和說明。
    發(fā)表于 05-23 10:48 ?2396次閱讀
    <b class='flag-5'>狀態(tài)機(jī)</b>在<b class='flag-5'>嵌入式</b>系統(tǒng)中的應(yīng)用

    嵌入式軟件架構(gòu)設(shè)計(jì)

    嵌入式軟件架構(gòu)的設(shè)計(jì),幫助我們建立合理,有效的軟件架構(gòu)。
    發(fā)表于 11-09 17:34 ?19次下載

    嵌入式軟件狀態(tài)機(jī)的抽象與實(shí)現(xiàn)

    文中提出了 在嵌入式軟件中把狀態(tài)機(jī)作為一個(gè)獨(dú)立模塊從控制模塊中抽象出來的思想 , 描述了 抽象出來的狀態(tài)機(jī)模塊 。 并介紹了 如何將這種狀態(tài)機(jī)
    發(fā)表于 03-22 15:47 ?1次下載

    有限狀態(tài)機(jī)嵌入式系統(tǒng)中的實(shí)現(xiàn)及應(yīng)用

    如何使嵌入式軟件代碼更加可靠 增強(qiáng)程序的可維護(hù)性 一直以來都是嵌入式程序員追 求的目標(biāo)。論述了有限狀態(tài)機(jī)的原理和其實(shí)現(xiàn)方法;采用狀態(tài)機(jī)方法編
    發(fā)表于 03-22 15:40 ?1次下載

    有限狀態(tài)機(jī)嵌入式軟件中的應(yīng)用

    有限狀態(tài)機(jī)嵌入式軟件中的應(yīng)用,感興趣的小伙伴們可以看看。
    發(fā)表于 07-26 10:43 ?27次下載

    嵌入式UI架構(gòu)設(shè)計(jì)漫談

    嵌入式UI架構(gòu)設(shè)計(jì)漫談
    發(fā)表于 11-03 17:36 ?15次下載
    <b class='flag-5'>嵌入式</b>UI<b class='flag-5'>架構(gòu)設(shè)</b>計(jì)漫談

    嵌入式狀態(tài)機(jī)的設(shè)置

    狀態(tài)機(jī)嵌入式軟件中隨處可見,可能你會說狀態(tài)機(jī)有什么難的,不就是 switch 嗎?
    的頭像 發(fā)表于 11-02 09:04 ?1369次閱讀

    嵌入式狀態(tài)機(jī)的編程優(yōu)點(diǎn)分析

    嵌入式狀態(tài)機(jī)編程是真的好用,寫出來的程序結(jié)構(gòu)非常清晰!所以平時(shí)用的也比較多。
    的頭像 發(fā)表于 02-25 16:21 ?1068次閱讀

    嵌入式狀態(tài)機(jī)的設(shè)計(jì)與實(shí)現(xiàn)

    嵌入式狀態(tài)機(jī)是一種常用的軟件設(shè)計(jì)模式,它能夠提高代碼的可讀性和可維護(hù)性。狀態(tài)機(jī)是一個(gè)抽象的概念,它描述了一個(gè)系統(tǒng)或者組件的不同狀態(tài)以及在不同
    的頭像 發(fā)表于 04-14 11:55 ?2280次閱讀

    C語言實(shí)現(xiàn)嵌入式狀態(tài)機(jī)簡單描述與應(yīng)用

    嵌入式狀態(tài)機(jī)是一種常用的軟件設(shè)計(jì)模式,它能夠提高代碼的可讀性和可維護(hù)性。
    發(fā)表于 05-20 14:52 ?1951次閱讀