Arduino 知识点汇总
cbowen

这篇记录 Arduino 入门时最常用的概念、函数和示例代码。示例默认使用 Arduino Uno/Nano 这类 AVR 开发板;如果使用 ESP32、ESP8266、Leonardo、Micro 等板卡,管脚编号、串口名称、PWM 管脚和电压可能不同,需要以对应板卡文档为准。

常用函数速查

函数名 参数示例 作用
setup() 初始化函数,上电或复位后执行一次
loop() 主循环函数,setup() 执行后不断重复执行
pinMode() pinMode(4, OUTPUT) 设置管脚模式:INPUTOUTPUTINPUT_PULLUP
digitalWrite() digitalWrite(4, HIGH) 给数字管脚输出高/低电平
digitalRead() digitalRead(4) 读取数字管脚电平,返回 HIGHLOW
analogRead() analogRead(A0) 读取模拟量,Uno 默认返回 01023
analogWrite() analogWrite(9, 128) PWM 输出,Uno 默认取值 0255
delay() delay(1000) 阻塞等待,单位毫秒
millis() millis() 获取程序启动后的毫秒数,常用于非阻塞计时
tone() tone(9, 440, 500) 在指定管脚输出方波驱动无源蜂鸣器
noTone() noTone(9) 停止 tone() 输出
Serial.begin() Serial.begin(9600) 初始化串口波特率
Serial.print() Serial.print(value) 串口打印,不换行
Serial.println() Serial.println(value) 串口打印并换行

常见生词

单词 含义
Digital 数字、数码
Analog 模拟、连续变化
Serial 串行、连续的
tone 音调、声调
int 整数类型
bool 布尔类型,取值 truefalse
const 常量,声明后不应再修改
volatile 易变的,常用于中断中会被改变的变量

初识 Arduino

安装步骤

  1. 安装最新版 Arduino IDE 2。
  2. 根据开发板选择 Board Manager。Uno/Nano 常用 Arduino AVR Boards by Arduino,大部分官方 AVR 板卡 IDE 已内置或可直接安装。
  3. 如果是 CH340、CP2102 等 USB 转串口芯片的国产兼容板,可能需要额外安装对应串口驱动。
  4. 使用数据线连接开发板。注意有些线只能充电,不能传输数据。
  5. 在 Arduino IDE 中选择开发板和端口。开发板决定如何编译和上传,端口对应当前接入电脑的设备。
  6. 打开串口监视器时,波特率要和代码里的 Serial.begin() 保持一致。

官方资料:

程序基本结构

一个 Arduino 程序必须包含一个 setup() 和一个 loop()

1
2
3
4
5
6
7
void setup() {
// 初始化,只执行一次
}

void loop() {
// 主循环,会一直重复执行
}

代码书写时注意:

  1. 语句以英文分号 ; 结尾。
  2. 函数名、变量名区分大小写,HIGHLOW 也区分大小写。
  3. 单行注释使用 //,多行注释使用 /* ... */
  4. Arduino IDE 可使用自动格式化整理缩进。
  5. 管脚模式建议在 setup() 中显式设置,避免管脚处于不确定状态。

程序烧录流程

  1. 编译。Arduino IDE 使用对应开发板核心和编译器生成二进制文件。
  2. 上传。IDE 通过 USB 或 USB 转串口芯片把程序写入开发板。
  3. 运行。开发板复位后先执行 setup(),然后不断执行 loop()

常见上传失败原因:

  • 开发板型号选错。
  • 端口选错或端口被串口监视器、其他软件占用。
  • USB 数据线只能充电。
  • 缺少 CH340、CP2102 等串口驱动。
  • 外接电路占用了 01 串口管脚,影响上传。

闪烁灯

内置 LED

多数 Arduino 板卡带有内置 LED,但对应的数字管脚不一定完全相同。推荐使用 LED_BUILTIN 常量,而不是直接写死 13

1
2
3
4
5
6
7
8
9
10
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}

外接 LED

外接 LED 时建议串联 220 欧到 1k 欧电阻限流。LED 长脚一般接正极,短脚接 GND。

1
2
3
4
5
6
7
8
9
10
11
12
const int ledPin = 4;

void setup() {
pinMode(ledPin, OUTPUT);
}

void loop() {
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
}

HIGH 可以理解为高电平,LOW 可以理解为低电平。虽然在很多地方也能用 10truefalse,但教程和正式代码里推荐使用 HIGHLOW,可读性更好。

流水灯

分别将三个 LED 连接至 4、5、6 号管脚,每个 LED 都需要串联限流电阻。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const int led1 = 4;
const int led2 = 5;
const int led3 = 6;

void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
}

void loop() {
digitalWrite(led1, HIGH);
delay(300);
digitalWrite(led1, LOW);

digitalWrite(led2, HIGH);
delay(300);
digitalWrite(led2, LOW);

digitalWrite(led3, HIGH);
delay(300);
digitalWrite(led3, LOW);
}

如果 LED 数量变多,可以使用数组简化代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const int ledPins[] = {4, 5, 6};
const int ledCount = 3;

void setup() {
for (int i = 0; i < ledCount; i++) {
pinMode(ledPins[i], OUTPUT);
}
}

void loop() {
for (int i = 0; i < ledCount; i++) {
digitalWrite(ledPins[i], HIGH);
delay(300);
digitalWrite(ledPins[i], LOW);
}
}

蜂鸣器

蜂鸣器常见有两种:

  • 有源蜂鸣器:内部自带振荡电路,通电后会直接响。
  • 无源蜂鸣器:需要输入一定频率的方波才会持续发声,适合用 tone() 控制音调。

