有限状态机器代码在μC中属于哪里?

时间:2017-06-03 20:09:03

标签: c microcontroller state-machine

我在EE论坛上问了this question。 StackOverflow上的你们对编码的了解比我们对EE的了解更多,所以也许你可以提供更多有关这方面的详细信息:)

当我了解微控制器时,老师教会我总是用while(1);结束代码,而不在该循环内代码。

这是为了确保软件“卡住”以保持中断工作。当我问他们是否可以在这个无限循环中放入一些代码时,他们告诉我这是一个坏主意。知道了,我现在尽力将这个循环保持为空。

我现在需要在微控制器中实现有限状态机。在第一个视图中,似乎该代码属于此循环。这使编码更容易。

这是个好主意吗?有什么优点和缺点?

这是我打算做的事情:

void main(void)
{
    // init phase

 while(1)
 {
    switch(current_State)
    {
    case 1:
        if(...)
        {
            current_State = 2;
        }
        else(...)
        {
            current_State = 3;
        }
        else
            current_State = 4;
        break;

    case 2:
        if(...)
        {
            current_State = 3;
        }
        else(...)
        {
            current_State = 1;
        }
        else
            current_State = 5;
        break;
   }
}

而不是:

 void main(void)
    {
        // init phase

     while(1);
    }

使用中断管理FSM

4 个答案:

答案 0 :(得分:4)

就像在一个地方回归所有功能,或其他习惯。您可能希望执行此类设计,一种纯粹基于中断/事件的设计。有些产品完全相反,被轮询甚至没有被驱动。以及介于两者之间的任何事情。

重要的是做你的系统工程,就是​​它,故事的结尾。中断增加了复杂性和风险,它们比不使用它们的价格更高。自动进行任何设计中断驱动自动是一个错误的决定,只是意味着没有投入设计,要求风险等。

理想情况下,您希望在主循环中使用大部分代码,您希望中​​断精简并且意味着为了保持其他时间关键任务的延迟。并非所有MCU都有一个复杂的中断优先级系统,可以让您节省大量时间或将所有应用程序都放在处理程序中。输入您的系统工程,可能有助于选择mcu,但在这里再次增加了风险。

你必须问问自己你的mcu要做的任务是什么,如果从事件发生到每个任务有任何延迟,直到他们必须开始响应,直到他们必须完成,每个事件/任务是什么如果它的任何部分可以推迟。在完成任务时是否可以中断,可能会有时间间隔。您将为硬件设计或cpld或fpga设计所做的所有问题。除了你在那里有真正的并行性。

在现实世界的解决方案中你可能最终得到的是中断处理程序中的某些部分以及主(无限)循环中的某些部分。主循环轮询由中断和/或直接轮询状态寄存器留下的面包屑,以知道循环期间要做什么。如果/当你到达你需要实时的地方时你仍然可以使用主超级循环,你的实时响应来自循环的可能路径以及任何这些路径的最坏情况时间。

大多数时候你不需要做这么多工作。也许有些中断,可能是一些轮询,还有一个主循环做了一定比例的工作。

正如你应该从EE世界中知道,如果一位老师/其他人说只有一种方法可以做某事而其他一切都是错误的......那么找时间找一位新老师并假装喝酒-aid,通过课程继续你的生活。还要注意课堂体验不是现实世界。有很多事情可以在MCU开发中出错,你真的在​​一个受控沙箱中,理想情况下你只能使用几个变量,这样你就不用花费数年的时间来尝试通过几个月的课程。他们在课堂上陈述的一些规则是让你通过课堂和/或让老师通过课堂,如果你告诉人们一个功能不能大于X或没有任何东西,那么更容易评分。当课程结束或添加到您的生命周期清单时,您应该做的第一件事就是质疑所有这些规则。研究并尝试自己,陷入陷阱并挖掘出来。

答案 1 :(得分:1)

在进行嵌入式编程时,一个常用的习惯是使用“超级循环” - 一个无限循环,它在初始化完成后开始,在程序需要运行时调度程序的各个组件。在这个范例下,你可以按照你的建议在超级循环中运行有限状态机,并继续从中断上下文中运行硬件管理功能,因为它听起来就像你已经在做的那样。这样做的一个缺点是你的处理器总是处于高功耗状态 - 因为你总是运行那个循环,处理器永远不会进入睡眠状态。这实际上也是你编写的任何代码中的问题 - 即使是空的无限while循环也会使处理器保持运行。对此的解决方案通常是通过一系列指令结束您的while循环,以使处理器进入低功耗状态(完全取决于架构),当中断通过处理时将唤醒它。如果FSM中发生的事情不是由任何中断驱动的,那么通常用于保持处理器定期唤醒的方法是初始化定时器以定期中断以使主循环继续执行。 / p>

另外需要注意的是,如果您之前从中断上下文执行了所有代码 - 中断服务程序(ISR)确实应该尽可能短,因为它们实际上是“中断”程序的主要执行,如果长时间使用可能会导致意外的副作用。处理这种情况的一种常用方法是在超级循环中使用只由ISR发出信号的处理程序,这样需要完成的大部分处理都是在有时间的情况下在主上下文中完成的,而不是中断主要背景的潜在时间关键部分。

答案 2 :(得分:0)

您应该实现的是您的选择和调试代码的简易性。 有时候使用while(1)是正确的;如果您的uC将完全处理中断(ISR),则在代码末尾的语句。在某些其他应用程序中,uC将与无限循环内的代码一起使用(称为轮询方法):

while(1) 
{

//code here;

} 

在其他一些应用程序中,您可以将ISR方法与轮询方法混合使用。

当说'调试容易'时,仅使用ISR方法(在末尾放置while(1);语句),将使你很难调试代码,因为当触发中断事件时,选择的调试器不会给你一步一步的事件登记阅读和跟随。此外,请注意,不建议写入完整的ISR代码,因为ISR事件应该进行最少的编码(例如递增计数器,提升/清除标记,例如)并且能够快速退出。

答案 3 :(得分:-1)

它属于一个线程,它执行它以响应来自生产者 - 消费者队列的输入消息。所有中断等都会向队列发送输入,并且线程会通过其FSM串行处理它们。

这是我发现避免破坏性混乱的唯一方法,同时保留了中断驱动I / O的低延迟和高效CPU使用。

'而(1);' UGH!