我正在尝试在两个不同的功能中使用两个switch case语句来通过串行包控制微控制器,但是其中一个功能不会切换,并且程序会无限期地循环。功能之一根据enum
切换:
enum class State {
example_a,
example_b,
example_c
};
void serialTask(State stateArg, ObjectA exampleA, ObjectB exampleB, ObjectC exampleC, ObjectD exampleD) {
switch (stateArg) {
case State::example_a:
Serial.println("Serial Task, example a");
exampleA.doSomething();
stateArg = State::example_a;
break;
case State::example_b:
Serial.println("Serial Task, example b");
exampleB.doSomething();
stateArg = State::example_b;
break;
case State::example_c:
Serial.println("Serial Task, example c");
exampleC.doSomething();
stateArg = State::example_c;
break;
}
};
我将所有其他对象作为参数,因为根据情况我调用了它们的函数或修改了它们的成员。
另一个功能根据串行端口切换enum
的值:
void stateSwitch(State stateArg) {
if (Serial.available()) {
uint8_t code = Serial.read();
switch (code) {
case 'a':
stateArg = State::example_a;
break;
case 'b':
stateArg = State::example_b;
break;
case 'c':
stateArg = State::example_c;
break;
}
};
他们后来在我的main.cpp
中被这样叫:
ObjectA aObj;
ObjectB bObj;
ObjectC cObj;
ObjectD dObj;
volatile State stateObj;
void setup(){
stateObj = State::example_a;
Serial.begin(115200);
};
void loop(){
stateSwitch(stateObj);
serialTask(stateObj, aObj, bObj, cObj, dObj);
};
这是问题的简化版本,但它说明了这一点。该程序可以编译,但是由于某种原因它不能跳出State::example_a
。我正在将Teensy微控制器与PlatformIO(Visual Studio的扩展)中的Arduino框架配合使用。谢谢您的帮助。
stateArg
传递到stateSwitch
。这意味着正在制作副本,而您正在修改副本;不是原始的。
void serialTask(State stateArg, ...
stateArg = State::example_a; // affects local copy only
这是按值传递的,因此将为该函数创建一个副本。它不会将任何更改回显到原始变量。为此,您需要通过引用传递它:
void serialTask(State &stateArg, ... stateArg = State::example_a; // affects variable used in call
注意,在所有要更改变量的函数中(因此stateSwitch
以及serialTask
),您都需要按引用传递。通过示例,请注意以下内容:
#include <iostream> void procA(int num) { num = 7; } void procB(int &num) { num = 42; } int main() { int num = 1; std::cout << num << '\n'; procA(num); std::cout << num << '\n'; procB(num); std::cout << num << '\n'; }
这将导致三行1
,1
和42
,因为对procA
的调用是传递值,不会影响传递的变量,仅会影响它的本地副本。另一方面,
procB
被传递引用,does更改了传递的变量。]>还要注意,无论您是通过值传递还是引用传递,调用都是相似的。您无需以任何方式更改通话。
您may
也想研究这些事情背后的逻辑:case State::example_a: // current state Serial.println("Serial Task, example a"); exampleA.doSomething(); stateArg = State::example_a; // why set to same/original state? break;
状态机将状态强制返回执行事件之前的值是非常不寻常的。可以,因为我们看不到您的所有代码,但我要小心一点。may