色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

狀態機的基本術語 傳統有限狀態機Fsm實現方法

STM32嵌入式開發 ? 來源:CSDN-取經的孫猴兒 ? 2023-09-08 09:56 ? 次閱讀

狀態機基本術語

現態:是指當前所處的狀態。條件:又稱為“事件”,當一個條件被滿足,將會觸發一個動作,或者執行一次狀態的遷移。動作:條件滿足后執行的動作。動作執行完畢后,可以遷移到新的狀態,也可以仍舊保持原狀態。

動作不是必需的,當條件滿足后,也可以不執行任何動作,直接遷移到新狀態。次態:條件滿足后要遷往的新狀態。“次態”是相對于“現態”而言的,“次態”一旦被激活,就轉變成新的“現態”了。 02b5f0bc-4de4-11ee-a25d-92fbcf53809c.png

傳統有限狀態機Fsm實現方法

02fa9956-4de4-11ee-a25d-92fbcf53809c.png ????

如圖,是一個定時計數器,計數器存在兩種狀態,一種為設置狀態,一種為計時狀態

設置狀態



“+” “-” 按鍵對初始倒計時進行設置當計數值設置完成,點擊確認鍵啟動計時 ,即切換到計時狀態



計時狀態



按下“+” “-” 會進行密碼的輸入。“+”表示1 ,“-”表示輸入0 ,密碼共有4位

確認鍵:只有輸入的密碼等于默認密碼,按確認鍵才能停止計時,否則計時直接到零,并執行相關操作


嵌套switch


      /***************************************
      1.列出所有的狀態
      ***************************************/
      typedef enum{
          SETTING,
          TIMING
      }STATE_TYPE;
      /***************************************
      2.列出所有的事件
      ***************************************/
      typedef enum{
         UP_EVT,
          DOWN_EVT,
          ARM_EVT,
          TICK_EVT
      }EVENT_TYPE;
      /***************************************
      3.定義和狀態機相關結構
      ***************************************/
      struct  bomb
      {
          uint8_t state;
          uint8_t timeout;
          uint8_t code;
          uint8_t defuse_code;
      }bomb1;
      /***************************************
      4.初始化狀態機
      ***************************************/
      void bomb1_init(void)
{
          bomb1.state = SETTING;
          bomb1.defuse_code = 6;    //0110 
      }
      /***************************************
      5. 狀態機事件派發
      ***************************************/
      void bomb1_fsm_dispatch(EVENT_TYPE evt ,void* param)
{
          switch(bomb1.state)
          {
              case SETTING:
              {
                  switch(evt)
                  {
                      case UP_EVT:    // "+"   按鍵按下事件
                        if(bomb1.timeout< 60)  ++bomb1.timeout;
                          bsp_display(bomb1.timeout);
                      break;
                      case DOWN_EVT:  // "-"   按鍵按下事件
                          if(bomb1.timeout > 0)  --bomb1.timeout;
                          bsp_display(bomb1.timeout);
                      break;
                      case ARM_EVT:   // "確認" 按鍵按下事件
                          bomb1.state = TIMING;
                          bomb1.code  = 0;
                      break;
                  }
              } break; 
              case TIMING:
              {
                  switch(evt)
                  {
                      case UP_EVT:    // "+"   按鍵按下事件
                         bomb1.code = (bomb1.code <<1) |0x01;
                      break;
                      case DOWN_EVT:  // "-"   按鍵按下事件
                          bomb1.code = (bomb1.code <<1); 
                      break;
                      case ARM_EVT:   // "確認" 按鍵按下事件
                          if(bomb1.code == bomb1.defuse_code){
                              bomb1.state = SETTING;
                          }
                          else{
                           bsp_display("bomb!")
                          }
                      break;
                      case TICK_EVT:
                          if(bomb1.timeout)
                          {
                              --bomb1.timeout;
                              bsp_display(bomb1.timeout);
                          }
                          if(bomb1.timeout == 0)
                          {
                              bsp_display("bomb!")
                          }
                      break;
                  }   
              }break;
          }
      }

030c227a-4de4-11ee-a25d-92fbcf53809c.png



優點:



簡單,代碼閱讀連貫,容易理解



