一、blink源程序分析
–》源程序如下(注释已翻译):
1 2 3 4 5 6 7 8 9 10 11 12 13 | // setup函数只运行一次 void setup() {<!-- --> // 初始化LED_BUILTIN引脚为输出引脚 pinMode(LED_BUILTIN, OUTPUT); } // loop函数会一直循环运行 void loop() {<!-- --> digitalWrite(LED_BUILTIN, HIGH); // 点亮LED(配置引脚输出高电平) delay(1000); // 等待1s digitalWrite(LED_BUILTIN, LOW); // 熄灭LED(配置引脚输出低电平) delay(1000); // 等待1s } |
这是先说一下电平的概念:
- 高电平就相当于高电位或高电势;
- 低电平就相当于低电位或地电势;
- 两点之间存在电平差就相当于存在电位差或者电势差,从而存在电压。
程序首先把LED_BUILTIN引脚配置为输出引脚,意思是板子可以控制该引脚输出为高电平或者低电平,LED引脚一端接在板子控制端口,而另外一端是接在参考地上,可以认为参考地是零电平或者低电平。当loop函数开始执行的时候,把控制端引脚输出为高电平,而参考地是低电平,所以LED被点亮,同理把控制端引脚输出为低电平,两点之间没有电位差,因此LED熄灭。
二、程序结构
- setup()函数
Arduino板子通电或复位后,即会开始执行setup() 函数中的程序,该部分只会执行一次。通常我们会在setup() 函数中完成Arduino的初始化设置,如配置I/O口状态,初始化串口等操作。
–》示例程序:
1 2 3 4 5 6 7 | // 给13号引脚连接的设备设置一个别名“led” int led = 13; // 在板子启动或者复位重启后, setup部分的程序只会运行一次 void setup(){<!-- --> // 将“led”引脚设置为输出状态 pinMode(led, OUTPUT); } |
- loop()函数
在setup() 函数中的程序执行完后,Arduino会接着执行loop() 函数中的程序。而loop()函数是一个死循环,其中的程序会不断的重复运行。通常我们会在loop() 函数中完成程序的主要功能,如驱动各种模块,采集数据等。
–》示例程序:
1 2 3 4 5 6 7 8 | // setup部分程序运行完后,loop部分的程序会不断重复运行 void loop() {<!-- --> digitalWrite(led, HIGH); // 点亮LED delay(1000); // 等待一秒钟 digitalWrite(led, LOW); // 通过将引脚电平拉低,关闭LED delay(1000); // 等待一秒钟 } |
*三、Arduino程序main函数结构解析
这里作为拓展,以下分析需要C/C++基础!
在进行Arduino开发时,没有像传统C/C++程序使用入口函数main。实际上main函数存在于Arduino核心库中,且仍然是程序的入口。
在Arduino核心库中可见main.cpp文件,其内容如下:
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 | #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结束后,都会进行串口事件判断,也正是因为这种设计,串口事件不能实时响应。