arduino 程序的机制

来源:互联网 发布:iphone吉他软件 编辑:程序博客网 时间:2024/05/16 14:45

        从一个简单的 arduino 程序说起:

/*  Blink  Turns on an LED on for one second, then off for one second, repeatedly.    This example code is in the public domain. */  // Pin 13 has an LED connected on most Arduino boards.// give it a name:int led = 13; // the setup routine runs once when you press reset:void setup() {                 // initialize the digital pin as an output.  pinMode(led, OUTPUT);    } // the loop routine runs over and over again forever:void loop() {  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)  delay(1000);               // wait for a second  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW  delay(1000);               // wait for a second}

        这个程序的主体,提供了 setup() 和 loop() 二个函数。setup 函数做一些初始化的工作,在系统上电或复位后,此函数只会执行一次。     loop 函数会在 setup 之后一直循环运行。


        在了解如何使用之后,其背后的机制是怎样的呢,那么,可以到安装目录下打开代码文件:C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\main.cpp  代码如下:


#include <Arduino.h> int main(void){    init(); #if defined(USBCON)    USBDevice.attach();#endif         setup();         for (;;) {        loop();        if (serialEventRun) serialEventRun();    }             return 0;}

       相信您看到了这段代码,就该知道 setup 和 loop 函数的前世今生了吧。我们所写的setup 和 loop 函数是这两个函数的定义。这两个函数在 main ( )主程序中已经预调用了。   在 loop 函数运行之后,我们还会看到 serialEventRun 的函数,此函数的功能是当串口有数据过来的时候,它可以调用Arduino的另一个函数 serialEvent。

       打开 Arduino IDE , 选择菜单:文件 -> 示例 -> 04.Communication -> SerialEvent 具体看下面的代码:


/*  Serial Event example   When new serial data arrives, this sketch adds it to a String. When a newline is received, the loop prints the string and clears it.   A good test for this is to try it with a GPS receiver that sends out NMEA 0183 sentences.   Created 9 May 2011 by Tom Igoe   This example code is in the public domain.   http://www.arduino.cc/en/Tutorial/SerialEvent   */ String inputString = "";         // a string to hold incoming databoolean stringComplete = false;  // whether the string is complete void setup() {  // initialize serial:  Serial.begin(9600);  // reserve 200 bytes for the inputString:  inputString.reserve(200);} void loop() {  // print the string when a newline arrives:  if (stringComplete) {    Serial.println(inputString);    // clear the string:    inputString = "";    stringComplete = false;  }} /*  SerialEvent occurs whenever a new data comes in the hardware serial RX.  This routine is run between each time loop() runs, so using delay inside loop can delay response.  Multiple bytes of data may be available. */void serialEvent() {  while (Serial.available()) {    // get the new byte:    char inChar = (char)Serial.read();    // add it to the inputString:    inputString += inChar;    // if the incoming character is a newline, set a flag    // so the main loop can do something about it:    if (inChar == '\n') {      stringComplete = true;    }  }}

        此代码的功能是:系统上电后,接收串口的输入数据并发送回去,类似 echo。系统的实现是通过在主循环判断全局变量 stringComplete 的状态来决定是否发送接收到的数据。而 stringComplete 的状态是在 serialEvent 这个函数里赋值的。根据 serialEvent 函数注释看,此函数的调用是在每次 loop 函数运行之后才执行的。再回到我们之前的代码:


for (;;) {        loop();        if (serialEventRun) serialEventRun();    }

        通过上面的代码,可以很明确的看出 serialEventRun 函数是在 loop 函数之后执行的。如果我们有多个串口,比如 2560 的板子提供了4个串口,那么 serialEventRun 函数又是如何处理的呢,我们打开代码文件:C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\HardwareSerial.cpp 找到 serialEventRun 函数的实现,代码如下:

void serialEventRun(void){#ifdef serialEvent_implemented  if (Serial.available()) serialEvent();#endif#ifdef serialEvent1_implemented  if (Serial1.available()) serialEvent1();#endif#ifdef serialEvent2_implemented  if (Serial2.available()) serialEvent2();#endif#ifdef serialEvent3_implemented  if (Serial3.available()) serialEvent3();#endif}

        serialEventRun 的函数体中是依次的调用 serialEvent() serialEvent1() serialEvent2() serialEvent3() 函数的。如果您的应用需要通过多个串口读写数据,那么在使用 serialEvent 函数的过程中,就要考虑接受的数据长度以及函数的处理时间,否则极有可能会导致其它串口的接收缓冲区满而影响应用。



0 0