Menu
CoddyTech

用按钮切换模式

本课属于 Coddy Arduino 学习旅程的“无需 delay 的计时”单元。第 11 课,共 18 课。

许多小设备只有一个按钮,用来依次切换模式:自行车灯依次熄灭、亮起、闪烁、快速闪烁,然后再次熄灭。这是一种状态机,按下按钮而不是等待时钟,就会切换到下一个状态。

把切换步骤放在单独的函数中。根据当前模式使用 switch 设置下一个模式,最后一个模式会回到第一个模式:

void nextMode() {
  switch (mode) {
    case OFF:
      mode = ON;
      Serial.println("ON");
      break;
    // ……以此类推,直到 FAST 重新切换为 OFF
  }
}

草图会在每次按下按钮时调用一次 nextMode()。按钮的消抖方式和你在“输入”单元中学的一样:读数变化时执行操作,然后等待 20 ms,让触点稳定下来。另一个针对 mode 的 switch 会设置 LED。

challenge icon

挑战

中等

按钮和 LED 的代码已经为你写好。编写 nextMode(),让每次按下按钮都切换到下一个模式,并输出它的名称:OFF、ON、BLINK、FAST,然后再次回到 OFF。

按“运行”,按几次按钮,然后按“检查”。

亲手试试

const int ledPin = 13;
const int buttonPin = 2;

enum Mode { OFF, ON, BLINK, FAST };
Mode mode = OFF;

bool wasPressed = false;
unsigned long blinkPrevious = 0;
int ledState = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
}

// 切换到下一个模式并打印其名称。
void nextMode() {
  // 每个模式对应一个 case:设置下一个模式,打印其名称,然后执行 break。
}

// 每隔 interval 毫秒切换一次 LED 状态。
void blinkEvery(unsigned long interval) {
  unsigned long now = millis();
  if (now - blinkPrevious >= interval) {
    blinkPrevious = now;
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState);
  }
}

void loop() {
  // 1. 按下按钮(消抖后)会调用 nextMode()
  bool pressed = digitalRead(buttonPin) == LOW;
  if (pressed != wasPressed) {
    if (pressed) {
      nextMode();
    }
    wasPressed = pressed;
    delay(20);   // 等待触点稳定
  }

  // 2. 模式决定 LED 的行为
  switch (mode) {
    case OFF:
      digitalWrite(ledPin, LOW);
      break;
    case ON:
      digitalWrite(ledPin, HIGH);
      break;
    case BLINK:
      blinkEvery(500);
      break;
    case FAST:
      blinkEvery(100);
      break;
  }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

无需 delay 的计时中的所有课

自己练习: Arduino 在线编辑器