微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

状态机编码 - 我被卡住了

如何解决状态机编码 - 我被卡住了

我正在尝试创建一个状态机,但有点迷茫。请放轻松,我只写了 4 个月的代码

我使用的是 pic16f18325 并在 mplab 中编码

所以我认为我差不多就在那里,我知道我想要它做什么,我已经写了图表等并且认为我已经正确设置了它。我的问题是如何在状态之间切换?如何更改活动?

例如,如果我在主代码中并且我想通过按下按钮来触发 ENTER 事件。我会写:

if (button == 0){ // (button has been defined already)
event = ENTER;
}
void ENTER (void){
// do some stuff
}

mplab 不喜欢“事件”这个词,我遇到了一些我不明白的错误

main.c:33:6: error: redeFinition of 'ENTER' as different kind of symbol
void ENTER (void);
     ^
main.c:26:5: note: prevIoUs deFinition is here
int ENTER; // for entering programming from maincode
    ^
main.c:34:6: error: redeFinition of 'EXIT' as different kind of symbol
void EXIT (void);
     ^
main.c:27:5: note: prevIoUs deFinition is here
int EXIT; // for exiting programming and returning to maincode
    ^
main.c:35:6: error: redeFinition of 'Reset' as different kind of symbol
void Reset (void);
     ^
main.c:28:5: note: prevIoUs deFinition is here
int Reset; // to reset the speed and return to main code
    ^
main.c:36:6: error: redeFinition of 'INCREASE' as different kind of symbol
void INCREASE (void);
     ^
main.c:29:5: note: prevIoUs deFinition is here
int INCREASE; // to increase the speed while in programming
    ^
main.c:37:6: error: redeFinition of 'DECREASE' as different kind of symbol
void DECREASE (void);
     ^
main.c:30:5: note: prevIoUs deFinition is here
int DECREASE; // to decrease the speed while in programming
    ^
