Arduino 學習

Old發表於2014-02-25

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);

 

相關文章