一、要求分析
? ? 利用狀態機程序思想,使用MSP-EXP430F5529 Launchpad板卡實現以下模擬飲水機的功能。
? ? 飲水機是我們生活中常見的家用設備。假設一個簡易的飲水機有兩個按鍵:童鎖按鍵[PUSH1]和熱水按鍵[PUSH2]。
? ? 按鍵功能說明: 1.童鎖按鍵: ①?平時“童鎖按鍵”處于鎖定狀態[RED_LED初始化條件],長按“童鎖按鍵”3秒后進入解鎖狀態[長按PUSH1事件]; ②?如果“童鎖按鍵”處于解鎖狀態,3秒內沒有按下“熱水按鍵”,“童鎖按鍵”回到鎖定狀態[閑置PUSH2事件]。 2.熱水按鍵: ①“童鎖按鍵”處于鎖定狀態時,按下“熱水按鍵”不起作用(不放水)
[無用限制條件]; ②?“童鎖按鍵”處于解鎖狀態時,按“熱水按鍵”(按鍵釋放有效)進入放水狀態,開 始放水[松開PUSH2事件]; ?處于放水狀態時,再次按“熱水按鍵”(按鍵釋放有效),停止放熱水,“童鎖按鍵” 回到鎖定狀態[松開PUSH2事件]; ③?處于放水狀態時,按“童鎖按鍵”不起作用[放水時童鎖一定解鎖,按童鎖鍵是為了解鎖,本身成立]。 ④在解鎖狀態時,長按“熱水按鍵”超過3秒不放,不會自動回到“鎖定狀態”,按“童鎖按鍵”也不起作用。[這里的長按具有迷惑性,根據前面其他描述,恢復鎖定狀態的條件是通過PUSH2未按下時作出閑置響應,但是按下了PUSH2后,PUSH2處于按擊狀態,不用考慮恢復鎖定的問題]?。請設計程序,模擬飲水機的工作。PUSH1為“童鎖按鍵”,PUSH2為“熱水按鍵”;鎖定狀態紅 色LED亮,解鎖狀態紅色LED滅;放水狀態綠色LED亮。
二、完整代碼 (僅供參考!!!)
#include "Timer.h"
int ChildLockState=0; //童鎖狀態,0鎖定,1解鎖
int ChildLockButtonState=0; //童鎖按鍵(PUSH1)狀態,0閑置,1短按,2長按
int WaterState=0; // 放水狀態,0不放水,1放水
int WaterButtonState=0; //熱水按鍵(PUSH2)狀態,0閑置,1按下(不區分短按/長按)
int LastClButton=1;
int CurClButton=1;
int LastWButton=1;
int CurWButton=1;int ClCnt=0; //童鎖按鍵長按計時器
int WCnt_Empty=0; //熱水按鍵閑置計數器void setup() {pinMode(PUSH1,INPUT_PULLUP);pinMode(PUSH2,INPUT_PULLUP);pinMode(RED_LED,OUTPUT);pinMode(GREEN_LED,OUTPUT);digitalWrite(RED_LED,HIGH); //初始童鎖鎖定,紅色LED亮digitalWrite(GREEN_LED,LOW); //初始處于未放水狀態,綠色LED滅SetTimer(irsTimer,20); //設置定時中斷計時器,中斷周期為20msSerial.begin(9600);
}void loop() {}void irsTimer()
{int ClButton=0; //童鎖按鍵瞬時狀態,0無改變,1按下,2松開int WButton=0; //熱水按鍵瞬時狀態,0無改變,1按下,2松開//按鍵消抖,檢測按鍵變化(1、童鎖;2、熱水按鍵)//1、檢測童鎖按鍵變化CurClButton=digitalRead(PUSH1);if(CurClButton!=LastClButton){if(CurClButton==LOW) ClButton=1;else ClButton=2;}//2.檢測熱水按鍵變化CurWButton=digitalRead(PUSH2);if(CurWButton!=LastWButton){if(CurWButton==LOW) WButton=1;else WButton=2;}//檢測按鍵狀態//檢測童鎖按鍵狀態switch(ChildLockButtonState){case 0:if(ClButton==1) {ChildLockButtonState=1; //若按下按鍵,切換為短按狀態ClCnt=0;}break;case 1:if(ClButton==2){ChildLockButtonState=0; //若松開按鍵,切換為閑置狀態ClCnt=0;}else if(ClButton==0) //如果按鍵狀態未改變,則開始計數{ClCnt++;if(ClCnt>=150) //3s/20ms=150{ChildLockButtonState=2; //達到計數門限,切換為長按狀態ClCnt=0;}}break;case 2: //長按童鎖時,解鎖童鎖(不放水狀態時)if(ClButton==0){ChildLockState=1; ChildUnlocked();WCnt_Empty=0;}if(ClButton==2) {ChildLockButtonState=0;}break;}switch(WaterButtonState) {case 0:if(WButton==0){if(WaterState==0&&ChildLockState==1){Serial.println(WCnt_Empty);WCnt_Empty++; if (WCnt_Empty>=150){WCnt_Empty=0;ChildLockState=0; //3s未按熱水按鍵,鎖定童鎖ChildLocked();}}}if(WButton==1)WaterButtonState=1; //若按下按鍵,切換為短按狀態break;case 1:if(WButton==2) //完整短按一次熱水按鍵,若童鎖已解鎖則放水{if(ChildLockState!=0) WaterButtonPush();WaterButtonState=0;WCnt_Empty=0;}break;}LastClButton=CurClButton;LastWButton=CurWButton;}void NoWater()
{digitalWrite(GREEN_LED,LOW);
}void InWater()
{digitalWrite(GREEN_LED,HIGH);
}void ChildLocked()
{digitalWrite(RED_LED,HIGH);
}void ChildUnlocked()
{digitalWrite(RED_LED,LOW);
}void WaterButtonPush()
{//若未放水則開始放水if(WaterState==0){WaterState=1;InWater();}//若已在放水,則將童鎖鎖定,停止放水else{ChildLockState=0;ChildLocked();WaterState=0;NoWater();}
}