缺點:

當狀態或事件增多時,代碼狀態函數需要經常改動,狀態事件處理函數會代碼量會不斷增加

狀態機沒有進行封裝,移植性差。

沒有實現狀態的進入和退出的操作。進入和退出在狀態機中尤為重要

進入事件:只會在剛進入時觸發一次,主要作用是對狀態進行必要的初始化

退出事件:只會在狀態切換時觸發一次 ,主要的作用是清除狀態產生的中間參數,為下次進入提供干凈環境

狀態表




二維狀態轉換表



狀態機可以分為狀態和事件 ,狀態的躍遷都是受事件驅動的,因此可以通過一個二維表格來表示狀態的躍遷。 03259160-4de4-11ee-a25d-92fbcf53809c.png

(*) 僅當( code == defuse_code) 時才發生到setting 的轉換。


      /*1.列出所有的狀態*/
      enum
      {
          SETTING,
          TIMING,
          MAX_STATE
      };
      /*2.列出所有的事件*/
      enum
      {
          UP_EVT,
          DOWN_EVT,
          ARM_EVT,
          TICK_EVT,
          MAX_EVT
      };
      
      /*3.定義狀態表*/
      typedef void (*fp_state)(EVT_TYPE evt , void* param);
      static  const fp_state  bomb2_table[MAX_STATE][MAX_EVENT] =
      {
          {setting_UP , setting_DOWN , setting_ARM , null},
          {setting_UP , setting_DOWN , setting_ARM , timing_TICK}
      };
      
      struct bomb_t
      {
          const fp_state const *state_table; /* the State-Table */
          uint8_t state; /* the current active state */
          
          uint8_t timeout;
          uint8_t code;
          uint8_t defuse_code;
      };
      struct bomb bomb2=
      {
          .state_table = bomb2_table;
      }
      void bomb2_init(void)
{
          bomb2.defuse_code = 6; // 0110
          bomb2.state = SETTING;
      }
      
      void bomb2_dispatch(EVT_TYPE evt , void* param)
{
          fp_state  s = NULL;
          if(evt > MAX_EVT)
          {
              LOG("EVT type error!");
              return;
          }
          s = bomb2.state_table[bomb2.state * MAX_EVT + evt];
          if(s != NULL)
          {
              s(evt , param);
          }
      }
      /*列出所有的狀態對應的事件處理函數*/
      void setting_UP(EVT_TYPE evt, void* param)
{
          if(bomb1.timeout< 60)  ++bomb1.timeout;
          bsp_display(bomb1.timeout);
      }

優點:

各個狀態面向用戶相對獨立,增加事件和狀態不需要去修改先前已存在的狀態事件函數。

可將狀態機進行封裝,有較好的移植性函數指針的安全轉換 , 利用下面的特性,用戶可以擴展帶有私有屬性的狀態機和事件而使用統一的基礎狀態機接口

typedef void (*Tran)(struct StateTableTag *me, Event const *e);
void Bomb2_setting_ARM (Bomb2 *me, Event const *e);
typedef struct Bomb
{
   struct StateTableTag *me;  //必須為第一個成員
    uint8_t private;
}



缺點:

函數粒度太小是最明顯的一個缺點,一個狀態和一個事件就會產生一個函數,當狀態和事件較多時,處理函數將增加很快,在閱讀代碼時,邏輯分散。

沒有實現進入退出動作。



一維狀態轉換表

