如何解决状态机编码 - 我被卡住了
我正在尝试创建一个状态机,但有点迷茫。请放轻松,我只写了 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
常量的歧义。
除此之外,发布的代码不是生成发布错误的代码 - 它还有许多其他问题,并且诊断中的行号引用与发布的代码不一致。具体:
- 您引用了以下未声明的变量
button
、event
、but1
、but2
和value
(一个特别糟糕的变量名称 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 举报,一经查实,本站将立刻删除。