Arduino 程序结构
本节我们学习 Arduino 的编程框架,并运行第一个 Arduino 程序。
程序框架
Arduino 使用 C/C++ 语言编写程序,但 Arduino 程序的结构与传统 C/C++ 的程序结构又有所不同 —— Arduino 程序中没有 main() 函数。
其实并不是 Arduino 程序没有 main() 函数,只是 main() 函数的定义隐藏在了 Arduino 的核心库文件中。用户在进行 Arduino 开发时一般不直接操作 main() 函数,而是使用 setup() 和 loop() 这两个函数。
Arduino 程序的基本结构由 setup() 和 loop() 两个函数组成。
-
setup()
Arduino 控制器通电或复位后,即会开始执行 setup() 函数中的程序,该程序只会执行一次。通常在这里完成 Arduino 的初始化设置,如初始化变量、初始化串口、配置 I/O 状态、启用软件库等操作。
-
loop()
setup() 函数中的程序执行完毕后,Arduino 会接着执行 loop() 函数中的程序,而 loop() 函数是一个死循环,其中的程序会不断地重复运行,使得 Arduino 可以不断工作。通常在这里完成程序的主要功能,如驱动各种模块和采集数据等。
void setup()
{
/* 初始化函数,配置管脚、调用库函数 */
}
void loop()
{
/* 连续执行函数内的语句 */
}
通常,一个编程风格良好的 Arduino 程序,会在程序的前几行添加注释,用于介绍该程序的作用及相关声明等。Arduino IDE 编写的代码被称为项目(sketch),当我们点击“保存”,文本编辑器中的项目将会以 .ino 的文件形式保存。
Hello World
Arduino IDE 内置示例程序,包括基本的、数字的、模拟的、控制的、通信的、传感器的、字符串的、存储卡的、显示的、音频的、网络的示例等等。您可在菜单栏中选择“文件”->“示例”中找到它们。
Arduino 的第一个 Hello World 程序叫做 Blink,在 IDE 中选择“文件”->“示例”->“01. Basics”->“Blink”即可打开该示例程序。Blink 程序的功能是驱动 Arduino 控制板上的 LED 灯,并以打开一秒、关闭一秒的节奏不断闪烁。
/*
Blink
Turns an LED on for one second, then off for one second, repeatedly.
*/
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
这里的 LED_BUILTIN 是 Arduino 为方便我们编程预先定义好的常量,用于指向控制板内置 LED 引脚编号。不同控制板对应的值可能不一样,对于大部分 Arduino 控制板(包括 Arduino Uno)来说,该值为 13,对应 D13 数字接口。
#define LED_BUILTIN 13
首先,在 setup() 函数中,将 LED_BUILTIN 引脚初始化为输出状态。
pinMode(LED_BUILTIN, OUTPUT);
接着,在 loop() 主循环中,将 LED_BUILTIN 引脚电平拉高,点亮 LED 灯。
digitalWrite(LED_BUILTIN, HIGH);
延时 1 秒,再将 LED_BUILTIN 引脚电平拉低,熄灭 LED 灯。
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
这样循环执行程序,我们就会看到 LED 灯不断闪烁。
除了使用 Arduino 控制板内置的 LED,您也可以像这样外接一个电阻和 LED 进行实验。您也可以将 LED 连接到其他数字接口,通过修改程序中的引脚编号,实现对 LED 灯的控制。
main 函数解析
虽然在开发 Arduino 程序时不需要关心 main 函数,但我们还是想看看 Arduino 的 main 函数长什么样。实际上,main 函数存在于 Arduino 核心库中,且仍然是整个程序的主入口。
在 Arduino 核心库中可见 main.cpp 文件,其内容如下:
#include <Arduino.h>
// Declared weak in Arduino.h to allow user redefinitions.
int atexit(void (* /*func*/ )()) { return 0; }
// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }
void setupUSB() __attribute__((weak));
void setupUSB() { }
int main(void)
{
init();
initVariant();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
可以看到,Arduino 程序中编写的 setup 和 loop 函数,都在 main 函数中被默默调用了。
loop 函数的循环执行,是通过 for 循环实现的,且每次 loop 结束后,都会进行串口事件判断,也正是因为这种设计,串口事件不能实时响应。