0346254c-4de4-11ee-a25d-92fbcf53809c.png ????實現原理:
0360b72c-4de4-11ee-a25d-92fbcf53809c.png

 typedef void (*fp_action)(EVT_TYPE evt,void* param);
    
    /*轉換表基礎結構*/
    struct tran_evt_t
    {
       EVT_TYPE evt;
        uint8_t next_state;
    };
    /*狀態的描述*/
    struct  fsm_state_t
    {
        fp_action  enter_action;      //進入動作
        fp_action  exit_action;   //退出動作
        fp_action  action;           
        
        tran_evt_t* tran;    //轉換表
        uint8_t     tran_nb; //轉換表的大小
        const char* name;
    }
    /*狀態表本體*/
    #define  ARRAY(x)   x,sizeof(x)/sizeof(x[0])
    const struct  fsm_state_t  state_table[]=
    {
        {setting_enter , setting_exit , setting_action , ARRAY(set_tran_evt),"setting" },
        {timing_enter , timing_exit , timing_action , ARRAY(time_tran_evt),"timing" }
    };
    
    /*構建一個狀態機*/
    struct fsm
    {
        const struct state_t * state_table; /* the State-Table */
        uint8_t cur_state;                      /* the current active state */
        
        uint8_t timeout;
        uint8_t code;
        uint8_t defuse_code;
    }bomb3;
    
    /*初始化狀態機*/
    void  bomb3_init(void)
{
        bomb3.state_table = state_table;  //指向狀態表
        bomb3.cur_state = setting;
        bomb3.defuse_code = 8; //1000
    }
    /*狀態機事件派發*/
    void  fsm_dispatch(EVT_TYPE evt , void* param)
{
        tran_evt_t* p_tran = NULL;
        
        /*獲取當前狀態的轉換表*/
        p_tran = bomb3.state_table[bomb3.cur_state]->tran;
        
        /*判斷所有可能的轉換是否與當前觸發的事件匹配*/
        for(uint8_t i=0;ievt == evt)//事件會觸發轉換
            {
                if(NULL != bomb3.state_table[bomb3.cur_state].exit_action){
              bomb3.state_table[bomb3.cur_state].exit_action(NULL);  //執行退出動作
             }
                if(bomb3.state_table[_tran[i]->next_state].enter_action){
                   bomb3.state_table[_tran[i]->next_state].enter_action(NULL);//執行進入動作
                }
                /*更新當前狀態*/
                bomb3.cur_state = p_tran[i]->next_state;
            }
            else
            {
                 bomb3.state_table[bomb3.cur_state].action(evt,param);
            }
        }
    }
    /*************************************************************************
    setting狀態相關
    ************************************************************************/
    void setting_enter(EVT_TYPE evt , void* param)
{
        
    }
    void setting_exit(EVT_TYPE evt , void* param)
{
        
    }
    void setting_action(EVT_TYPE evt , void* param)
{
        
    }
    tran_evt_t set_tran_evt[]=
    {
        {ARM , timing},
    }
    /*timing 狀態相關*/


優點:

各個狀態面向用戶相對獨立,增加事件和狀態不需要去修改先前已存在的狀態事件函數。

實現了狀態的進入和退出

容易根據狀態躍遷圖來設計 (狀態躍遷圖列出了每個狀態的躍遷可能,也就是這里的轉換表)

實現靈活,可實現復雜邏輯,如上一次狀態,增加監護條件來減少事件的數量。可實現非完全事件驅動



缺點:

函數粒度較小(比二維小且增長慢),可以看到,每一個狀態需要至少3個函數,還需要列出所有的轉換關系。



QP嵌入式實時框架


特點:



事件驅動型編程



好萊塢原則:和傳統的順序式編程方法例如“超級循環”,或傳統的RTOS 的任務不同。絕大多數的現代事件驅動型系統根據好萊塢原則被構造,(Don’t call me; I’ll call you.)


面向對象



類和單一繼承。 03845d12-4de4-11ee-a25d-92fbcf53809c.png


工具



QM ,一個通過UML類圖來描述狀態機的軟件,并且可以自動生成C代碼: 039a66de-4de4-11ee-a25d-92fbcf53809c.png ??

QS軟件追蹤工具: 03d62fca-4de4-11ee-a25d-92fbcf53809c.png0459b106-4de4-11ee-a25d-92fbcf53809c.png



QEP實現有限狀態機Fsm

