Skip to content

Arduino - 控制语句

为了创建交互式和智能的项目,您的程序需要做出决策。控制语句是基本的构建块,它允许您根据特定条件来决定程序执行的流程。这使得您的 Arduino 能够对传感器输入、用户命令和内部状态变化做出反应。

现代 C++(Arduino 使用的语言)提供了一套强大的控制结构。让我们通过实际的现实世界示例来探索其中最核心的部分。

这是最常见的决策工具。它只在特定条件为 true(真)时执行一段代码。

  • if:检查一个条件。如果条件为真,花括号 {} 里的代码就会运行。
  • else if:如果第一个 if 条件为假,则检查第二个条件。
  • else:如果所有之前的 if 和 else if 条件都为假,则 else 代码块中的代码会运行。

让我们制作一个仅在按下按钮时才点亮的 LED。这展示了一个基本的输入到输出的反应。

// 最佳实践:对引脚号使用 'const int' 或 'constexpr'。
// 这可以防止意外修改,并使代码更具可读性。
constexpr int LED_PIN = 13; // 大多数 Arduino 板载的 LED
constexpr int BUTTON_PIN = 2; // 将一个按钮连接到引脚 2
void setup() {
// 初始化引脚,使其用于指定目的
pinMode(LED_PIN, OUTPUT);
// 使用 INPUT_PULLUP 启用内部上拉电阻。
// 这意味着当按钮未按下时引脚读数为 HIGH,按下时读数为 LOW。
pinMode(BUTTON_PIN, INPUT_PULLUP);
// 启动串口通信,用于调试
Serial.begin(9600);
}
void loop() {
// 读取按钮状态
int buttonState = digitalRead(BUTTON_PIN);
// 由于使用了 INPUT_PULLUP,逻辑是反转的:LOW 表示按钮被按下。
if (buttonState == LOW) {
// 如果按钮被按下,打开 LED。
digitalWrite(LED_PIN, HIGH);
Serial.println("Button is pressed. LED ON.");
} else {
// 如果按钮未按下,关闭 LED。
// 此处无需打印,否则会刷屏串口监视器。
digitalWrite(LED_PIN, LOW);
}
delay(50); // 一个小延迟,用于消除抖动并防止串口刷屏
}

当您有一个变量需要对照多个可能的值进行检查时,switch 语句通常比一长串 if-else if 语句更简洁、更高效。

想象一个具有三种模式(例如,常亮、闪烁、渐变)的设备,通过串口监视器发送命令来选择模式。

constexpr int LED_PIN = 9; // 使用一个 PWM 引脚进行渐变(例如 Uno 上的 3, 5, 6, 9, 10, 11)
char deviceMode = 's'; // 's' 代表常亮,'b' 代表闪烁,'f' 代表渐变
void setup() {
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600);
Serial.println("Enter a mode: 's' (solid), 'b' (blink), 'f' (fade)");
}
void loop() {
// 检查串口是否有可用数据可读
if (Serial.available() > 0) {
char input = Serial.read();
if (input == 's' || input == 'b' || input == 'f') {
deviceMode = input;
}
}
// 使用 switch 语句处理当前模式
switch (deviceMode) {
case 's':
// 常亮模式:LED 始终开启
digitalWrite(LED_PIN, HIGH);
break; // **关键**:'break' 用于退出 switch 语句。如果没有它,程序将继续执行下一个 case 块!
case 'b':
// 闪烁模式
digitalWrite(LED_PIN, HIGH);
delay(500);
digitalWrite(LED_PIN, LOW);
delay(500);
break;
case 'f':
// 渐变模式(使用 for 循环,见下一节)
for (int i = 0; i <= 255; i++) {
analogWrite(LED_PIN, i);
delay(5);
}
for (int i = 255; i >= 0; i--) {
analogWrite(LED_PIN, i);
delay(5);
}
break;
default:
// 最佳实践:始终包含一个 default 情况,以处理意外值。
// 在这种情况下,什么也不做。
break;
}
}

忘记 break 语句是一个非常常见的错误。如果您省略它,程序将继续执行下一个 case 块中的代码,导致意想不到的行为。

循环用于重复执行一段代码块。这对于诸如 LED 闪烁、多次读取传感器或处理数据等任务至关重要。

当您确切知道要重复某个动作多少次时,for 循环是完美的选择。switch 语句中的 LED 渐变示例就使用了 for 循环。

当您希望循环在条件为真时持续执行,但不知道何时会停止时,while 循环是理想的选择。

// 实践示例:等待传感器准备就绪
// (这是一个概念性示例)
#include <Wire.h>
#include <Adafruit_Sensor.h>
// #include <Some_Sensor_Library.h> // 一个假想的传感器库
// SomeSensor sensor;
void setup() {
Serial.begin(9600);
while (!Serial) {
; // 等待串口连接。原生 USB 端口板需要此操作。
}
Serial.println("等待传感器初始化...");
// while 循环非常适合等待条件满足
// while (!sensor.isReady()) {
// Serial.print(".");
// delay(100);
// }
Serial.println("\n传感器已准备就绪!");
}
void loop() {
// 主程序逻辑从这里开始
}

这是一种紧凑的、单行的简写形式,用于简单的 if-else 语句。它非常适合根据条件为变量赋值。

语法:condition ? value_if_true : value_if_false

Section titled “语法:condition ? value_if_true : value_if_false”
// 之前(使用 if-else):
int x = 10;
int y;
if (x > 5) {
y = 100;
} else {
y = 0;
}
// 之后(使用三元运算符):
int x = 10;
int y = (x > 5) ? 100 : 0; // y 将为 100
// 另一个示例
int lightLevel = analogRead(A0);
String message = (lightLevel < 500) ? "It's dark" : "It's bright";
Serial.println(message);

综合您所学到的知识!创建一个简单的交通灯系统,包含红、黄、绿三色 LED。使用 digitalWrite() 控制 LED,使用 delay() 控制序列时间。使用 if-else 或 switch 语句来构建您的逻辑,使其在以下状态之间循环:绿灯 -> 黄灯 -> 红灯 -> 绿灯…