
一、Arduino 编程语言
Arduino 核心是 C++ 编程 ,不是纯 C 语言,但它兼容 C 语言语法,新手写简单代码时几乎感觉不到区别。
- 官方标准 :Arduino 基于 AVR-GCC C++ 编译器,完整支持 C++ 特性
- 新手体验 :默认的
setup()/loop()、数字 / 串口操作,用的是简化版 C++,写法和 C 高度相似 - 底层本质 :Arduino 核心库(如
digitalWrite、Serial)都是用 C++ 类、对象 编写的
Arduino 强制使用 C++ 编译,纯 C 能做的它都能做,C++ 独有的特性它也支持,比如:
- 类(Class)、对象(Object)
- 构造函数 / 析构函数
- 函数重载
- 引用(&)
- 命名空间
而 纯 C 语言不支持这些特性。
|--------|-------------------|------------------|
| 语言 | 能否在 Arduino 用 | 特点 |
| 纯 C | ✅ 兼容 | 语法简单,无面向对象 |
| C++ | ✅ 原生支持 | 包含全部 C 语法 + 高级特性 |
Arduino IDE 用 C++ 编译,你可以写 C 风格代码 入门,也可以用 C++ 高级特性 写复杂项目。
总结
- Arduino 编程本质是 C++,不是纯 C
- 新手写基础代码(
setup/loop、引脚控制)用 C 语法 完全够用 - 进阶开发(库、模块化、面向对象)必须用 C++ 特性
- 所有代码最终都会被 C++ 编译器编译
二、Arduino 程序核心函数
Arduino 程序必须有这两个函数,少一个就编译报错。
void setup(){
// 上电 / 复位,只执行 1 次
}
void loop(){
// setup跑完之后,无限循环反复执行
}
1、void setup()函数
- 执行时机 :板子通电、按复位按钮之后,只运行一遍,仅此一次。
- 用途:做初始化工作,只需要设置一次的代码放这里。 适合写:
- 引脚模式设置
pinMode(LED_BUILTIN, OUTPUT); - 串口初始化
Serial.begin(9600); - OLED、传感器初始化
- 变量初始赋值
❌不要把需要反复执行的逻辑写在这里,写完就不再跑了。
示例:
void setup() {
pinMode(42, OUTPUT); //把42号引脚设置为输出模式,只需要设置1次
Serial.begin(9600); //开启串口
}
2、void loop()函数
- 执行时机 :
setup()全部执行完毕之后,自动一遍一遍无限循环 。loop(){A;B;C;}→ 执行 A→B→C,然后立刻回到 A→B→C...... 永不停歇。 - 用途:放需要不停重复运行的逻辑。
适合写:
- 读取传感器数值
- 开关灯、电机控制
- 判断按键状态
- 串口接收数据
示例(闪烁 LED)
void loop() {
digitalWrite(42, HIGH); //灯亮
delay(1000); //等1000ms
digitalWrite(42, LOW); //灯灭
delay(1000); //等1000ms
//执行完,自动回到loop开头重新运行
}
void 代表:这个函数没有返回值,执行完不返回任何数据给程序。
3、 完整最小样板代码
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("我在循环运行");
delay(1000);
}
上电后,串口每秒打印一行文字,无限输出。
新手容易踩坑
- 把延时
delay()写在 setup:只会执行一次,不会循环闪烁。 - 把
pinMode()写进 loop:可以跑,但每次循环重复设置引脚,属于多余浪费。引脚模式放 setup。 - Arduino 程序入口不是
main(),IDE 底层帮你封装好了main(),用户只写 setup + loop。
三、 Arduino 自定义函数
setup()、loop()是系统规定函数;自定义函数是我们自己写的,用来把重复的代码打包,简化 loop,减少复制粘贴。
使用自定义函数的好处:
- 代码清晰,一个函数做一件事;
- 重复逻辑只写一遍,多处调用,修改只改一处;
loop()不会写的几百行一大坨,可读性高。
1、 函数基本语法
返回值类型 函数名(参数列表)
{
//函数内部代码
return 返回的数据; //有返回值才写return
}
两种大类
- 无返回值函数(void):只干活,最后不返回数据。
- 有返回值函数(int /float/bool):干完活返回一个结果给调用处。
2、void 无返回不带参数
比如要实现 LED 闪烁,代码会重复写digitalWrite+delay,封装成函数。
//自定义函数:让42号LED闪烁一次
void ledBlink()
{
digitalWrite(42, HIGH);
delay(500);
digitalWrite(42, LOW);
delay(500);
}
void setup() {
pinMode(42, OUTPUT);
}
void loop() {
ledBlink(); //直接调用,执行函数里面全部代码
}
运行效果:LED 持续闪烁。
调用:写ledBlink();加括号加分号,就会跑函数内部代码。
3、void带参数
参数可以向函数传递数值,让函数更加灵活。
// 函数:LED闪烁,ms毫秒由调用的时候决定
void ledBlinkTime(int ms)
{
digitalWrite(42, HIGH);
delay(ms);
digitalWrite(42, LOW);
delay(ms);
}
void setup() {
pinMode(42, OUTPUT);
}
void loop() {
ledBlinkTime(100); //快速闪烁,ms=100
ledBlinkTime(1000); //慢速闪烁,ms=1000
}
int ms:形式参数,相当于函数内部的局部变量。- 调用写
ledBlinkTime(100),此时ms = 100。
可以写多个参数,逗号隔开:
void ledBlink(int pin, int onTime, int offTime)
{
digitalWrite(pin,HIGH);
delay(onTime);
digitalWrite(pin,LOW);
delay(offTime);
}
//调用
ledBlink(13,300,700);
4、 有返回值函数(int/float/bool)
用return把计算结果送回去。 需求:写一个函数计算两个数字相加。
//返回int类型,接收a、b两个参数
int addNum(int a, int b)
{
int sum = a + b;
return sum; //把sum返回给调用地方
}
void setup() {
Serial.begin(9600);
}
void loop() {
int result = addNum(3,5); //调用函数,拿到返回值存入result
Serial.println(result); //输出8
delay(1000);
}
逻辑:
addNum(3,5)执行函数内部代码return sum,把结果返回 ,替换掉addNum(3,5)这一块int result = 8;
return 执行之后,函数立刻结束,return 后面的代码不会运行。
布尔返回值示例,判断数值是否大于 100:
bool isOver100(int val)
{
if(val>100){
return true;
}else{
return false;
}
}
5、 重要规则
-
函数写在哪里? 可以写在
setup()、loop()的外面,全局位置。 ✅正确结构:void myFunc(){ }
void setup(){ }
void loop(){ }
❌错误:不能把函数定义写在另一个函数里面!
void loop(){
void myFunc(){ } // 错误!Arduino C++不允许函数嵌套定义
}
-
变量作用域(局部 vs 全局)
void test(){
int a = 10; //局部变量,只在test函数内部有效,外面访问不到
}
int b = 20; //全局变量,setup、loop、所有自定义函数都可以访问
尽量少用全局变量,多用参数传递。
-
函数声明(当自定义写在 loop 后面时) 如果你把自定义函数写在
loop()下方,需要在开头做函数声明,否则编译报错。void hello(); //函数声明
void setup(){
hello();
}
void loop(){}//定义写在后面
void hello(){
Serial.println("hi");
}
Arduino IDE 有个小便利:对于简单函数,很多时候会自动帮你生成前置声明,但复杂参数建议手动写。