0489ec54-4de4-11ee-a25d-92fbcf53809c.png

    /* qevent.h ----------------------------------------------------------------*/
      typedef struct QEventTag 
      {  
        QSignal sig;     
       uint8_t dynamic_;  
      } QEvent;
      /* qep.h -------------------------------------------------------------------*/
      typedef uint8_t QState; /* status returned from a state-handler function */
      typedef QState (*QStateHandler) (void *me, QEvent const *e); /* argument list */
      typedef struct QFsmTag   /* Finite State Machine */
      { 
        QStateHandler state;     /* current active state */
      }QFsm;
      
      #define QFsm_ctor(me_, initial_) ((me_)->state = (initial_))
      void QFsm_init (QFsm *me, QEvent const *e);
      void QFsm_dispatch(QFsm *me, QEvent const *e);
      
      #define Q_RET_HANDLED ((QState)0)
      #define Q_RET_IGNORED ((QState)1)
      #define Q_RET_TRAN ((QState)2)
      #define Q_HANDLED() (Q_RET_HANDLED)
      #define Q_IGNORED() (Q_RET_IGNORED)
      
       #define Q_TRAN(target_) (((QFsm *)me)->state = (QStateHandler)   (target_),Q_RET_TRAN)
      
      enum QReservedSignals
      {
          Q_ENTRY_SIG = 1, 
        Q_EXIT_SIG, 
        Q_INIT_SIG, 
        Q_USER_SIG 
      };
      
      /* file qfsm_ini.c ---------------------------------------------------------*/
      #include "qep_port.h" /* the port of the QEP event processor */
      #include "qassert.h" /* embedded systems-friendly assertions */
      void QFsm_init(QFsm *me, QEvent const *e) 
{
          (*me->state)(me, e); /* execute the top-most initial transition */
       /* enter the target */
        (void)(*me->state)(me , &QEP_reservedEvt_[Q_ENTRY_SIG]);
      }
      /* file qfsm_dis.c ---------------------------------------------------------*/
      void QFsm_dispatch(QFsm *me, QEvent const *e)
{
          QStateHandler s = me->state; /* save the current state */
        QState r = (*s)(me, e); /* call the event handler */
        if (r == Q_RET_TRAN)  /* transition taken? */
          {
          (void)(*s)(me, &QEP_reservedEvt_[Q_EXIT_SIG]); /* exit the source */
          (void)(*me->state)(me, &QEP_reservedEvt_[Q_ENTRY_SIG]);/*enter target*/
       }
      }
  //實現上面定時器例子
      #include "qep_port.h" /* the port of the QEP event processor */
      #include "bsp.h" /* board support package */
      
      enum BombSignals /* all signals for the Bomb FSM */
      { 
          UP_SIG = Q_USER_SIG,
          DOWN_SIG,
          ARM_SIG,
          TICK_SIG
      };
      typedef struct TickEvtTag 
      {
        QEvent super;      /* derive from the QEvent structure */
        uint8_t fine_time; /* the fine 1/10 s counter */
      }TickEvt;
      
      typedef struct Bomb4Tag 
      {
        QFsm super;   /* derive from QFsm */
        uint8_t timeout; /* number of seconds till explosion */
         uint8_t code;    /* currently entered code to disarm the bomb */
         uint8_t defuse;  /* secret defuse code to disarm the bomb */
      } Bomb4;
      
      void Bomb4_ctor (Bomb4 *me, uint8_t defuse);
      QState Bomb4_initial(Bomb4 *me, QEvent const *e);
      QState Bomb4_setting(Bomb4 *me, QEvent const *e);
      QState Bomb4_timing (Bomb4 *me, QEvent const *e);
      /*--------------------------------------------------------------------------*/
      /* the initial value of the timeout */
      #define INIT_TIMEOUT 10
      /*..........................................................................*/
      void Bomb4_ctor(Bomb4 *me, uint8_t defuse) {
       QFsm_ctor_(&me->super, (QStateHandler)&Bomb4_initial);
        me->defuse = defuse; /* the defuse code is assigned at instantiation */
      }
      /*..........................................................................*/
      QState Bomb4_initial(Bomb4 *me, QEvent const *e) {
       (void)e;
       me->timeout = INIT_TIMEOUT;
       return Q_TRAN(&Bomb4_setting);
      }
      /*..........................................................................*/
      QState Bomb4_setting(Bomb4 *me, QEvent const *e) {
       switch (e->sig){
        case UP_SIG:{
         if (me->timeout < 60) {
          ++me->timeout;
          BSP_display(me->timeout);
         }
                  return Q_HANDLED();
        }
        case DOWN_SIG: {
         if (me->timeout > 1) {
          --me->timeout;
          BSP_display(me->timeout);
         }
         return Q_HANDLED();
        }
        case ARM_SIG: {
         return Q_TRAN(&Bomb4_timing); /* transition to "timing" */
        }
       }
       return Q_IGNORED();
      }
      /*..........................................................................*/
      void Bomb4_timing(Bomb4 *me, QEvent const *e) {
       switch (e->sig) {
        case Q_ENTRY_SIG: {
         me->code = 0; /* clear the defuse code */
         return Q_HANDLED();
              }
        case UP_SIG: {
         me->code <<= 1;
         me->code |= 1;
         return Q_HANDLED();
              }
        case DOWN_SIG: {
         me->code <<= 1;
         return Q_HANDLED();
        }
        case ARM_SIG: {
         if (me->code == me->defuse) {
          return Q_TRAN(&Bomb4_setting);
         }
         return Q_HANDLED();
        }
        case TICK_SIG: {
         if (((TickEvt const *)e)->fine_time == 0) {
          --me->timeout;
          BSP_display(me->timeout);
          if (me->timeout == 0) {
          BSP_boom(); /* destroy the bomb */
          }
         }
         return Q_HANDLED();
        }
       }
       return Q_IGNORED();
      }