main.c:110:36: error: function deFinition is not allowed here
void step_state(enum events event) { // not sure what to write here,will work it out
                                   ^
main.c:145:18: error: function deFinition is not allowed here
void ENTER (void){
                 ^
main.c:148:17: error: function deFinition is not allowed here
void EXIT (void){
                ^
main.c:151:18: error: function deFinition is not allowed here
void Reset (void){
                 ^
main.c:154:21: error: function deFinition is not allowed here
void INCREASE (void){
                    ^
main.c:157:21: error: function deFinition is not allowed here
void DECREASE (void){
                    ^
11 errors generated.

这是我的状态机编码:

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/device_config.h"

int ENTER; // for entering programming from maincode
int EXIT; // for exiting programming and returning to maincode
int Reset; // to reset the speed and return to main code
int INCREASE; // to increase the speed while in programming
int DECREASE; // to decrease the speed while in programming

int events;
void ENTER (void);
void EXIT (void);
void Reset (void);
void INCREASE (void);
void DECREASE (void);


void main(void) {

enum states { // this state machine will have 2 states

    MAINCODE,// main code where it will sit most of the time
    PROGRAMMING,// and then programming which is used to change the speed
} state;

enum events { // we will have 5 events
    ENTER,// for entering programming from maincode
    EXIT,// for exiting programming and returning to maincode
    RESET,// to reset the speed and return to main code
    INCREASE,// to increase the speed while in programming
    DECREASE,// to decrease the speed while in programming
};
void step_state(enum events event) { // not sure what to write here??? what is step_state? why enum events event?
 switch(state) { // the switch is done by a change of state
 case MAINCODE: // while in maincode
  switch(event) { // and the enter event is initiated
  case ENTER: // enter programming
   state = PROGRAMMING; // to do this we change the state
   break; // break to jump into that state

  default: // if something messes up,the default instruction
   state = MAINCODE; // is to go back into the maincode
   break;
  }
  break;

 case PROGRAMMING: // while in programming state
  switch(event) { // and an event is triggered
  case EXIT: // which happens to be exit
   state = MAINCODE; // enter maincode
   break;
  case RESET:
   // add code to revert default speed value
   state = MAINCODE; // then enter maincode
   break;
  case INCREASE:
   // add code for increasing speed
   break;
  case DECREASE:
   // add code for decreasing speed
   break;

  default:
   state = MAINCODE;
   break;
  }
  break;
 }

}

if (button == 0){
event = ENTER;
}
void ENTER (void){
    state = PROGRAMMING;
}
if (button == 0){
event = EXIT;
}
void EXIT (void){
    state = MAINCODE;
}
if (button == 0 && but1 == 0){
event = Reset;
}
void Reset (void){
    value = default;
    state = MAINCODE;
}
if (but1 == 0){
event = INCREASE;
}
void INCREASE (void){
    // add code to increase speed
}
if (but2 == 0){
event = DECREASE;
}
void DECREASE (void){
    // add code to decrease speed
}
    while (1)

    {

    }
    }

解决方法

所以我认为我差不多在那里,[...] 我的问题是如何在状态之间切换?如何更改活动?

您的问题肯定是为什么我会收到所有这些错误?!很明显,您离“几乎在那里”远比您想象的要远得多。首先获得可编译的有效代码(即学习编写有效的 C 代码) - 然后询问如果状态机不工作如何使状态机工作。否则,所有这些其他错误只是一种干扰 - 您甚至还没有接近“几乎在那里”,因为它无法编译,因此您可以运行、测试和调试它。事实上,我将忽略您的问题并解决代码有效性问题。构建工作后,如有必要,提出一个关于如何使其工作的新问题 - 或者更好地使用您的调试器并自行解决。

错误信息看起来很清楚:

main.c:33:6: error: redefinition of 'ENTER' as different kind of symbol
void ENTER (void);
     ^
main.c:26:5: note: previous definition is here
int ENTER; // for entering programming from maincode

第 33 行定义了一个名为 ENTER函数,但 ENTER 之前在第 26 行定义为 int 变量。它告诉你不要两次使用相同的名称(至少不在同一个范围内)。

事实上,符号 ENTER(例如 - 其他符号的相同错误)为不同的事物定义了 三次

一个整数变量

int ENTER; // for entering programming from maincode

一个函数:

void ENTER (void);

枚举常量

enum events { // we will have 5 events
    ENTER,// for entering programming from maincode

对于我们来说,出于多种目的使用相同的符号名称通常是一个坏主意,并且在大多数情况下它是不明确的,因此编译器无法确定使用哪个。

在这种情况下,您应该使用小写或驼峰命名作为函数名称 - 通常大写用于常量。有点不一致的是,您已经有一个 Reset() 函数 - 您在其他地方使用了不同的命名约定。但是请注意,因为 exit() 是标准库中函数的名称。

变量 int ENTER; 和其他类似声明的变量似乎没有被使用,可能可以被删除 - 这样就消除了 enum 常量的歧义。

除此之外,发布的代码不是生成发布错误的代码 - 它还有许多其他问题,并且诊断中的行号引用与发布的代码不一致。具体:

  • 您引用了以下未声明的变量 buttoneventbut1but2value(一个特别糟糕的变量名称 BTW -它们都是“价值观”)。
  • 语句 event = Reset; 无效,event 未定义,但上下文表明它应该是一个 enum events 对象,在这种情况下,可能是使用 RESET 吗?立>
  • 语句 value = default ; 无效,因为 default 是 switch case 标签的保留关键字。不清楚您在这里的意图是什么,因为 value 未定义,这是您唯一引用它的地方。
,

我没有看到有关您的“事件”变量的错误,而且我不知道它是关键字。至于其他错误,您有一些命名空间问题。定义枚举时,它会告诉编译器将指定的关键字用于数字,以帮助使您的源代码更易于维护。枚举隐式地将这些关键字的类型设置为“int”,从而使以下几行变得不必要并导致名称冲突。

int ENTER; // for entering programming from maincode
int EXIT; // for exiting programming and returning to maincode
int Reset; // to reset the speed and return to main code
int INCREASE; // to increase the speed while in programming
int DECREASE; // to decrease the speed while in programming

即使删除了这些行,编译器也会感到困惑,因为您的状态函数与您在“事件”枚举中的状态共享相同的名称。相反,如果您将状态函数重命名为 INCREASE_func()、DECREASE_func() 等,它将解决该问题。 here 是用 C 语言实现的状态机代码的良好来源。

,

您正在尝试重新定义一个已经使用过的符号,例如 ENTER。您不能将变量命名为与方法相同的名称,因为编译器会感到困惑,而且它对任何人也没有多大意义>

你也可以使用枚举类型来创建你的状态机

enum EventType {
     EVENT_NONE,EVENT_EXAMPLE
};

struct State {
     enum EventType last_event;  
};

int main(void) {
   struct State state = { .last_event = EVENT_NONE }

   // do what you want to do....
   {
       if (state.last_event == EVENT_EXAMPLE) {
            // do what you want 
       }
   }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。