0%

单片机编程——状态机

以下内容均摘自参考文献

状态机建模

状态机(State Machine),也叫有限状态机(Finite State Machine),简称状态机,状态机的概念来源于时序逻辑电路,又细分为 Mealy 状态机和 Moore 状态机,两者的区别在于是否只根据状态就能得出输出结果。

单片机中借用了这两种状态机的思想,引申出“状态中判断事件”和“事件中查询状态”两种单片机状态机的编程方法。


上图是一个通用的状态转换图框架,所有状态机都可以基于该框架进行扩展,Event 相当于事件检测函数检测出的事件,Action 相当于事件处理函数,且上图表达了以下信息:

  1. 状态 State 的个数至少 2 个,多则不限,一般为有限多个,所以称为有限状态机。
  2. 并非所有 State 之间都有 Event 转换路径,比如 State0 → State1,State2 → State0 就没有。
  3. 同样的 State 转换,可能由不同的 Event 引发。
  4. 同样的 Event 未必触发同样的 Action。
  5. Event 可以同时引起 State 变化,并触发 Action。
  6. Event 也可以只触发 Action,而不引起 State 的变化。
  7. Event 还可以只引起 State 的变化,而不触发任何 Action。

状态中判断事件

对图中的状态机进行编程,可以采用 State 状态中判断 Event 事件的方法。这种方法类似于 Mealy 型状态机(不完全等同),即在 switch 语句中还需判断 Event 才能决定输出的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//---------状态中查询事件(Mealy状态机)-----------
switch(State)
{
case 0: if(Event_0) Action2(); //路径1
if(Event_1) { State = 2; Action0(); } //路径2
if(Event_2) State = 2; //路径3
break;
case 1: if(Event_0) State = 2; //路径4
if(Event_2) { State = 0; Action2(); } //路径5
break;
case 2: if(Event_1) { State = 1; Action1(); } //路径6
break;
default: break;
}

事件中查询状态

对图中的状态机进行编程,也可以采用 Event 事件中查询 State 状态的方法。这种方法类似于 Moore 型状态机(不完全等同),在 switch 语句中,即无需再判断 Event, 由当前状态就知道结果。
其中,if(Event) 表达的含义是,无论用什么方法,只要能判断 Event 发生了,并不仅限于字面理解用 if 查询 Event,还包括直接在中断中判断 Event 的情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//---------状态中查询事件(Moore状态机)-----------
if(Event0) //中断或扫描得知Event0事件发生
{
switch(State)
{
case 0: Action2(); break; //路径1
case 1: State = 2; break; //路径5
default: break;
}
}
if(Event1) //中断或扫描得知Event1事件发生
{
switch(State)
{
case 0: State = 2; Action0(); break;` //路径3
case 1: state = 1; Action1(); break; //路径6
default: break;
}
}
if(Event2) //中断或扫描得知Event2事件发生
{
switch(State)
{
case 0: State = 2; break; //路径4
case 1: State = 0; Action2(); break; //路径2
default: break;
}
}

两种状态机的区别

在时序逻辑电路中,Moore 状态机和 Mealy 状态机都可以用来描述任何状态机,并且两种状态机也可以互相转换。在单片机的编程中,刚刚举例,也证明了事件中查询状态和状态中查询事件都可以用来描述状态机。那么这两种方法有什么优缺点呢?

  1. 如果 Event 直接由中断引发,不需要 if 语句轮询就能判断,则用 Moore 型状态机(事件中查询状态)执行速度快。这是因为只需执行对应 Event 的 switch(State) 语句,而且 switch 中只需对 State 进行判断就可以输出结果了。
  2. 如果 Event 本身就需要轮询才能得出,则使用 Mealy 型状态机(状态中查询事件)的代码要简单。因为状态中查询事件只有一个 switch(State) 语句。

参考文献

从零开启大学生电子设计之路:基于 MSP430 LaunchPad 口袋实验平台 / 杨艳,傅强编著. --北京:北京航空航天大学出版社,2014.8