優點:



采用面向對象的設計方法,很好的移植性


實現了進入退出動作



合適的粒度,且事件的粒度可控



狀態切換時通過改變指針,效率高


可擴展成為層次狀態機



缺點:


對事件的定義以及事件粒度的控制是設計的最大難點,如串口接收到一幀數據,這些變量的更新單獨作為某個事件,還是串口收到數據作為一個事件。再或者顯示屏,如果使用此種編程方式,如何設計事件。



QP 實現層次狀態機 Hsm簡介

049d76de-4de4-11ee-a25d-92fbcf53809c.png初始化 04b2d808-4de4-11ee-a25d-92fbcf53809c.png


初始化層次狀態機的實現:在初始化時,用戶所選取的狀態永遠是最底層的狀態,如上圖,我們在計算器開機后,應該進入的是開始狀態,這就涉及到一個問題,由最初top(頂狀態)到begin 是有一條狀態切換路徑的,當我們設置狀態為begin如何搜索這條路徑成為關鍵(知道了路徑才能正確的進入begin,要執行路徑中過渡狀態的進入和退出事件)

void QHsm_init(QHsm *me, QEvent const *e) 
{
     Q_ALLEGE((*me->state)(me, e) == Q_RET_TRAN);
        t = (QStateHandler)&QHsm_top; /* HSM starts in the top state */
      do { /* drill into the target... */
      QStateHandler path[QEP_MAX_NEST_DEPTH_];
       int8_t ip = (int8_t)0; /* transition entry path index */
       path[0] = me->state; /* 這里的狀態為begin */
            
            /*通過執行空信號,從底層狀態找到頂狀態的路徑*/
        (void)QEP_TRIG_(me->state, QEP_EMPTY_SIG_);
        while (me->state != t) {
         path[++ip] = me->state;
       (void)QEP_TRIG_(me->state, QEP_EMPTY_SIG_);
      }
            /*切換為begin*/
       me->state = path[0]; /* restore the target of the initial tran. */
      /* 鉆到最底層的狀態,執行路徑中的所有進入事件 */
        Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
      do { /* retrace the entry path in reverse (desired) order... */
          QEP_ENTER_(path[ip]); /* enter path[ip] */
       } while ((--ip) >= (int8_t)0);
            
        t = path[0]; /* current state becomes the new source */
       } while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN);
      me->state = t;
    }

狀態切換

