Arduino 学习
Arduino 背景可以参考官方网站 www.arduino.cc
先看一个最简单的示例程序:
打开 Arduino IDE , 选择菜单:文件 -> 示例 -> 01.Basics -> Blink
/* 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 函数的前世今生了吧。在 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 data boolean 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 函数的过程中,就要考虑接受的数据长度以及函数的处理时间,否则极有可能会导致其它串口的接收缓冲区满而影响应用。
**** 看门狗 (测试卡死了 bootloader) 请谨慎操作 ****
最新的 Arduino 1.5.6-r2 烧写的bootloader 已经支持看门狗了。
重新烧写mega2560的bootloader 烧写完之后 用usb直接编译下载 已经可以支持avr的这个wdt.h了,不用再像之前那样非得用ISP下载程序了。
使用代码如下:
/*------ avr看门狗测试 -----*/ #include <avr/wdt.h> void setup() { pinMode(13,OUTPUT); wdt_enable(WDTO_4S); //开启看门狗,并设置溢出时间为4秒 digitalWrite(13,HIGH); delay(100); digitalWrite(13,LOW); delay(100); digitalWrite(13,HIGH); delay(100); digitalWrite(13,LOW); delay(100); } void loop() { digitalWrite(13,HIGH); delay(600); digitalWrite(13,LOW); delay(600); //wdt_reset(); //喂狗操作,使看门狗定时器复位 }
溢出时间如下:
序号
|
常量
|
定义
|
1
|
WDTO_15MS
|
看门狗定时器15ms超时
|
2
|
WDTO_30MS
|
看门狗定时器30ms超时
|
3
|
WDTO_60MS
|
看门狗定时器60ms超时
|
4
|
WDTO_120MS
|
看门狗定时器120ms超时
|
5
|
WDTO_250MS
|
看门狗定时器250ms超时
|
6
|
WDTO_500MS
|
看门狗定时器500ms超时
|
7
|
WDTO_1S
|
看门狗定时器1S超时
|
8
|
WDTO_2S
|
看门狗定时器2S超时
|
9
|
WDTO_4S
|
看门狗定时器4S超时
|
10
|
WDTO_8S
|
看门狗定时器8S超时
|
Arduino Ethernet Shield MEGA hack
http://mcukits.com/2009/04/06/arduino-ethernet-shield-mega-hack/
or
pinMode(11,INPUT); pinMode(12,INPUT); pinMode(13,INPUT);