我正在使用 Arduino 为我的学校项目制作一个反应游戏,我想使用附加中断来注册我的按钮按下操作,但我所做的功能不会在我试图制作的附加中断语句中声明。这是我第一次使用基于对象的编程,所以我还没有完全习惯它的工作原理。
#include <Arduino.h>
// Game class
/**
* The Game class represents a reaction game that can be played between two players.
*
* The game starts when any button is pressed. The RGB LED will turn red for a random
* amount of time, and then turn green. The first player to press their button when the
* RGB LED turns green will win the round. The winner's indicator LED and the RGB LED will
* flash rapidly several times, and a fanfare will play from the buzzer. If a player presses
* their button before the RGB LED turns green, they will lose the round and their indicator
* LED and the RGB LED will flash rapidly several times, and a failure sound will play from
* the buzzer. The class takes in the pin numbers for the buttons, LEDs, RGB LED, and buzzer
* as parameters in the constructor. The class provides methods to start the game, blink the
* winner LED, blink the RGB LED, and randomize the lights.
*/
class Game {
private:
bool started; // Whether the game has started
bool over; // Whether the game is over
int winner; // The winner of the game (1 or 2)
int reactionTime; // The reaction time of the winner
unsigned long startTime; // The start time of the game
int button1Pin;
int button2Pin;
int led1Pin;
int led2Pin;
int redPin;
int greenPin;
int bluePin;
int buzzerPin;
int player1Score;
int player2Score;
public:
Game(int b1, int b2, int l1, int l2, int r, int g, int b, int bz) {
button1Pin = b1;
button2Pin = b2;
led1Pin = l1;
led2Pin = l2;
redPin = r;
greenPin = g;
bluePin = b;
buzzerPin = bz;
started = false;
over = false;
winner = 0;
reactionTime = 0;
player1Score = 0;
player2Score = 0;
pinMode(button1Pin, INPUT_PULLUP);
pinMode(button2Pin, INPUT_PULLUP);
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(button1Pin), button1Pressed, FALLING);
attachInterrupt(digitalPinToInterrupt(button2Pin), button2Pressed, FALLING);
}
void start() {
Serial.println("Press any button to start the game");
while (!digitalRead(button1Pin) && !digitalRead(button2Pin)) {
// Wait for button press
}
started = true;
Serial.println("Game started!");
}
void blinkWinnerLed() {
if (over) {
if (winner == 1) {
digitalWrite(led1Pin, HIGH);
delay(100);
digitalWrite(led1Pin, LOW);
digitalWrite(redPin, LOW);
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, LOW);
for (int i = 0; i < 5; i++) {
digitalWrite(led1Pin, HIGH);
digitalWrite(greenPin, HIGH);
digitalWrite(bluePin, HIGH);
delay(100);
digitalWrite(led1Pin, LOW);
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, LOW);
delay(100);
}
} else if (winner == 2) {
digitalWrite(led2Pin, HIGH);
delay(100);
digitalWrite(led2Pin, LOW);
digitalWrite(redPin, LOW);
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, LOW);
for (int i = 0; i < 5; i++) {
digitalWrite(led2Pin, HIGH);
digitalWrite(greenPin, HIGH);
digitalWrite(bluePin, HIGH);
delay(100);
digitalWrite(led2Pin, LOW);
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, LOW);
delay(100);
}
}
}
}
void button1Pressed() {
if (!over && started) {
over = true;
winner = 1;
reactionTime = millis() - startTime;
digitalWrite(led1Pin, HIGH);
digitalWrite(redPin, LOW);
digitalWrite(greenPin, HIGH);
digitalWrite(bluePin, LOW);
tone(buzzerPin, 440, 500);
Serial.println("Player 1 wins!");
Serial.print("Reaction time: ");
Serial.print(reactionTime);
Serial.println("ms");
player1Score++;
delay(2000);
resetGame();
}
}
void button2Pressed() {
if (!over && started) {
over = true;
winner = 2;
reactionTime = millis() - startTime;
digitalWrite(led2Pin, HIGH);
digitalWrite(redPin, LOW);
digitalWrite(greenPin, HIGH);
digitalWrite(bluePin, LOW);
tone(buzzerPin, 440, 500);
Serial.println("Player 2 wins!");
Serial.print("Reaction time: ");
Serial.print(reactionTime);
Serial.println("ms");
player2Score++;
delay(2000);
resetGame();
}
}
void blinkRgbLed() {
if (started && !over) {
int randomTime = random(3000, 6000);
digitalWrite(redPin, HIGH);
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, LOW);
delay(randomTime);
digitalWrite(redPin, LOW);
digitalWrite(greenPin, HIGH);
digitalWrite(bluePin, LOW);
startTime = millis();
}
if (over) {
if (winner == 1) {
digitalWrite(redPin, LOW);
digitalWrite(greenPin, HIGH);
digitalWrite(bluePin, LOW);
} else if (winner == 2) {
digitalWrite(redPin, LOW);
digitalWrite(greenPin, HIGH);
digitalWrite(bluePin, LOW);
} else {
digitalWrite(redPin, LOW);
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, HIGH);
}
}
}
void resetGame() {
digitalWrite(led1Pin, LOW);
digitalWrite(led2Pin, LOW);
digitalWrite(redPin, LOW);
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, LOW);
over = false;
winner = 0;
reactionTime = 0;
startTime = 0;
}
int getPlayer1Score() {
return player1Score;
}
int getPlayer2Score() {
return player2Score;
}
};
// Create a Game object with the specified pins
Game game(2, 3, 6, 7, 9, 10, 11, 12);
void setup() {
Serial.begin(9600);
randomSeed(analogRead(0));
game.start();
delay(250); // Add a 250ms delay after the game starts
}
void loop() {
game.blinkWinnerLed();
game.blinkRgbLed();
}
我尝试在代码中移动函数来声明主题,但无论我把它们放在哪里,它们都会导致我的整个代码出现错误。我非常有信心这是因为附加中断在类中,但我不知道如何使其适合我的代码的其余部分。
除了 Juraj 提到的关于前向声明的内容。
您的类设计存在一些问题。
当 Arduino 启动时,其中有一个 main() 函数,该函数在将控制权传递给
setup()
之前执行系统初始化(例如定义引脚、设置板变量等)。您的类构造已实例化,并尝试在调用 main() 中的 init()
之前运行代码,而 Arduino 还不知道如何执行这些代码。这就是为什么几乎所有 Arduino 库都有一个 begin()
方法,您的类构造应该只包含类变量初始化,在调用 setup()
之前,不应在类构造中运行任何代码。重新设计您的类构造,将设置 pinMode()
和中断等代码移至 begin()
方法,并在您的 setup()
中调用它。
其他参考:
你的中断处理程序
button1Pressed()
和button2Pressed()
太长了,它应该尽可能短,并且不应该包含诸如delay()
,tone()
和Serial.print()
之类的阻塞函数。我建议阅读 Nick Gammon 的 Interrupt。