04c6c1ec-4de4-11ee-a25d-92fbcf53809c.png

 /*.................................................................*/
    QState result(Calc *me, QEvent const *e) 
{
        switch (e->sig) 
        {you
            case ENTER_SIG:{
                break;
            }
            case EXIT_SIG:{
             break;
            }
         case C_SIG: 
            {
          printf("clear");    
                return Q_HANDLED();
            }
            case B_SIG:
            {  
                return Q_TRAN(&begin);
            }
     }
     return Q_SUPER(&reday);
    }
    /*.ready為result和begin的超狀態................................................*/
    QState ready(Calc *me, QEvent const *e) 
{
        switch (e->sig) 
        {
            case ENTER_SIG:{
                break;
            }
            case EXIT_SIG:{
             break;
            }
            case OPER_SIG:
            {  
                return Q_TRAN(&opEntered);
            }
     }
     return Q_SUPER(&on);
    }






    void QHsm_dispatch(QHsm *me, QEvent const *e) 
{
        QStateHandler path[QEP_MAX_NEST_DEPTH_];
     QStateHandler s;
     QStateHandler t;
     QState r;
     t = me->state;     /* save the current state */
     do {       /* process the event hierarchically... */
      s = me->state;
      r = (*s)(me, e);   /* invoke state handler s */
     } while (r == Q_RET_SUPER); //當前狀態不能處理事件 ,直到找到能處理事件的狀態
        
     if (r == Q_RET_TRAN) {     /* transition taken? */
      int8_t ip = (int8_t)(-1);   /* transition entry path index */
      int8_t iq;       /* helper transition entry path index */
      path[0] = me->state;    /* save the target of the transition */
         path[1] = t;
      while (t != s) {   /* exit current state to transition source s... */
       if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {/*exit handled? */
        (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); /* find superstate of t */
       }
       t = me->state;   /* me->state holds the superstate */
      }
      . . .
     }
     me->state = t;     /* set new state or restore the current state */
    }

