Python實戰社羣php
Java實戰社羣程序員
長按識別下方二維碼,按需求添加web
掃碼關注添加客服編程
進Python社羣▲微信
掃碼關注添加客服網絡
進Java社羣▲模塊化
做者丨李肖遙
函數
來源丨技術讓夢想更偉大測試
毫無疑問,單片機的萬能語言就是狀態機,在嵌入式單片機編程中,也是咱們經常使用的方法。ui
本文將從最基礎入門的方法幫助你們瞭解狀態機,從我經常使用的2種狀態機編寫方式爲你們慢慢展開。
switch/case的方法來實現
要點
用switch/case的結構配合一個狀態變量,經過修改狀態變量的值來切換狀態。
代碼以下
1//代碼參考網絡 2 3//! 定義狀態名稱與狀態值之間的關係 4#define FSM_START 0x00 5#define FSM_STATE_A 0x01 6#define FSM_STATE_B 0x02 7… 8#define FSM_RESET 0xFF 9 10bool fsm_example_A( <形參列表> ) { 11 static uint8_t s_chFSMState = FSM_START;//!< 定義狀態變量 12 … 13 switch ( s_chFSMState ) { 14 case FSM_START: 15 //! 這裏添加狀態機初始化代碼 16 … 17 s_chFSMState = FSM_STATE_A;//!< 進入下一狀態 18 break; 19 case FSM_STATE_A: 20 //! 這裏添加狀態機A進入下一狀態的檢測代碼 21 if (<某某條件>) { 22 //! 這裏作一些進入下一狀態時要作的準備工做 23 s_chFSMState = FSM_STATE_B;//!< 進入下一狀態 24 } 25 break; 26 case FSM_STATE_B: 27 //! 這裏添加狀態機A進入下一狀態的檢測代碼 28 if (<某某條件>) { 29 //! 這裏作一些進入下一狀態時要作的準備工做 30 s_chFSMState = FSM_STATE_A;//!< 進入下一狀態 31 } else if (<某某條件>) { 32 } else if (<某某條件>) { 33 … 34 } else { 35 } 36 break; 37 … 38 case FSM_STOP: 39 case FSM_RESET: 40 default: 41 //! 這裏添加狀態機復位相關的代碼 42 … 43 chFSMState = FSM_START;//!< 狀態機復位 44 //! 返回false表示狀態機已經不須要繼續運行了 45 return false; 46 } 47 48 //! 返回true表示狀態機正在運行 49 return true; 50}
小結
從代碼可知,這種狀態機就是一路走到黑,沒有讓多個狀態同時處於激活狀態,也就是說在同一時刻,只能處於一種狀態之下。
無疑,實際中有不少這樣的應用,好比簡單的燈的開關,固然也有不少狀況是多種狀態並存的,好比天氣的狀態就能夠分爲晴天、陰天、風雨雷電等等,能夠同時處於多個狀態。
通用的if/else來了
要點
用if else…else if結構的組合來描述狀態流程圖。
範例
1//代碼參考網絡 2//! 首先將布爾量的狀態標誌壓縮在一個字節裏面以節省內存開支 3typedef union { 4 uint8_t Value; 5 uint8_t Byte; 6 struct { 7 unsigned BIT0:1; 8 unsigned BIT1:1; 9 unsigned BIT2:1; 10 unsigned BIT3:1; 11 unsigned BIT4:1; 12 unsigned BIT5:1; 13 unsigned BIT6:1; 14 unsigned BIT7:1; 15 }Bits; 16}byte_t; 17 18#define FSM_ACTION_FLAG s_tbState.Bits 19#define FSM_STOP_ALL_ACTIONS() do {s_tbState.Value = 0;}while(0) 20#define FSM_START (0 == s_tbState.Value) 21#define FSM_STATE_A FSM_ACTION_FLAG.BIT0 22#define FSM_STATE_B FSM_ACTION_FLAG.BIT1 23… 24#define FSM_STATE_H FSM_ACTION_FLAG.BIT7 25 26bool fsm_example_B( <</span>形參列表> ) { 27 static byte_t s_tbState = {0};//!< 定義狀態變量 28 29 if (FSM_START) { //!< 起始狀態 30 //! 這裏放置狀態機初始化的代碼 31 … 32 FSM_STATE_A = true; //!< 進入狀態B,start裝臺自動結束 33 } 34 35 if (FSM_STATE_A) { //!< 一個典型的簡單狀態 36 //! 這裏放置狀態A的代碼或者 37 … 38 //! 這裏放置某些條件以開啓別的狀態 39 if (<</span>某些條件>) { 40 //! 這裏作一些「進入」下一個狀態以前的準備工做 41 FSM_STATE_B = true; //!< 開啓下一個狀態 42 FSM_STATE_A = false; //!< 結束當前狀態 43 } 44 } 45 46 if (FSM_STATE_B) { //!< 一個典型的監視狀態 47 … 48 //! 這裏檢測某些條件 49 if (<</span>某些條件>) { 50 //! 這裏作一些「開啓」某個狀態的準備工做 51 FSM_STATE_C = true; //!< 開啓某一個狀態而不結束當前狀態 52 FSM_STATE_D = true; //!< 你固然能夠一次觸發多個狀態 53 … 54 } else if (<</span>某些條件>) { 55 //! 知足某些條件之後關閉當前狀態 56 FSM_STATE_B = false; 57 } 58 } 59 … 60 if (FSM_STATE_F) { //!< 一個典型的子狀態機調用 61 if (!fsm_example_a(<實參列表>)) {//!< 等待子狀態機返回false 62 //!子狀態機運行完成,進入下一狀態 63 … 64 FSM_STATE_F = false; //!< 結束當前狀態 65 FSM_STATE_x = true; //!< 進入下一狀態x表明某個字母 66 } 67 } 68 69 if (FSM_STATE_H) { //!< 一個典型的停止狀態 70 //!< 某些狀態機的操做,好比釋放某些資源 71 … 72 FSM_STOP_ALL_ACTIONS(); //!< 復位狀態機 73 return false; //!< 返回false表示狀態機結束 74 } 75 76 return true; //!< 返回true表示狀態機保持運行 77}
小結
從範例可知,這種狀態機雖然看起來比較費腦子,可是在應用當中很是靈活,經過布爾變量的開啓和關閉,你能夠自由的控制某些狀態的開啓。
而且同一時刻可能有多個狀態是激活的,這種結構幾乎能夠翻譯任何流程圖。
全部的函數均可以看做是狀態機
要點
全部的函數均可以看做是狀態機,若是函數有返回值,且這個返回值能表徵至少兩種以上不一樣的狀態,那麼這些返回值就能夠被用做指示當前狀態機的運行狀況。
在咱們實際編程中,咱們也須要有這樣的思惟,好比函數之間的引用,參數傳遞,這些均可以看成一個狀態,那麼咱們編碼的過程當中,就可以根據狀態運行進行相應的模塊化。
範例
咱們常常會用到的枚舉類型,來寫測試用例,以判斷程序具體執行到函數體的哪一塊了
1enum 2{ 3 test1=0, 4 test2, 5 test3, 6 test4, 7 ... 8} 9 10//舉個簡單的例子,根據返回值判斷函數運行到哪裏,來判斷邏輯走向 11int testDemo() 12{ 13 if (FSM_STATE_A) { 14 if (<</span>某些條件>) { 15 return test1; 16 }else{ 17 return test2; 18 } 19 }else{ 20 return test3; 21 } 22 return test4; 23}
小結
狀態機能夠說是一個萬能的計算機語言表述方式,應用很普遍,是裸機條件下多任務的廉價實現方案。
狀態機總結
在帶有操做系統的狀況下也是如此,咱們瞭解了狀態機的本質,可以運用得當的話,對咱們的模塊化編程,代碼的整理是頗有幫助的。
程序員專欄 掃碼關注填加客服 長按識別下方二維碼進羣
近期精彩內容推薦:
在看點這裏好文分享給更多人↓↓