一、要求分析
利用状态机程序思想,使用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();}
}