04ecb05a-4de4-11ee-a25d-92fbcf53809c.png
 t = path[0]; /* target of the transition */
        if (s == t) { /* (a) check source==target (transition to self) */
             QEP_EXIT_(s) /* exit the source */
             ip = (int8_t)0; /* enter the target */
         }
         else {
             (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); /* superstate of target */
             t = me->state;
             if (s == t) { /* (b) check source==target->super */
                  ip = (int8_t)0; /* enter the target */
            }
             else {
                 (void)QEP_TRIG_(s, QEP_EMPTY_SIG_); /* superstate of src */
                 /* (c) check source->super==target->super */
                 if(me->state == t) {
                     QEP_EXIT_(s) /* exit the source */
                     ip = (int8_t)0; /* enter the target */
                  }
                  else {
                       /* (d) check source->super==target */
                       if (me->state == path[0]) {
                          QEP_EXIT_(s) /* exit the source */
                       }
                       else { /* (e) check rest of source==target->super->super..
                           * and store the entry path along the way */
                        ....

QP實時框架的組成

05015d98-4de4-11ee-a25d-92fbcf53809c.png05228a54-4de4-11ee-a25d-92fbcf53809c.png


內存管理



使用內存池,對于低性能mcu,內存極為有限,引入內存管理主要是整個架構中,是以事件作為主要的任務通信手段,且事件是帶參數的,可能相同類型的事件會多次觸發,而事件處理完成后,需要清除事件,無法使用靜態的事件,因此是有必要為不同事件創建內存池的。

對于不同塊大小的內存池,需要考慮的是每個塊的起始地址對齊問題。在進行內存池初始化時,我們是根據blocksize+header大小來進行劃分內存池的。假設一個2字節的結構,如果以2來進行劃分,假設mcu 4字節對齊,那么將有一半的結構起始地址無法對齊,這時需要為每個塊預留空間,保證每個塊的對齊。 05463ba2-4de4-11ee-a25d-92fbcf53809c.png


事件隊列



每一個活動對象維護一個事件隊列,事件都是由基礎事件派生的,不同類型的事件只需要將其基礎事件成員添加到活動對象的隊列中即可,最終在取出的時候通過一個強制轉換便能獲得附加的參數。 05677b00-4de4-11ee-a25d-92fbcf53809c.png



事件派發



直接事件發送:

QActive_postLIFO()



發行訂閱事件發送:

豎軸表示信號(為事件的基類)

活動對象支持64個優先級,每一個活動對象要求擁有唯一優先級

通過優先級的bit位來表示某個事件被哪些活動對象訂閱,并在事件觸發后根據優先級為活動對象派發事件。

0584d59c-4de4-11ee-a25d-92fbcf53809c.png

定時事件



非有序鏈表:
05a9bc5e-4de4-11ee-a25d-92fbcf53809c.png ????合作式調度器QV: 05bb992e-4de4-11ee-a25d-92fbcf53809c.png


QP nano的簡介

完全支持層次式狀態嵌套,包括在最多4 層狀態嵌套情況下,對任何狀態轉換拓撲的可保證的進入/ 退出動作

支持高達8 個并發執行的,可確定的,線程安全的事件隊列的活動對象57

支持一個字節寬( 255 個信號)的信號,和一個可伸縮的參數,它可被配置成0 (沒有參數), 1 , 2 或4 字節

使用先進先出FIFO排隊策略的直接事件派發機制

每個活動對象有一個一次性時間事件(定時器),它的可配置動態范圍是0(沒有時間事件) , 1 , 2 或4 字節

內建的合作式vanilla 內核

內建的名為QK-nano 的可搶占型RTC內核(見第六章6.3.8節)

帶有空閑回調函數的低功耗架構,用來方便的實現節省功耗模式。

在代碼里為流行的低端CPU架構的C編譯器的非標準擴展進行了準備(例如,在代碼空間分配常數對象,可重入函數,等等)

基于斷言的錯誤處理策略

代碼風格: 05da9ee6-4de4-11ee-a25d-92fbcf53809c.png05fb1842-4de4-11ee-a25d-92fbcf53809c.png06120e80-4de4-11ee-a25d-92fbcf53809c.png0651ebf4-4de4-11ee-a25d-92fbcf53809c.png067fef54-4de4-11ee-a25d-92fbcf53809c.png ?   

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 計數器
    +關注

    關注

    32

    文章

    2259

    瀏覽量

    94860
  • 有限狀態機
    +關注

    關注

    0

    文章

    52

    瀏覽量

    10357
  • 狀態機
    +關注

    關注

    2

    文章

    492

    瀏覽量

    27614
  • fsm
    fsm
    +關注

    關注

    0

    文章

    35

    瀏覽量

    12835

原文標題:QP狀態機框架與常見狀態機方法 | 長文收藏

文章出處:【微信號:c-stm32,微信公眾號:STM32嵌入式開發】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    如何去實現有限狀態機FSM的程序設計呢

    什么是有限狀態機FSM呢?如何去實現有限狀態機FSM的程序設計呢?
    發表于 01-21 07:04

    fsm有限狀態機pdf

    利用 VHDL 設計的許多實用邏輯系統中,有許多是可以利用有限狀態機的設計方案來描述和實現的。無論與基于 VHDL的其它設計方案相比,還是與可完成相似功能的 CPU 相比,狀
    發表于 06-04 10:33 ?75次下載

    有限狀態機_FSM_的實現

    本文主要介紹了IP模塊的有限狀態機實現
    發表于 03-22 15:42 ?0次下載

    有限狀態機FSM在PLD中的實現分析

    本文通過舉例 利用VHDL 語言描述了不同模式的有限狀態機 分析了有限狀態機在 PLD 中綜合的特點 。
    發表于 03-22 15:41 ?3次下載

    有限狀態機的建模與優化設計

    本文提出一種優秀 、高效的 Verilog HDL 描述方式來進行有限狀態機設計 介紹了 有限狀態機的建模原則 并通過一個可綜合的實例 驗證了 該方法設計的有限狀態機在面積和功耗上的優
    發表于 03-22 15:19 ?1次下載

    VHDL有限狀態機設計-ST

    EDA的有限狀態機,廣義而言是指只要涉及觸發器的電路,無論電路大小都可以歸結為狀態機有限狀態機設計在學習EDA時是很重要的一章。
    發表于 06-08 16:46 ?3次下載

    初學者對有限狀態機FSM)的設計的認識

    有限狀態機FSM)是一種常見的電路,由時序電路和組合電路組成。設計有限狀態機的第一步是確定采用Moore狀態機還是采用Mealy狀態機
    發表于 02-11 13:51 ?4348次閱讀
    初學者對<b class='flag-5'>有限狀態機</b>(<b class='flag-5'>FSM</b>)的設計的認識

    使用函數指針的方法實現狀態機

    之前寫過一篇狀態機的實用文章,很多朋友說有幾個地方有點難度不易理解,今天給大家換種簡單寫法,使用函數指針的方法實現狀態機狀態機簡介 有限狀態機
    的頭像 發表于 10-19 09:36 ?2434次閱讀
    使用函數指針的<b class='flag-5'>方法</b><b class='flag-5'>實現狀態機</b>

    如何使用FPGA實現序列檢測有限狀態機

    有限狀態機是絕大部分控制電路的核心結構, 是表示有限狀態以及在這些狀態之間轉移和動作等行為的數學模型。有限狀態機是指輸出取決于過去輸入部分
    發表于 11-04 17:17 ?12次下載
    如何使用FPGA<b class='flag-5'>實現</b>序列檢測<b class='flag-5'>有限狀態機</b>

    基于事件驅動的有限狀態機介紹

    ? 一、介紹 EFSM(event finite state machine,事件驅動型有限狀態機),是一個基于事件驅動的有限狀態機,主要應用于嵌入式設備的軟件系統中。 EFSM的設計原則是:簡單
    的頭像 發表于 11-16 15:29 ?2376次閱讀

    基于事件驅動的有限狀態機介紹

    EFSM(event finite state machine,事件驅動型有限狀態機),是一個基于事件驅動的有限狀態機,主要應用于嵌入式設備的軟件系統中。
    的頭像 發表于 02-11 10:17 ?1075次閱讀

    Verilog狀態機的類型

    有限狀態機(Finite-State Machine,FSM),簡稱狀態機,是表示有限狀態以及在這些
    的頭像 發表于 06-01 15:23 ?1948次閱讀
    Verilog<b class='flag-5'>狀態機</b>的類型

    有限狀態機分割設計

    有限狀態機分割設計,其實質就是一個狀態機分割成多個狀態機
    的頭像 發表于 10-09 10:47 ?669次閱讀

    什么是狀態機狀態機的種類與實現

    狀態機,又稱有限狀態機(Finite State Machine,FSM)或米利狀態機(Mealy Machine),是一種描述系統狀態變化
    的頭像 發表于 10-19 10:27 ?9914次閱讀

    什么是有限狀態機?如何解決傳統有限狀態機狀態爆炸」問題?

    有限狀態機(Finite State Machine,簡稱FSM)是一種用來進行對象行為建模的工具,其作用主要是描述對象在它的生命周期內所經歷的狀態序列以及如何響應來自外界的各種事件。
    的頭像 發表于 02-17 16:09 ?6327次閱讀
    什么是<b class='flag-5'>有限狀態機</b>?如何解決<b class='flag-5'>傳統</b><b class='flag-5'>有限狀態機</b>「<b class='flag-5'>狀態</b>爆炸」問題?
    主站蜘蛛池模板: 精品AV亚洲乱码一区二区| 2021乱码精品公司| 父亲猜女儿在线观看| 亚洲综合日韩在线2019| 99re这里只有精品视频| 被黑人做的白浆直流| 亚洲国产综合久久精品| 性直播免费| 3a丝袜论坛| 国产精品久久久久婷婷五月色婷婷 | 中文无码第3页不卡av| 鬼灭之刃花街篇免费樱花动漫| WWW国产亚洲精品久久久日本| 国产极品白嫩超清在线观看| 国产成人综合在线| 国产精品成人免费视频99| 久久学生精品国产自在拍| 久久九九日本韩国精品| 久久精品综合网中文字幕| 丝瓜涩涩屋黄瓜香蕉丝瓜| 中文字幕久久久| 国产专区青青草原亚洲| 国产自拍视频在线一区| 人妖xxhdxx| 在线不卡日本v二区到六区| 国产精品久久久久久久久久免费| 老师好爽你下面水好多视频| 小泽玛丽av无码观看| 被肉日常np高h| 免费在线亚洲视频| 一本道无码v亚洲| 国产人妻777人伦精品HD| 精品国产在线亚洲欧美| 色淫阁色九九| 一本道久在线综合色姐| 国产欧美日韩国产高清| 三级全黄的视频| 亚洲无线观看国产| av天堂电影网在线观看| 国产精品免费观看视频播放| 强开乳罩摸双乳吃奶视频|