有源蜂鸣器

1
2
3
4
5
6
7
8
9
10
11
12
const int buzzerPin = 4;

void setup() {
pinMode(buzzerPin, OUTPUT);
}

void loop() {
digitalWrite(buzzerPin, HIGH);
delay(500);
digitalWrite(buzzerPin, LOW);
delay(500);
}

无源蜂鸣器

tone(pin, frequency) 会持续发声,直到调用 noTone(pin)tone(pin, frequency, duration) 会在指定时长后停止。

1
2
3
4
5
6
7
8
9
const int buzzerPin = 9;

void setup() {
}

void loop() {
tone(buzzerPin, 440, 500);
delay(1000);
}

常用音高:

音名 频率
C4 261.63 Hz
D4 293.66 Hz
E4 329.63 Hz
F4 349.23 Hz
G4 392.00 Hz
A4 440.00 Hz
B4 493.88 Hz

串口打印

串口常用于调试。Serial.print() 不换行,Serial.println() 打印后换行。

1
2
3
4
5
6
7
8
9
void setup() {
Serial.begin(9600);
}

void loop() {
Serial.print("time: ");
Serial.println(millis());
delay(1000);
}

当开发板通过 USB 数据线连接电脑时,在 Arduino IDE 打开串口监视器即可看到输出。串口监视器右下角的波特率要选择 9600,与 Serial.begin(9600) 保持一致。

数字输入与按键

数字输入

digitalRead() 可以读取数字管脚状态。读取按键时,不建议让输入管脚悬空,否则松开按键时电平可能随机跳变。最简单的做法是使用内部上拉电阻 INPUT_PULLUP

接线方式:

  • 按键一端接数字管脚 2。
  • 按键另一端接 GND。
  • 代码中设置 pinMode(buttonPin, INPUT_PULLUP)

这种接法下,按键松开时读到 HIGH,按下时读到 LOW

1
2
3
4
5
6
7
8
9
10
11
12
const int buttonPin = 2;

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

void loop() {
int value = digitalRead(buttonPin);
Serial.println(value);
delay(100);
}

分支结构

1
2
3
4
5
6
7
8
9
if (条件1) {
语句1;
}

if (条件2) {
语句2;
} else {
语句3;
}

条件不可省略,条件必须加括号。条件满足时,执行紧随其后的大括号内语句。

比较运算符:

比较运算符 含义
> 大于
< 小于
>= 大于或等于
<= 小于或等于
!= 不等于
== 等于

按下亮,松开灭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const int buttonPin = 2;
const int ledPin = 4;

void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
}

void loop() {
int buttonState = digitalRead(buttonPin);

if (buttonState == LOW) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}

按一下亮,再按一下灭

机械按键会抖动,一次按下可能被程序读成多次变化。下面示例加入了简单消抖逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const int buttonPin = 2;
const int ledPin = 4;

bool ledState = false;
int lastButtonReading = HIGH;
int stableButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50;

void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
}

void loop() {
int reading = digitalRead(buttonPin);

if (reading != lastButtonReading) {
lastDebounceTime = millis();
}

if (millis() - lastDebounceTime > debounceDelay) {
if (reading != stableButtonState) {
stableButtonState = reading;

if (stableButtonState == LOW) {
ledState = !ledState;
digitalWrite(ledPin, ledState ? HIGH : LOW);
}
}
}

lastButtonReading = reading;
}

模拟输入与 PWM 输出

电位器读取

电位器两侧接 5VGND,中间引脚接 A0。Uno 默认把模拟输入转换为 01023

1
2
3
4
5
6
7
8
9
10
11
const int potPin = A0;

void setup() {
Serial.begin(9600);
}

void loop() {
int value = analogRead(potPin);
Serial.println(value);
delay(100);
}

PWM 控制 LED 亮度

Uno 上不是所有数字管脚都支持 PWM,通常带 ~ 标记的管脚才支持,如 3、5、6、9、10、11。

1
2
3
4
5
6
7
8
9
10
11
12
const int potPin = A0;
const int ledPin = 9;

void setup() {
pinMode(ledPin, OUTPUT);
}

void loop() {
int sensorValue = analogRead(potPin);
int brightness = map(sensorValue, 0, 1023, 0, 255);
analogWrite(ledPin, brightness);
}

局部变量、全局变量与常量

局部变量声明在函数内部,只在当前函数内部生效。

1
2
3
void loop() {
int value = analogRead(A0);
}

全局变量声明在所有函数外部,可以被多个函数读取或修改。

1
2
3
4
5
int count = 0;

void loop() {
count++;
}

不会改变的配置值建议用 const,例如管脚编号。

1
const int ledPin = 4;

volatile 用在变量可能被中断服务程序修改的场景。普通 loop() 里的变量不需要加 volatile

1
volatile bool triggered = false;

常见问题

  1. LED 不亮:检查正负极、限流电阻、GND 是否共地、管脚是否写错、是否调用了 pinMode(pin, OUTPUT)
  2. 按键读数乱跳:输入管脚可能悬空,使用 INPUT_PULLUP 或外接上拉/下拉电阻。
  3. 串口监视器乱码:串口监视器波特率和 Serial.begin() 不一致。
  4. 上传失败:确认开发板型号、端口、数据线、驱动,必要时断开占用 01 管脚的外设。
  5. 蜂鸣器不响:确认是有源还是无源蜂鸣器;无源蜂鸣器使用 tone() 更合适。
  6. PWM 没效果:确认使用的是支持 PWM 的管脚。
 评论
评论插件加载失败
正在加载评论插件