首页 > 解决方案 > 用于嵌入式系统的 C++ 事件驱动状态机

问题描述

在 C++ 中实现状态机的最简单方法是什么?

我的第一个想法是创建一个抽象类并从它派生出每个状态机。使用指向函数的指针,我可以跟踪当前状态。

使用派生类的构造函数,我可以设置初始状态。这个例子展示了我将如何做。

派生类中的每个方法都代表一个状态。

下一个出现在我脑海中的设计是使用一个State带有虚函数的类,onEntry, onExit, handleEvent, 和一个指针State * currentState。然而,这种方法很大程度上基于继承,因为每个状态都必须从类派生State。所以,如果我有 50 个州,我将需要 50 个新课程!我猜这很多?

我目前在 C 中的实现只是一个指向结构内函数的指针。在变量下,我只是在同一个文件static state_machine_t state_machine_one中定义了所有功能状态。.c因此,当我想向所有状态机发送一个事件时,我只需将每个结构放入一个指针数组中,然后运行一个循环。这就是我在 C++ 中尝试做的事情。

编辑:系统依赖于分层状态机。当前嵌套级别最多为 8 个状态。并且可执行文件在 Cortex-M0 8MHz - 48MHz 上运行。

标签: c++eventsembeddedstate-machine

解决方案


最简单的状态机是:

#include <functional>
#include <iostream>

template<class...Message>
struct State:
  std::function< State<Message...>( Message... )>
{
    using Base=std::function< State<Message...>( Message... )>;
    using Base::Base;
};
 
int main(){
  State<int> end=[](int x){
     std::cout<<"end\n";
     return nullptr;
  };
  State<int> odd=[&](int x){
    if (x%2) return odd;
    return end;
  };
  State<int> even=[&](int x){
    if (x%2) return odd;
    return even;
  };
  State<int> start=[&](int x){
    std::cout << "Start "<<x<<'\n';
    if (x%2) return odd;
    return even;
  };

    
  int buff[]={0,2,3,5,9,10,33};
  int* inp=buff;
  auto state=start;
  while(state){
    std::cout<<*inp<<'\n';
    state=state(*inp++);    
  }
}
  

状态是一个接收消息并返回新状态的函数。

这没有进入/退出时,也没有不处理消息的状态。如果您的消息是对您可以弹出的队列的引用,您可以轻松地模拟这一点。


推荐阅读