在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 中斷多任務(wù)+狀態(tài)機(jī) 單片機(jī)軟件結(jié)構(gòu)設(shè)計

            中斷多任務(wù)+狀態(tài)機(jī) 單片機(jī)軟件結(jié)構(gòu)設(shè)計

            作者: 時間:2016-11-27 來源:網(wǎng)絡(luò) 收藏

            本文引用地址:http://www.biyoush.com/article/201611/322212.htm

            以下是一個鍵盤掃描的例子,這里假設(shè)tick = 20 ms, ScanKeyboard()函數(shù)控制口線的輸出掃描,并檢測輸入轉(zhuǎn)換為鍵碼,利用每個state之間20 ms的間隔去抖動。

            enum EnumKey {

            EnumKey_NoKey =0,

            };

            struct StructKey {

            intkeyValue;

            boolkeyPressed;

            } ;

            struct StructKeyProcess key;

            void ProcessKey() { (*states[state])(); }

            void state0() { }

            void state1() { key.keyPressed = false; state++; }

            void state2() { if (ScanKey() != EnumKey_NoKey) state++; }//next state if a key pressed

            void state3()

            {//debouncing state

            key.keyValue = ScanKey();

            if (key.keyValue == EnumKey_NoKey)

            state--;

            else {

            key.keyPressed = true;

            state++;

            }

            }

            void state4() {if (ScanKey() == EnumKey_NoKey) state++; }//next state if the key released

            void state5() {ScanKey() == EnumKey_NoKey? state = 1 : state--; }

            上面的鍵盤處理過程顯然比通常使用標(biāo)志去抖的程序簡潔清晰,而且沒有軟件延時去抖的困擾。以此類推,各個任務(wù)都可以劃分成一個個的state,每個state實際上占用不多的處理時間。某些任務(wù)可以劃分成若干個子任務(wù),每個子任務(wù)再劃分成若干個狀態(tài)。

            (題外話:對于常數(shù)類型,建議使用enum分類組織,避免使用大量#define定義常數(shù))

            對于一些完全不能分割,必須獨占的任務(wù)來說,比如我以前一個低成本應(yīng)用中紅外遙控器的軟件解碼任務(wù),這時只能犧牲其他的任務(wù)了。兩種做法:一種是關(guān)閉中斷,完全的獨占;

            void RunTaskN()

            {

            Disable_Interrupt;

            Enable_Interrupt;

            }

            第二種,允許定時中斷發(fā)生,保證某些時基register得以更新;

            void Timer_Interrupt()

            {

            SetTimer();

            Enable_Timer_Interrupt;

            UpdateTimingRegisters();

            if (watchDogCounter = 0) {

            ResetStack();

            for (i=0; i

            (*tasks[i])();

            while (1) IDLE;

            }

            else

            watchDogCounter--;

            }

            只要watchDogCounter不為0,那么中斷正常返回到中斷點,繼續(xù)執(zhí)行先前被中斷的任務(wù),否則,復(fù)位stack,重新進(jìn)行任務(wù)循環(huán)。這種狀況下,中斷處理過程極短,對獨占任務(wù)的影響也有限。

            中斷驅(qū)動多任務(wù)配合狀態(tài)機(jī)的使用,我相信這是mcu下無os系統(tǒng)較好的設(shè)計結(jié)構(gòu)。對于絕大多數(shù)mcu程序設(shè)計來說,可以極大的減輕程序結(jié)構(gòu)的安排,無需過多的考慮各個任務(wù)之間的時間安排,而且可以讓程序簡潔易懂。缺點是,程序員必須花費一定的時間考慮如何切分任務(wù)。

            下面是一段用C改寫的CD Player中檢測disc是否存在的偽代碼,用以展示這種結(jié)構(gòu)的設(shè)計技巧,原源代碼為Z8 mcu匯編,基于Sony的DSP, Servo and RF處理芯片,通過送出命令字來控制主軸/滑板/聚焦/尋跡電機(jī),并讀取狀態(tài)以及CD的sub Q碼。這個處理任務(wù)只是一個大任務(wù)下用state machine切開的一個二級子任務(wù),tick = 20 ms。

            state1() { InitializeMotor(); state++; }

            state2() {

            if (innerSwitch != ON) {

            SendCommand(EnumCommand_SlidingMotorBackward);

            timeout = MILLISECOND(10000);

            state++;//滑板電機(jī)向內(nèi)運動,直至觸及最內(nèi)開關(guān)。

            }

            else

            state +=2;

            }

            state3() {

            if ((--timeout) == 0) {//note: some C compliers do not support (--timeout) ==

            SendCommand(EnumCommand_SlidingMotorStop)

            systemErrorCode = EnumErrorCode_InnerSwitch;

            state = 0;// 10 s超時錯誤,

            }

            else {

            if (innerSwitch == ON) {

            SendCommand(EnumCommand _SlidingMotorStop)

            timeout = MILLISECOND(200);// 200ms電機(jī)停止時間

            state++;

            }

            }

            }

            state4() { if ((--timeout) == 0) state++; }//等待電機(jī)完全停止

            state5() {

            SendCommand(EnumCommand_SlidingMotorForward);

            timeout = MILLISECOND(2000);

            state++;

            }//滑板電機(jī)向外運動,脫離inner switch

            state6() {

            if ((--timeout) == 0) {

            SendCommand(EnumCommand_SlidingMotorStop)

            systemErrorCode = EnumErrorCode_InnerSwitch;

            state = 0;// 2 s超時錯誤,

            }

            else {

            if (innerSwitch == OFF) {

            SendCommand(EnumCommand_SlidingMotorStop)

            timeout = MILLISECOND(200);// 200ms電機(jī)停止時間

            state++;

            }

            }

            }

            state7() { state4(); }

            state8() { LaserOn(); state++; retryCounter = 3;}//打開激光器

            state9() {

            SendCommand(FocusUp);

            state++;

            timeout = MILLISECOND(2000);

            }//光頭上舉,檢測聚焦過零3次,判斷cd是否存在

            state10() {

            if (FocusCrossZero){

            systemStatus.Disc = EnumStatus_DiscExist;

            SendCommand(EnumCommand_AutoFocusOn);//有cd,打開自動聚焦。

            state = 0;//本任務(wù)結(jié)束。

            playProcess.state = 1;//啟動play任務(wù)

            }

            else if ((--timeout) == 0) {

            SendCommand(EnumCommand_ FocusClose);//光頭聚焦復(fù)位

            if ((--retryCounter) == 0) {

            systemStatus.Disc = EnumStatus_Nodisc;//無盤

            displayProcess.state = EnumDisplayState_NoDisc;//顯示閃爍的無盤

            LaserOff();

            state = 0;//任務(wù)停止

            }

            else

            state--;//再試

            }

            }

            stateStop() {

            SendCommand(EnumCommand_SlidingMotorStop);

            SendCommand(EnumCommand_FocusClose);

            state = 0;

            }


            上一頁 1 2 下一頁

            評論


            技術(shù)專區(qū)

            關(guān)閉