Arduino編程參考手冊

來自ALSROBOT WiKi
跳轉至: 導航、 搜索

首頁

程序結構 變量 基本函數
setup()
loop()
控制結構
if
if...else
for
switch case
while
do...while
break
continue
return
goto
相關語法
 ; 分號
{ 大括號
// 單行注釋
/**/ 多行注釋
#define 宏定義
#include 文件包含
算術運算符
= 賦值
+ (加)
- (減)
* (乘)
/ (除)
 % (取模)
比較運算符
== 等于
 != (不等于)
< (小于)
> (大于)
<= (小于等于)
>= (大于等于)
布爾運算符
&& (邏輯與)
|| (邏輯或)
 ! (邏輯非)
指針運算符
* 指針運算符
& 地址運算符
位運算
& (位與)
| (位或)
^ (位異或)
~ (位非)
<< (左移)
>> (右移)
復合運算符
++ (自加)
-- (自減)
+= (復合加)
-= (復合減)
*= (復合乘)
/= (復合除)
&= (復合與)
|= (復合或)


范圍
HIGH | LOW
INPUT | OUTPUT
true | false
整型常量
浮點數常量
數據類型
void
boolean
char
unsigned char
byte
int
unsigned int
word
long
unsigned long
float
double
string
String(c++)
array
數據類型轉換
char()
byte()
int()
word()
long()
float()
變量作用域
變量作用域
static (靜態(tài)變量)
volatile (易變變量)
const (不可改變變量)
輔助工具
sizeof() (sizeof運算符)
ASCII碼表


數字I/O
pinMode()
digitalWrite()
digitalRead()
模擬I/O
analogReference()
analogRead()
analogWrite()
指高級I/O
shiftOut()
pulseIn()
時間
millis()
delay(ms)
delayMicroseconds(us)
數學庫
min()
max()
abs()
constrain()
map()
pow()
sqrt()
三角函數
sin(rad)
cos(rad)
tan(rad)
隨機數
randomSeed()
random()
random()
位操作
lowByte()
highByte()
bitRead()
bitWrite()
bitSet()
bitClear()
bit()
設置中斷函數
attachInterrupt()
detachInterrupt()
interrupts()
noInterrupts()
串口通訊
begin()
available()
read()
flush
print()
println()
write()
peak()
serialEvent()












































































程序結構

(本節(jié)直譯自Arduino官網最新Reference)

在Arduino中, 標準的程序入口main函數在內部被定義, 用戶只需要關心以下兩個函數:

setup()
當Arduino板起動時setup()函數會被調用。用它來初始化變量,引腳模式,開始使用某個庫,等等。該函數在Arduino板的每次上電和復位時只運行一次。


loop()

在創(chuàng)建setup函數,該函數初始化和設置初始值,loop()函數所做事的正如其名,連續(xù)循環(huán),允許你的程序改變狀態(tài)和響應事件??梢杂盟鼇韺崟r控制arduino板。

示例:

int buttonPin = 3;

void setup()
{
  Serial.begin(9600); //初始化串口
  pinMode(buttonPin, INPUT); //設置3號引腳為輸入模式
}

void loop()
{
  if (digitalRead(buttonPin) == HIGH)
    serialWrite('H');
  else
    serialWrite('L');

  delay(1000);
}




控制語句

if

if,用于與比較運算符結合使用,測試是否已達到某些條件,例如一個輸入數據在某個范圍之外。使用格式如下:

if (value > 50)
{
  // 這里加入你的代碼
}

該程序測試value是否大于50。如果是,程序將執(zhí)行特定的動作。換句話說,如果圓括號中的語句為真,大括號中的語句就會執(zhí)行。如果不是,程序將跳過這段代碼。大括號可以被省略,如果這么做,下一行(以分號結尾)將成為唯一的條件語句。

 
if (x > 120) digitalWrite(LEDpin, HIGH); 

if (x > 120)
digitalWrite(LEDpin, HIGH); 

if (x > 120){ digitalWrite(LEDpin, HIGH); } 

if (x > 120){ 
  digitalWrite(LEDpin1, HIGH);
  digitalWrite(LEDpin2, HIGH); 
}                                 // 都是正確的

圓括號中要被計算的語句需要一個或多個操作符。


if...else


與基本的if語句相比,由于允許多個測試組合在一起,if/else可以使用更多的控制流。例如,可以測試一個模擬量輸入,如果輸入值小于500,則采取一個動作,而如果輸入值大于或等于500,則采取另一個動作。代碼看起來像是這樣:

if (pinFiveInput < 500)
{
  // 動作A
}
else
{
  // 動作B
}

else中可以進行另一個if測試,這樣多個相互獨立的測試就可以同時進行。每一個測試一個接一個地執(zhí)行直到遇到一個測試為真為止。當發(fā)現(xiàn)一個測試條件為真時,與其關聯(lián)的代碼塊就會執(zhí)行,然后程序將跳到完整的if/else結構的下一行。如果沒有一個測試被驗證為真。缺省的else語句塊,如果存在的話,將被設為默認行為,并執(zhí)行。

注意:一個else if語句塊可能有或者沒有終止else語句塊,同理。每個else if分支允許有無限多個。

if (pinFiveInput < 500)
{
  // 執(zhí)行動作A
}
else if (pinFiveInput >= 1000)
{
  // 執(zhí)行動作B
}
else
{
  // 執(zhí)行動作C
}

另外一種表達互斥分支測試的方式,是使用switch case語句。




for

for語句
描述
for語句用于重復執(zhí)行被花括號包圍的語句塊。一個增量計數器通常被用來遞增和終止循環(huán)。for語句對于任何需要重復的操作是非常有用的。常常用于與數組聯(lián)合使用以收集數據/引腳。for循環(huán)的頭部有三個部分:

for (初始化部分; 條件判斷部分; 數據遞增部分) {
//語句塊
。。。
}

初始化部分被第一個執(zhí)行,且只執(zhí)行一次。每次通過這個循環(huán),條件判斷部分將被測試;如果為真,語句塊和數據遞增部分就會被執(zhí)行,然后條件判斷部分就會被再次測試,當條件測試為假時,結束循環(huán)。

示例:

//使用一個PWM引腳使LED燈閃爍
int PWMpin = 10; // LED在10號引腳串聯(lián)一個470歐姆的電阻

void setup()
{
  //這里無需設置
}

void loop()
{
   for (int i=0; i <= 255; i++){
      analogWrite(PWMpin, i);
      delay(10);
   } 
}

編碼提示:
C中的for循環(huán)比在其它計算機語言中發(fā)現(xiàn)的for循環(huán)要靈活的多,包括BASIC。三個頭元素中的任何一個或全部可能被省略,盡管分號是必須的。而且初始化部分、條件判斷部分和數據遞增部分可以是任何合法的使用任意變量的C語句。且可以使用任何數據類型包括floats。這些不常用的類型用于語句段也許可以為一些罕見的編程問題提供解決方案。

例如,在遞增部分中使用一個乘法將形成對數級增長:

for(int x = 2; x < 100; x = x * 1.5){
	println(x);
}

輸出: 2,3,4,6,9,13,19,28,42,63,94
另一個例子,在一個for循環(huán)中使一個LED燈漸漸地變亮和變暗:

void loop()
{
   int x = 1;
   for (int i = 0; i > -1; i = i + x){
      analogWrite(PWMpin, i);
      if (i == 255) x = -1;             // 在峰值切換方向
      delay(10);
   } 
}



switch case

switch case 語句
就像if語句,switch...case通過允許程序員根據不同的條件指定不同的應被執(zhí)行的代碼來控制程序流。特別地,一個switch語句對一個變量的值與case語句中指定的值進行比較。當一個case語句被發(fā)現(xiàn)其值等于該變量的值。就會運行這個case語句下的代碼。

break關鍵字將中止并跳出switch語句段,常常用于每個case語句的最后面。如果沒有break語句,switch語句將繼續(xù)執(zhí)行下面的表達式(“持續(xù)下降”)直到遇到break,或者是到達switch語句的末尾。

示例:

   switch (var) {
    case 1:
      //當var等于1執(zhí)行這里
      break;
    case 2:
      //當var等于2執(zhí)行這里
      break;
    default: 
      // 如果沒有匹配項,將執(zhí)行此缺省段
      // default段是可選的
  }

語法

 switch (var) {
  case label:
    // statements
    break;
  case label:
    // statements
    break;
  default: 
    // statements
}

參數

var: 與不同的case中的值進行比較的變量


label: 相應的case的值



while

while循環(huán)

描述:

while循環(huán)將會連續(xù)地無限地循環(huán),直到圓括號()中的表達式變?yōu)榧?。被測試的變量必須被改變,否則while循環(huán)將永遠不會中止。這可以是你的代碼,比如一個遞增的變量,或者是一個外部條件,比如測試一個傳感器。

語法:

 while(expression){
  // statement(s)
}

參數:

expression - 一個(布爾型)C語句,被求值為真或假

示例:

var = 0;
 while(var < 200){
   // 做兩百次重復的事情
   var++;
 }



do...while

do循環(huán)
do循環(huán)與while循環(huán)使用相同方式工作,不同的是條件是在循環(huán)的末尾被測試的,所以do循環(huán)總是至少會運行一次。

do
{
    // 語句塊
} while (測試條件);

示例:

do
{
  delay(50);          // 等待傳感器穩(wěn)定
  x = readSensors();  // 檢查傳感器的值

} while (x < 100);



break

break用于中止do,for,或while循環(huán),繞過正常的循環(huán)條件。它也用于中止switch語句。

示例:

 for (x = 0; x < 255; x ++)
{
    digitalWrite(PWMpin, x);
    sens = analogRead(sensorPin);  
    if (sens > threshold){      // bail out on sensor detect
       x = 0;
       break;
    }  
    delay(50);
}



continue

continue語句跳過一個循環(huán)的當前迭代的余下部分。(do,for,或while)。通過檢查循環(huán)測試條件它將繼續(xù)進行隨后的迭代。

示例:

for (x = 0; x < 255; x ++)
{
    if (x > 40 && x < 120){      // create jump in values
        continue;
    }

    digitalWrite(PWMpin, x);
    delay(50);
}



return

終止一個函數,并向被調用函數并返回一個值,如果你想的話。

語法:

return; 
return value; // both forms are valid 

參數:
value: 任何類型的變量或常量

示例:

//一個函數,用于對一個傳感器輸入與一個閾值進行比較
 
 int checkSensor(){       
    if (analogRead(0) > 400) {
        return 1;
    else{
        return 0;
    }
}

return 關鍵字對測試一段代碼很方便,不需“注釋掉”大段的可能是錯誤的代碼。

void loop(){

//在此測試代碼是個好想法

return;

// 這里是功能不正常的代碼
// 這里的代碼永遠也不會執(zhí)行
}




goto

在程序中轉移程序流到一個標記點

語法:

label: 
goto label; // sends program flow to the label 

提示:
在C程序中不建議使用goto,而且一些C編程書的作者主張永遠不要使用goto語句,但是明智地使用它可以 簡化某些代碼。許多程序員不贊成使用goto的原因是,無節(jié)制地使用goto語句很容易產生執(zhí)行流混亂的很難被調試程序。 盡管如是說,仍然有很多使用goto語句而大大簡化編碼的實例。其中之一就是從一個很深的循環(huán)嵌套中跳出去,或者是if邏輯塊,在某人些條件下。

示例:

 for(byte r = 0; r < 255; r++){
    for(byte g = 255; g > -1; g--){
        for(byte b = 0; b < 255; b++){
            if (analogRead(0) > 250){ goto bailout;}
            // 其它語句。。。
        }
    }
}
bailout:



相關語法

分號

用于一個語句的結束
示例

	int a = 13;

提示
忘記在一行的末尾加一個分號將產生一個編譯器錯誤。該錯誤信息可能是明顯的,且會提及丟失分號,但也許不會。如果出現(xiàn)一個不可理喻的或看起來不合邏輯的錯誤,其中一個首先要做的事就是檢查分號丟失。編譯器會在前一行的附近發(fā)出抱怨。



大括號

大括號(又稱括弧或花括號)是C語言的主要組成部分。它們用在幾個不同的結構中,大致如下,這可能會令初學者感到困惑。

一個左大括號必須有一個右大括號跟在后面。這是一個常被稱為平衡括號的條件。Arduino IDE(集成開發(fā)環(huán)境)包含一個方便的特性以檢驗平衡大括號。只需選擇一個大括號,甚至直接在一個大括號后面點擊插入點,然后它的邏輯上的同伴就會高亮顯示。
目前此功能有些許錯誤,因為IDE經常在文本中(錯誤地)發(fā)現(xiàn)一個已經被注釋掉的大括號。

初級程序員,和從BASIC轉到C的程序員常常發(fā)現(xiàn)使用大括號令人困惑或畏縮。畢竟,用同樣的大括號在子例程(函數)中替換RETURN語句,在條件語句中替換ENDIF語句和在FOR循環(huán)中替換NEXT語句。

由于大括號的使用是如此的多樣,當插入一個需要大括號的結構時,直接在打出開括號之后打出閉括號是個不錯的編程實踐。然后在大括號之間插入一些回車符,接著開始插入語句。你的大括號,還有你的態(tài)度,將永遠不會變得不平衡。

不平衡的大括號常常導致古怪的,難以理解的編譯器錯誤,有時在大型程序中很難查出。因為它們的多樣的使用,大括號對于程序的語法也是極其重要的,對一個大括號移動一行或兩行常常顯著地影響程序的意義。
大括號的主要用法

//函數
   void myfunction(datatype argument){
    statements(s)
  }
 


//循環(huán)
   while (boolean expression)
  {
     statement(s)
  }

  do
  {
     statement(s)
  } while (boolean expression);

  for (initialisation; termination condition; incrementing expr)
  {
     statement(s)
  } 
 


//條件語句
 
  if (boolean expression)
  {
     statement(s)
  }

  else if (boolean expression)
  {
     statement(s)
  } 
  else
  {
     statement(s)
  }




注釋

注釋是程序中的一些行,用于讓自己或他人了解程序的工作方式。他們會被編譯器忽略,而不會輸出到控制器,所以它們不會占用Atmega芯片上的任何空間。

注釋唯一的目的是幫助你理解(或記憶)你的程序是怎樣工作的,或者是告知其他人你的程序是怎樣工作的。標記一行為注釋只有兩種方式:
示例

  x = 5;  //這是一個單行注釋。此斜線后的任何內容都是注釋
         //直到該行的結尾
		
/* 這是多行注釋 - 用它來注釋掉整個代碼塊
if (gwb == 0){   //在多行注釋中使用單行注釋是沒有問題的
x = 3;           /* 但是其中不可以使用另一個多行注釋 - 這是不合法的 */
}


//別忘了加上“關閉”注釋符 - 它們必須是平衡的
*/

提示


當實驗代碼時,“注釋掉”你的程序的一部分來移除可能是錯誤的行是一種方便的方法。這不是把這些行從程序中移除,而是把它們放到注釋中,所以編譯器就會忽略它們。這在定位問題時,或者當程序無法編譯通過且編譯錯誤信息很古怪或沒有幫助時特別有用。



define

#define 宏定義
宏定義是一個有用的C組件,它允許程序員在程序編譯前給常量取一個名字。在arduino中定義的常量不會在芯片中占用任何程序空間。編譯器在編譯時會將這些常量引用替換為定義的值。

這雖然可能有些有害的副作用,舉例來說,一個已被定義的常量名被包含在一些其它的常量或變量名中。那樣的話該文本將被替換成被定義的數字(或文本)。


通常,用const關鍵字定義常量是更受歡迎的且用來代替#define會很有用。


Arduino宏定義與C宏定義有同樣的語法


語法

#define constantName value 

注意‘#’是必須的

示例:

#define ledPin 3
// 編譯器在編譯時會將任何提及l(fā)edPin的地方替換成數值3。

提示
#define語句的后面分號。如果你加了一個,編譯器將會在進一步的頁面引發(fā)奇怪的錯誤。

#define ledPin 3;    // this is an error 

類似地,包含一個等號通常也會在進一步的頁面引發(fā)奇怪的編譯錯誤。

#define ledPin  = 3  // this is also an error 




include

#include 包含

#include用于在你的sketch中包含外部的庫。這使程序員可以訪問一個巨大的標準C庫(預定義函數集合)的集合。

AVR C庫(AVR是Atmel芯片的一個基準,Arduino正是基于它)的主參考手冊頁在這里。


注意#include和#define相似,沒有分號終止符,且如果你加了,編譯器會產生奇怪的錯誤信息。

示例

該示例包含一個用于輸出數據到程序空間閃存的庫,而不是內存。這會為動態(tài)內存需求節(jié)省存儲空間且使需要創(chuàng)建巨大的查找表變得更實際。

#include <avr/pgmspace.h>

prog_uint16_t myConstants[] PROGMEM = {0, 21140, 702  , 9128,  0, 25764, 8456,
0,0,0,0,0,0,0,0,29810,8968,29762,29762,4500};





算術運算符

賦值

=賦值運算符(單個等號)

把等號右邊的值存儲到等號左邊的變量中。
在C語言中單個等號被稱為賦值運算符。它與在代數課中的意義不同,后者象征等式或相等。賦值運算符告訴微控制器求值等號右邊的變量或表達式,然后把結果存入等號左邊的變量中。


示例

  int sensVal;                  //聲明一個名為sensVal的整型變量
 senVal = analogRead(0);       //存儲(數字的)0號模擬引腳的輸入電壓值到sensVal


編程技巧


賦值運算符(=號)左邊的變量需要能夠保存存儲在其中的值。如果它不足以大到容納一個值,那個存儲在該變量中的值將是錯誤的。


不要混淆賦值運算符[ = ](單個等號)和比較運算符[ == ](雙等號),后者求值兩個表達式是否相等。




加,減,乘,除

描述

這些運算符(分別)返回兩人運算對象的和,差,積,商。這些操作受運算對象的數據類型的影響。所以,例如,9 / 4結果是2,如果9和2是整型數。這也意味著運算會溢出,如果結果超出其在相應的數據類型下所能表示的數。(例如,給整型數值32767加1結果是-32768)。如果運算對象是不同的類型,會用那個較大的類型進行計算。

如果其中一個數字(運算符)是float類型或double類型,將采用浮點數進行計算。

示例

y = y + 3;
x = x - 7;
i = j * 6;
r = r / 5;

語法

result = value1 + value2;
result = value1 - value2;
result = value1 * value2;
result = value1 / value2;

參數:

value1:任何變量或常量

value2:任何變量或常量


編程技巧:

要知道整型常量默認為int型,因此一些常量計算可能會溢出(例如:60 * 1000將產生負的結果)

選擇一個大小足夠大的變量以容納你的最大的計算結果。

要知道你的變量在哪一點將會“翻轉”且要知道在另一個方向上會發(fā)生什么,例如:(0 - 1)或(0 - 32768)。

對于數學需要分數,就使用浮點變量,但是要注意它們的缺點:占用空間大,計算速度慢。


使用強制類型轉換符例如:(int)myFloat以在運行中轉換一個變量到另一個類型。




取模

%(取模)

描述

計算一個數除以另一個數的余數。這對于保持一個變量在一個特定的范圍很有用(例如:數組的大小)。


語法

result = dividend % divisor 


參數

dividend: 被除數

divisor: 除數


結果:余數


示例

x = 7 % 5;   // x now contains 2
x = 9 % 5;   // x now contains 4
x = 5 % 5;   // x now contains 0
x = 4 % 5;   // x now contains 4

示例代碼

 /* update one value in an array each time through a loop */

int values[10];
int i = 0;

void setup() {}

void loop()
{
  values[i] = analogRead(0);
  i = (i + 1) % 10;   // modulo operator rolls over variable  
}

 


提示:

取模運算符不能用于浮點型數。




比較運算符

if(條件) and ==, !=, <, > (比較運算符)

if,用于和比較運算符聯(lián)合使用,測試某一條件是否到達,例如一個輸入超出某一數值。if條件測試的格式:

if (someVariable > 50)
{
  // do something here
}
 

該程序測試someVariable是否大于50。如果是, 程序執(zhí)行特定的動作。換句話說,如果圓括號中的語句為真,花括號中的語句就會運行。否則,程序跳過該代碼。

if語句后的花括號可能被省略。如果這么做了,下一行(由分號定義的行)就會變成唯一的條件語句。

if (x > 120) digitalWrite(LEDpin, HIGH); 

if (x > 120)
digitalWrite(LEDpin, HIGH); 

if (x > 120){ digitalWrite(LEDpin, HIGH); } 

if (x > 120){ 
  digitalWrite(LEDpin1, HIGH);
  digitalWrite(LEDpin2, HIGH); 
}                                 // all are correct

圓括號中被求值的語句需要使用一個或多個運算符:


比較運算符:

 x == y (x is equal to y)
 x != y (x is not equal to y)
 x <  y (x is less than y)  
 x >  y (x is greater than y) 
 x <= y (x is less than or equal to y) 
 x >= y (x is greater than or equal to y)
 

警告:

小心偶然地使用單個等號(例如if(x = 10))。單個等號是賦值運算符,這里設置x為10(將值10存入變量x)。改用雙等號(例如if (x == 10)),這個是比較運算符,用于測試x是否等于10。后者只在x等于10時返回真,但是前者將總是為真。

這是因為C如下求值語句if(x=10):10分配給x(切記單個等號是賦值運算符),因此x現(xiàn)在為10。然后'if'條件求值10,其總是為真,由于任何非零數值都為真值。由此,if (x = 10)將總是求值為真,這不是使用if語句所期望的結果。另外,變量x將被設置為10,這也不是期望的操作。

if也可以是使用[if...else]的分支控制結構的一部分。





布爾運算符

它們可用于if語句中的條件

&& (邏輯與)
只有在兩個操作數都為真時才返回真,例如:

if (digitalRead(2) == HIGH  && digitalRead(3) == HIGH) { // read two switches 
  // ...
} 

只在兩個輸入都為高時返回真


|| (邏輯或)
任意一個為真時返回真,例如:

if (x > 0 || y > 0) {
  // ...
} 

x或y任意一個大于0時返回真

! (非)
當操作數為假時返回真,例如:

if (!x) { 
  // ...
} 

若x為假返回真(即如果x等于0)


警告

確保你沒有把布爾與運算符,&&(兩個與符號)錯認為按位與運算符&(單個與符號)。它們是完全不同的概念。

同樣,不要混淆布爾或運算符||(雙豎杠)與按位或運算符|(單豎杠)。

按位取反~(波浪號)看起來與布爾非!有很大不同(感嘆號或程序員口中的“棒”),但是你仍然必須確保在什么地方用哪一個。


例如

 if (a >= 10 && a <= 20){}   // true if a is between 10 and 20




指針運算符

&(引用)和 *(間接引用)

指針對于C初學者來說是更復雜的對象之一。并且可能寫大量的Arduino程序甚至都不會遇到指針。
無論如何,巧妙地控制特定的數據結構,使用指針可以簡化代碼,而且在自己工具箱中擁有熟練控制指針的知識是很方便的。




位運算

位與

按位與(&)

按位操作符在變量的位級執(zhí)行運算。它們幫助解決各種常見的編程問題。以下大部分資料來自一個有關位數學的優(yōu)秀教程,或許可以在這里找到。[1]


描述和語法


以下是所有這些運算符的描述和語法。更詳細的資料或許可以在參考指南中找到。


按位與(&)

在C++中按位與運算符是單個與符號,
用于其它兩個整型表達式之間使用。按位與運算獨立地在周圍的表達式的每一位上執(zhí)行操作。根據這一規(guī)則:如果兩個輸入位都是1,結果輸出1,否則輸出0。表達這一思想的另一個方法是:

    0  0  1  1    operand1
    0  1  0  1    operand2
    ----------
    0  0  0  1    (operand1 & operand2) - returned result
 

在Arduino中,int型是16位的。所以在兩個整型表達式之間使用&將會導致16個與運算同時發(fā)生。代碼片斷就像這樣:

    int a =  92;    // in binary: 0000000001011100
    int b = 101;    // in binary: 0000000001100101
    int c = a & b;  // result:    0000000001000100, or 68 in decimal.
 

在a和b的16位的每一位將使用按位與處理。且所有16位結果存入C中,以二進制存入的結果值01000100,即十進制的68。


按位與的其中一個最常用的用途是從一個整型數中選擇特定的位,常被稱為掩碼屏蔽??慈缦率纠?br />





位或

按位或(|)


在C++中按位或運算符是垂直的條桿符號,|。就像&運算符,|獨立地計算它周圍的兩個整型表達式的每一位。(當然)它所做的是不同的(操作)。兩個輸入位其中一個或都是1按位或將得到1,否則為0。換句話說:

    0  0  1  1    operand1
    0  1  0  1    operand2
    ----------
    0  1  1  1    (operand1 | operand2) - returned result
 

這是一個使用一小斷C++代碼描述的按位或(運算)的例子:

    int a =  92;    // in binary: 0000000001011100
    int b = 101;    // in binary: 0000000001100101
    int c = a | b;  // result:    0000000001111101, or 125 in decimal.
 


按位與和按位或的一個共同的工作是在端口上進行程序員稱之為讀-改-寫的操作。在微控制器中,每個端口是一個8位數字,每一位表示一個引腳的狀態(tài)。寫一個端口可以同時控制所有的引腳。


PORTD是內建的參照數字口0,1,2,3,4,5,6,7的輸出狀態(tài)的常量。如果一個比特位是1,那么該引腳置高。(引腳總是需要用pinMode()指令設置為輸出模式)。所以如果我們寫入PORTD = B00110001;我們就會讓引腳2,3和7輸出高。一個小小的問題是,我們同時也改變了某些引腳的0,1狀態(tài)。這用于Arduino與串口通訊,所以我們可能會干擾串口通訊。


我們的程序規(guī)則是:
僅僅獲取和清除我們想控制的與相應引腳對應的位(使用按位與)。
合并要修改的PORTD值與所控制的引腳的新值(使用按位或)。

int i;     // counter variable
int j;

void setup(){
DDRD = DDRD | B11111100; // set direction bits for pins 2 to 7, leave 0 and 1 untouched (xx | 00 == xx)
// same as pinMode(pin, OUTPUT) for pins 2 to 7
Serial.begin(9600);
}

void loop(){
for (i=0; i<64; i++){

PORTD = PORTD & B00000011;  // clear out bits 2 - 7, leave pins 0 and 1 untouched (xx & 11 == xx)
j = (i << 2);               // shift variable up to pins 2 - 7 - to avoid pins 0 and 1
PORTD = PORTD | j;          // combine the port information with the new information for LED pins
Serial.println(PORTD, BIN); // debug to show masking
delay(100);
   }
}
 






位異或

按位異或(^)


在C++中有一個有點不尋常的操作,它被稱為按位異或,或者XOR(在英語中,通常讀作“eks-or”)。按位異或運算符使用符號^。該運算符與按位或運算符“|”非常相似 ,唯一的不同是當輸入位都為1時它返回0。

    0  0  1  1    operand1
    0  1  0  1    operand2
    ----------
    0  1  1  0    (operand1 ^ operand2) - returned result
 


看待XOR的另一個視角是,當輸入不同時結果為1,當輸入相同時結果為0。


這里是一個簡單的示例代碼:

   
    int x = 12;     // binary: 1100
    int y = 10;     // binary: 1010
    int z = x ^ y;  // binary: 0110, or decimal 6
 

“^”運算符常用于翻轉整數表達式的某些位(例如從0變?yōu)?,或從1變?yōu)?)。在一個按位異或操作中,如果相應的掩碼位為1, 該位將翻轉,如果為0,該位不變。以下是一個閃爍引腳5的程序.

// Blink_Pin_5
// demo for Exclusive OR
void setup(){
DDRD = DDRD | B00100000; // set digital pin five as OUTPUT 
Serial.begin(9600);
}

void loop(){
PORTD = PORTD ^ B00100000;  // invert bit 5 (digital pin 5), leave others untouched
delay(100);
}
 





位非

按位取反(~)

在C++中按位取反運算符為波浪符“~”。不像“&”和“|”,按位取反運算符應用于其右側的單個操作數。按位取反操作會翻轉其每一位。0變?yōu)?,1變?yōu)?。例如:

    0  1    operand1
 
   ----------
    1  0   ~ operand1
 
    int a = 103;    // binary:  0000000001100111
    int b = ~a;     // binary:  1111111110011000 = -104
 

看到此操作的結果為一個負數:-104,你可能會感到驚訝,這是因為一個整型變量的最高位是所謂的符號位。如果最高位為1,該整數被解釋為負數。這里正數和負數的編碼被稱為二進制補碼。欲了解更多信息,請參閱維基百科條目:補碼。


順便說一句,值得注意的是,對于任何整數x, ~x 與 -x-1 相等。


有時候,符號位在有符號整數表達式中能引起一些不期的意外。





左移、右移

左移運算(<<),右移運算(>>)

描述

From The Bitmath Tutorial in The Playground


在C++中有兩個移位運算符:左移運算符<<和右移運算符>>。這些運算符將使左邊操作數的每一位左移或右移其右邊指定的位數。


語法

variable << number_of_bits 

variable >> number_of_bits 

參數<br>
 
*variable - (byte, int, long) number_of_bits integer <= 32 <br>


示例:<br>
    <pre style="color:green">
	int a = 5;        // binary: 0000000000000101
	int b = a << 3;   // binary: 0000000000101000, or 40 in decimal
	int c = b >> 3;   // binary: 0000000000000101, or back to 5 like we started with


當把x左移y位(x << y),x中最左邊的y位將會丟失。

	int a = 5;        // binary: 0000000000000101
	int b = a << 14;  // binary: 0100000000000000 - 101中的第一個1被丟棄
 

如果您確信沒有值被移出,理解左移位運算符一個簡單的辦法是,把它的左操作數乘2將提高其冪值。例如,要生成2的乘方,可以使用以下表達式:

    1 <<  0  ==    1
    1 <<  1  ==    2
    1 <<  2  ==    4
    1 <<  3  ==    8
    ...
    1 <<  8  ==  256
    1 <<  9  ==  512
    1 << 10  == 1024
    ...
 

當把x右移y位,x的最高位為1,該行為依賴于x的確切的數據類型。如果x的類型是int,最高位為符號位,決定x是不是負數,正如我們在上面已經討論過的。在這種情況下,符號位會復制到較低的位:

	int x = -16;     // binary: 1111111111110000
	int y = x >> 3;  // binary: 1111111111111110

該行為,被稱為符號擴展,常常不是你所期待的。反而,你可能希望移入左邊的是0。事實上右移規(guī)則對于無符合整型表達式是不同的。所以你可以使用強制類型轉換來避免左邊移入1。

	int x = -16;                   // binary: 1111111111110000
	int y = (unsigned int)x >> 3;  // binary: 0001111111111110
 

如果你可以很小心地避免符號擴展,你可以使用右移位運算符>>,作為除以2的冪的一種方法。例如

	int x = 1000;
	int y = x >> 3;   // 1000除以8,得y = 125.




復合運算符

自加++
i++; //相當于 i = i + 1;
自減--
i--; //相當于 i = i - 1;
復合加+=
i+=5; //相當于 i = i + 5;
復合減-=
i-=5; //相當于 i = i - 5;
復合乘*=
i*=5; //相當于 i = i * 5;
復合除/=
i/=5; //相當于 i = i / 5;
復合與&=
i&=5; //相當于 i = i & 5;
復合或|=
i|=5; //相當于 i = i | 5;





變量

(本節(jié)轉自極客工坊)

常量

constants是在Arduino語言里預定義的變量。它們被用來使程序更易閱讀。我們按組將常量分類。
邏輯層定義,true與false(布爾Boolean常量)

在Arduino內有兩個常量用來表示真和假:true和 false。
false

在這兩個常量中false更容易被定義。false被定義為0(零)。
true

true通常被定義為1,這是正確的,但true具有更廣泛的定義。在布爾含義(Boolean sense)里任何 非零 整數 為true。所以在布爾含義內-1,2和-200都定義為ture。 需要注意的是true和false常量,不同于HIGH,LOW,INPUT和OUTPUT,需要全部小寫。

——這里引申一下題外話arduino是大小寫敏感語言(case sensitive)。
引腳電壓定義,HIGH和LOW

當讀?。╮ead)或寫入(write)數字引腳時只有兩個可能的值: HIGH 和 LOW 。
HIGH

HIGH(參考引腳)的含義取決于引腳(pin)的設置,引腳定義為INPUT或OUTPUT時含義有所不同。當一個引腳通過pinMode被設置為INPUT,并通過digitalRead讀?。╮ead)時。如果當前引腳的電壓大于等于3V,微控制器將會返回為HIGH。 引腳也可以通過pinMode被設置為INPUT,并通過digitalWrite設置為HIGH。輸入引腳的值將被一個內在的20K上拉電阻 控制 在HIGH上,除非一個外部電路將其拉低到LOW。 當一個引腳通過pinMode被設置為OUTPUT,并digitalWrite設置為HIGH時,引腳的電壓應在5V。在這種狀態(tài)下,它可以 輸出電流 。例如,點亮一個通過一串電阻接地或設置為LOW的OUTPUT屬性引腳的LED。
LOW

LOW的含義同樣取決于引腳設置,引腳定義為INPUT或OUTPUT時含義有所不同。當一個引腳通過pinMode配置為INPUT,通過digitalRead設置為讀?。╮ead)時,如果當前引腳的電壓小于等于2V,微控制器將返回為LOW。 當一個引腳通過pinMode配置為OUTPUT,并通過digitalWrite設置為LOW時,引腳為0V。在這種狀態(tài)下,它可以 倒灌 電流。例如,點亮一個通過串聯(lián)電阻連接到+5V,或到另一個引腳配置為OUTPUT、HIGH的的LED。
數字引腳(Digital pins)定義,INPUT和OUTPUT

數字引腳當作 INPUT 或 OUTPUT都可以 。用pinMode()方法使一個數字引腳從INPUT到OUTPUT變化。
引腳(Pins)配置為輸入(Inputs)

Arduino(Atmega)引腳通過pinMode()配置為 輸入(INPUT) 即是將其配置在一個高阻抗的狀態(tài)。配置為INPUT的引腳可以理解為引腳取樣時對電路有極小的需求,即等效于在引腳前串聯(lián)一個100兆歐姆(Megohms)的電阻。這使得它們非常利于讀取傳感器,而不是為LED供電。
引腳(Pins)配置為輸出(Outputs)

引腳通過pinMode()配置為 輸出(OUTPUT) 即是將其配置在一個低阻抗的狀態(tài)。

這意味著它們可以為電路提供充足的電流。Atmega引腳可以向其他設備/電路提供(提供正電流positive current)或倒灌(提供負電流negative current)達40毫安(mA)的電流。這使得它們利于給LED供電,而不是讀取傳感器。輸出(OUTPUT)引腳被短路的接地或5V電路上會受到損壞甚至燒毀。Atmega引腳在為繼電器或電機供電時,由于電流不足,將需要一些外接電路來實現(xiàn)供電。





宏定義

#define 	HIGH   0x1
			高電平
#define 	LOW   0x0
			低電平
#define 	INPUT   0x0
			輸入
#define 	OUTPUT   0x1
			輸出
#define 	true   0x1
			真
#define 	false   0x0
			假
#define 	PI   3.14159265
			PI.
#define 	HALF_PI   1.57079
			二分之一PI
#define 	TWO_PI   6.283185
			二倍PI
#define 	DEG_TO_RAD   0.01745329
			弧度轉角度
#define 	RAD_TO_DEG   57.2957786
			角度轉弧度




整型常量

整數常量

整數常量是直接在程序中使用的數字,如123。默認情況下,這些數字被視為int,但你可以通過U和L修飾符進行更多的限制(見下文)。 通常情況下,整數常量默認為十進制,但可以加上特殊前綴表示為其他進制。

進制 			例子 		格式 		備注
10(十進制) 	123 		無 	
2(二進制) 	B1111011 	前綴'B' 	只適用于8位的值(0到255)字符0-1有效
8(八進制) 	0173 		前綴”0” 	字符0-7有效
16(十六進制)	0x7B 		前綴”0x” 	字符0-9,A-F,A-F有效

小數是十進制數。這是數學常識。如果一個數沒有特定的前綴,則默認為十進制。

二進制以2為基底,只有數字0和1是有效的。

示例:

101  //和十進制5等價 (1*2^2 + 0*2^1 + 1*2^0)

二進制格式只能是8位的,即只能表示0-255之間的數。如果輸入二進制數更方便的話,你可以用以下的方式:

myInt = (B11001100 * 256) + B10101010;    // B11001100 作為高位。

八進制是以8為基底,只有0-7是有效的字符。前綴“0”(數字0)表示該值為八進制。

0101    // 等同于十進制數65   ((1 * 8^2) + (0 * 8^1) + 1) 

警告:八進制數0前綴很可能無意產生很難發(fā)現(xiàn)的錯誤,因為你可能不小心在常量前加了個“0”,結果就悲劇了。

十六進制以16為基底,有效的字符為0-9和A-F。十六進制數用前綴“0x”(數字0,字母愛克斯)表示。請注意,A-F不區(qū)分大小寫,就是說你也可以用a-f。

示例:

0x101   // 等同于十進制257   ((1 * 16^2) + (0 * 16^1) + 1)

U & L 格式

默認情況下,整型常量被視作int型。要將整型常量轉換為其他類型時,請遵循以下規(guī)則:

  • 'u' or 'U' 指定一個常量為無符號型。(只能表示正數和0) 例如: 33u
  • 'l' or 'L' 指定一個常量為長整型。(表示數的范圍更廣) 例如: 100000L
  • 'ul' or 'UL' 這個你懂的,就是上面兩種類型,稱作無符號長整型。 例如:32767ul




浮點數常量

浮點常量

和整型常量類似,浮點常量可以使得代碼更具可讀性。浮點常量在編譯時被轉換為其表達式所取的值。 例子

n = .005; 浮點數可以用科學記數法表示。'E'和'e'都可以作為有效的指數標志。

浮點數		被轉換為		被轉換為
10.0 		10
2.34E5		2.34 * 10^5		234000
67E-12		67.0 * 10^-12	0.000000000067





數據類型

void

void只用在函數聲明中。它表示該函數將不會被返回任何數據到它被調用的函數中。
例子

//功能在“setup”和“l(fā)oop”被執(zhí)行
//但沒有數據被返回到高一級的程序中

void setup()
{
// ...
}
 
void loop()
{
// ...
}





boolean

布爾

一個布爾變量擁有兩個值,true或false。(每個布爾變量占用一個字節(jié)的內存。)
例子

int LEDpin = 5;       // LED與引腳5相連
int switchPin = 13;   // 開關的一個引腳連接引腳13,另一個引腳接地。
 
boolean running = false;
 
void setup()
{
  pinMode(LEDpin, OUTPUT);
  pinMode(switchPin, INPUT);
  digitalWrite(switchPin, HIGH);      // 打開上拉電阻
}
 
void loop()
{
  if (digitalRead(switchPin) == LOW)
  {  // 按下開關 - 使引腳拉向高電勢
    delay(100);                        // 通過延遲,以濾去開關抖動產生的雜波
    running = !running;                // 觸發(fā)running變量
    digitalWrite(LEDpin, running)      //點亮LED
    }
  }





char

char
描述

一個數據類型,占用1個字節(jié)的內存存儲一個字符值。字符都寫在單引號,如'A'(多個字符(字符串)使用雙引號,如“ABC”)。

字符以編號的形式存儲。你可以在ASCII表中看到對應的編碼。這意味著字符的ASCII值可以用來作數學計算。(例如'A'+ 1,因為大寫A的ASCII值是65,所以結果為66)。如何將字符轉換成數字參考serial.println命令。

char數據類型是有符號的類型,這意味著它的編碼為-128到127。對于一個無符號一個字節(jié)(8位)的數據類型,使用byte數據類型。
例如

  char myChar = 'A';
  char myChar = 65;      // both are equivalent





unsigned char

無符號字符型
描述

一個無符號數據類型占用1個字節(jié)的內存。與byte的數據類型相同。

無符號的char數據類型能編碼0到255的數字。

為了保持Arduino的編程風格的一致性,byte數據類型是首選。
例子

    unsigned char myChar = 240;





byte

字節(jié)型
描述

一個字節(jié)存儲8位無符號數,從0到255。
例子

    byte b = B10010;  // "B" 是二進制格式(B10010等于十進制18)





int

整型
簡介

整數是基本數據類型,占用2字節(jié)。整數的范圍為-32,768到32,767( -2^15 ~(2^15)-1)。

整數類型使用2的補碼方式存儲負數。最高位通常為符號位,表示數的正負。其余位被“取反加1”(此處請參考補碼相關資料,不再贅述)。

Arduino為您處理負數計算問題,所以數學計算對您是透明的(術語:實際存在,但不可操作。相當于“黑盒”)。但是,當處理右移位運算符(?)時,可能有未預期的編譯過程。
示例

int ledPin = 13;

語法

int var = val;
  • var - 變量名
  • val - 賦給變量的值

提示

當變量數值過大而超過整數類型所能表示的范圍時(-32,768到32,767),變量值會“回滾”(詳情見示例)。

   int x
   x = -32,768;
   x = x - 1;       // x 現(xiàn)在是 32,767。
 
   x = 32,767;
   x = x + 1;       // x 現(xiàn)在是 -32,768。





unsigned int

無符號整型
描述

unsigned int(無符號整型)與整型數據同樣大小,占據2字節(jié)。它只能用于存儲正數而不能存儲負數,范圍0~65,535 (2^16) - 1)。

無符號整型和整型最重要的區(qū)別是它們的最高位不同,既符號位。在Arduino整型類型中,如果最高位是1,則此數被認為是負數,剩下的15位為按2的補碼計算所得值。
例子

unsigned int ledPin = 13;

語法

unsigned int var = val;
  • var - 無符號變量名稱
  • val - 給變量所賦予的值


編程提示

當變量的值超過它能表示的最大值時它會“滾回”最小值,反向也會出現(xiàn)這種現(xiàn)象。

   unsigned int x
       x = 0;
   x = x - 1;       //x現(xiàn)在等于65535--向負數方向滾回
   x = x + 1;       //x現(xiàn)在等于0--滾回





word


描述

一個存儲一個16位無符號數的字符,取值范圍從0到65535,與unsigned int相同。
例子

    word w = 10000; 



long

長整型
描述

長整數型變量是擴展的數字存儲變量,它可以存儲32位(4字節(jié))大小的變量,從-2,147,483,648到2,147,483,647。
例子

long speedOfLight = 186000L; //參見整數常量‘L’的說明

語法

long var = val;
  • var - 長整型變量名
  • var - 賦給變量的值






unsigned long

無符號長整型
描述

無符號長整型變量擴充了變量容量以存儲更大的數據,它能存儲32位(4字節(jié))數據。與標準長整型不同無符號長整型無法存儲負數,其范圍從0到4,294,967,295(2 ^ 32 - 1)。
例子

unsigned long time;
 
void setup()
{
     Serial.begin(9600);
}
 
void loop()
{
  Serial.print("Time: ");
  time = millis();
//程序開始后一直打印時間
  Serial.println(time);
//等待一秒鐘,以免發(fā)送大量的數據
     delay(1000);
}

語法

unsigned long var = val;
  • var - 你所定義的變量名
  • val - 給變量所賦的值





float

單精度浮點型
描述

float,浮點型數據,就是有一個小數點的數字。浮點數經常被用來近似的模擬連續(xù)值,因為他們比整數更大的精確度。浮點數的取值范圍在3.4028235 E+38 ~ -3.4028235E +38。它被存儲為32位(4字節(jié))的信息。

float只有6-7位有效數字。這指的是總位數,而不是小數點右邊的數字。與其他平臺不同的是,在那里你可以使用double型得到更精確的結果(如15位),在Arduino上,double型與float型的大小相同。

浮點數字在有些情況下是不準確的,在數據大小比較時,可能會產生奇怪的結果。例如 6.0 / 3.0 可能不等于 2.0。你應該使兩個數字之間的差額的絕對值小于一些小的數字,這樣就可以近似的得到這兩個數字相等這樣的結果。

浮點運算速度遠遠慢于執(zhí)行整??數運算,例如,如果這個循環(huán)有一個關鍵的計時功能,并需要以最快的速度運行,就應該避免浮點運算。程序員經常使用較長的程式把浮點運算轉換成整數運算來提高速度。
舉例

    float myfloat;
    float sensorCalbrate = 1.117;

語法

float var = val;
  • var——您的float型變量名稱
  • val——分配給該變量的值

示例代碼

   int x;
   int y;
   float z;
 
   x = 1;
   y = x / 2;         // Y為0,因為整數不能容納分數
   z = (float)x / 2.0;   // Z為0.5(你必須使用2.0做除數,而不是2)





double

雙清度浮點型
描述

雙精度浮點數。占用4個字節(jié)。

目前的arduino上的double實現(xiàn)和float相同,精度并未提高。
提示

如果你從其他地方得到的代碼中包含了double類變量,最好檢查一遍代碼以確認其中的變量的精確度能否在arduino上達到。





string

string(字符串)
描述

文本字符串可以有兩種表現(xiàn)形式。你可以使用字符串數據類型(這是0019版本的核心部分),或者你可以做一個字符串,由char類型的數組和空終止字符('\0')構成。(求助,待潤色-Leo)本節(jié)描述了后一種方法。而字符串對象(String object)將讓你擁有更多的功能,同時也消耗更多的內存資源。
舉例

以下所有字符串都是有效的聲明。

  char Str1[15];
  char Str2[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o'};
  char Str3[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o', '\0'};
  char Str4[ ] = "arduino";
  char Str5[8] = "arduino";
  char Str6[15] = "arduino";

聲明字符串的解釋

  • 在Str1中 聲明一個沒有初始化的字符數組
  • 在Str2中 聲明一個字符數組(包括一個附加字符),編譯器會自動添加所需的空字符
  • 在Str3中 明確加入空字符
  • 在Str4中 用引號分隔初始化的字符串常數,編譯器將調整數組的大小,以適應字符串常量和終止空字符
  • 在Str5中 初始化一個包括明確的尺寸和字符串常量的數組
  • 在Str6中 初始化數組,預留額外的空間用于一個較大的字符串

空終止字符

一般來說,字符串的結尾有一個空終止字符(ASCII代碼0)。以此讓功能函數(例如Serial.pring())知道一個字符串的結束。否則,他們將從內存繼續(xù)讀取后續(xù)字節(jié),而這些并不屬于所需字符串的一部分。

這意味著,你的字符串比你想要的文字包含更多的個字符空間。這就是為什么Str2和Str5需要八個字符,即使“Arduino”只有七個字符 - 最后一個位置會自動填充空字符。str4將自動調整為八個字符,包括一個額外的空。在Str3的,我們自己已經明確地包含了空字符(寫入'\ 0')。

需要注意的是,字符串可能沒有一個最后的空字符(例如在Str2中您已定義字符長度為7,而不是8)。這會破壞大部分使用字符串的功能,所以不要故意而為之。如果你注意到一些奇怪的現(xiàn)象(在字符串中操作字符),基本就是這個原因導致的了。
單引號?還是雙引號?

定義字符串時使用雙引號(例如“ABC”),而定義一個單獨的字符時使用單引號(例如'A')
包裝長字符串

你可以像這樣打包長字符串: char myString[] = “This is the first line” ” this is the second line” ” etcetera”;
字符串數組

當你的應用包含大量的文字,如帶有液晶顯示屏的一個項目,建立一個字符串數組是非常便利的。因為字符串本身就是數組,它實際上是一個兩維數組的典型。

在下面的代碼,”char*”在字符數據類型char后跟了一個星號'*'表示這是一個“指針”數組。所有的數組名實際上是指針,所以這需要一個數組的數組。指針對于C語言初學者而言是非常深奧的部分之一,但我們沒有必要了解詳細指針,就可以有效地應用它。
樣例

char* myStrings[]={
  "This is string 1", "This is string 2", "This is string 3",
  "This is string 4", "This is string 5","This is string 6"};
 
void setup(){
  Serial.begin(9600);
}
 
void loop(){
  for (int i = 0; i < 6; i++){
    Serial.println(myStrings[i]);
    delay(500);
  }
}





String(c++)

描述

String類,是0019版的核心的一部分,允許你實現(xiàn)比運用字符數組更復雜的文字操作。你可以連接字符串,增加字符串,尋找和替換子字符串以及其他操作。它比使用一個簡單的字符數組需要更多的內存,但它更方便。

僅供參考,字符串數組都用小寫的string表示而String類的實例通常用大寫的String表示。注意,在“雙引號”內指定的字符常量通常被作為字符數組,并非String類實例。
函數

  • String
  • charAt()
  • compareTo()
  • concat()
  • endsWith()
  • equals()
  • equalsIgnoreCase()
  • GetBytes()
  • indexOf()
  • lastIndexOf
  • length
  • replace()
  • setCharAt()
  • startsWith()
  • substring()
  • toCharArray()
  • toLowerCase()
  • toUpperCase()
  • trim()

操作符

  • [](元素訪問)
  • +(串連)
  • ==(比較)






array

Arrays (數組)

數組是一種可訪問的變量的集合。Arduino的數組是基于C語言的,因此這會變得很復雜,但使用簡單的數組是比較簡單的。
創(chuàng)建(聲明)一個數組

下面的方法都可以用來創(chuàng)建(聲明)數組。

  myInts [6];
  myPins [] = {2,4,8,3,6};
  mySensVals [6] = {2,4,-8,3,2};
  char message[6] = "hello";
 

你聲明一個未初始化數組,例如myPins。

在myPins中,我們聲明了一個沒有明確大小的數組。編譯器將會計算元素的大小,并創(chuàng)建一個適當大小的數組。

當然,你也可以初始化數組的大小,例如在mySensVals中。請注意,當聲明一個char類型的數組時,你初始化的大小必須大于元素的個數,以容納所需的空字符。
訪問數組

數組是從零開始索引的,也就說,上面所提到的數組初始化,數組第一個元素是為索引0,因此:

mySensVals [0] == 2,mySensVals [1] == 4,

依此類推 。

這也意味著,在包含十個元素的數組中,索引九是最后一個元素。因此,

  int myArray[10] = {9,3,2,4,3,2,7,8,9,11};
  // myArray[9]的數值為11
  // myArray[10],該索引是無效的,它將會是任意的隨機信息(內存地址)
 

出于這個原因,你在訪問數組應該小心。若訪問的數據超出數組的末尾(即索引數大于你聲明的數組的大小- 1),則將從其他內存中讀取數據。從這些地方讀取的數據,除了產生無效的數據外,沒有任何作用。向隨機存儲器中寫入數據絕對是一個壞主意,通常會導致不愉快的結果,如導致系統(tǒng)崩潰或程序故障。要排查這樣的錯誤是也是一件難事。 不同于Basic或JAVA,C語言編譯器不會檢查你訪問的數組是否大于你聲明的數組。
指定一個數組的值:

  mySensVals [0] = 10;

從數組中訪問一個值:

  X = mySensVals [4];

數組和循環(huán)

數組往往在for循環(huán)中進行操作,循環(huán)計數器可用于訪問每個數組元素。例如,將數組中的元素通過串口打印,你可以這樣做:

  int i;
  for (i = 0; i < 5; i = i + 1) {
  Serial.println(myPins[i]);
  }






數據類型轉換

char()

描述

將一個變量的類型變?yōu)閏har。
語法

char(x)

參數

  • x:任何類型的值

返回

  • char




byte()

描述

將一個值轉換為字節(jié)型數值。
語法

byte(x)

參數

  • X:任何類型的值

返回

  • 字節(jié)





int()

簡介

將一個值轉換為int類型。
語法

int(x)

參數

  • x:一個任何類型的值

返回值

  • int類型的值





word()

描述

把一個值轉換為word數據類型的值,或由兩個字節(jié)創(chuàng)建一個字符。
語法

word(x)
word(h, l)

參數

  • X:任何類型的值
  • H:高階(最左邊)字節(jié)
  • L:低序(最右邊)字節(jié)

返回

  • 字符





long()

描述

將一個值轉換為長整型數據類型。

語法

long(x)

參數

  • x:任意類型的數值

返回

  • 長整型數






float()

描述

將一個值轉換為float型數值。
語法

float(x)

參數

  • X:任何類型的值

返回

  • float型數






變量作用域&修飾符

變量作用域

變量的作用域

在Arduino使用的C編程語言的變量,有一個名為 作用域(scope) 的屬性 。這一點與類似BASIC的語言形成了對比,在BASIC語言中所有變量都是 全局(global) 變量。

在一個程序內的全局變量是可以被所有函數所調用的。局部變量只在聲明它們的函數內可見。在Arduino的環(huán)境中,任何在函數(例如,setup(),loop()等)外聲明的變量,都是全局變量。

當程序變得更大更復雜時,局部變量是一個有效確定每個函數只能訪問其自己變量的途徑。這可以防止,當一個函數無意中修改另一個函數使用的變量的程序錯誤。

有時在一個for循環(huán)內聲明并初始化一個變量也是很方便的選擇。這將創(chuàng)建一個只能從for循環(huán)的括號內訪問的變量。
例子:

int gPWMval;  // 任何函數都可以調用此變量
 
void setup()
{
  // ...
}
 
void loop()
{
  int i;    // "i" 只在 "loop" 函數內可用
  float f;  // "f" 只在 "loop" 函數內可用
  // ...
 
  for (int j = 0; j <100; j++){
    //變量j只能在循環(huán)括號內訪問
  }
}






static (靜態(tài)變量)

static關鍵字用于創(chuàng)建只對某一函數可見的變量。然而,和局部變量不同的是,局部變量在每次調用函數時都會被創(chuàng)建和銷毀,靜態(tài)變量在函數調用后仍然保持著原來的數據。

靜態(tài)變量只會在函數第一次調用的時候被創(chuàng)建和初始化。
例子

/* RandomWalk
* Paul Badger 2007
* RandomWalk函數在兩個終點間隨機的上下移動
* 在一個循環(huán)中最大的移動由參數“stepsize”決定
*一個靜態(tài)變量向上和向下移動一個隨機量
*這種技術也被叫做“粉紅噪聲”或“醉步”
*/
 
#define randomWalkLowRange -20
#define randomWalkHighRange 20
 
int stepsize;
 
INT thisTime;
int total;
 
void setup()
{
     Serial.begin(9600);
}
 
void loop()
{        //  測試randomWalk 函數
  stepsize = 5;
  thisTime = randomWalk(stepsize);
serial.println(thisTime);
   delay(10);
}
 
int randomWalk(int moveSize){
  static int  place;     // 在randomwalk中存儲變量
                         // 聲明為靜態(tài)因此它在函數調用之間能保持數據,但其他函數無法改變它的值
 
  place = place + (random(-moveSize, moveSize + 1));
 
  if (place < randomWalkLowRange){                    //檢查上下限
    place = place + (randomWalkLowRange - place);     // 將數字變?yōu)檎较?}
  else if(place > randomWalkHighRange){
    place = place - (place - randomWalkHighRange);     // 將數字變?yōu)樨摲较?}
 
  return place;
}





volatile (易變變量)

volatile關鍵字

volatile這個關鍵字是變量修飾符,常用在變量類型的前面,以告訴編譯器和接下來的程序怎么對待這個變量。

聲明一個volatile變量是編譯器的一個指令。編譯器是一個將你的C/C++代碼轉換成機器碼的軟件,機器碼是arduino上的Atmega芯片能識別的真正指令。

具體來說,它指示編譯器編譯器從RAM而非存儲寄存器中讀取變量,存儲寄存器是程序存儲和操作變量的一個臨時地方。在某些情況下,存儲在寄存器中的變量值可能是不準確的。

如果一個變量所在的代碼段可能會意外地導致變量值改變那此變量應聲明為volatile,比如并行多線程等。在arduino中,唯一可能發(fā)生這種現(xiàn)象的地方就是和中斷有關的代碼段,成為中斷服務程序。
例子

//當中斷引腳改變狀態(tài)時,開閉LED
 
int pin = 13;
volatile int state = LOW;
 
void setup()
{
  pinMode(pin, OUTPUT);
  attachInterrupt(0, blink, CHANGE);
}
 
void loop()
{
  digitalWrite(pin, state);
}
 
void blink()
{
  state = !state;
}





const (不可改變變量)

const關鍵字

const關鍵字代表常量。它是一個變量限定符,用于修改變量的性質,使其變?yōu)橹蛔x狀態(tài)。這意味著該變量,就像任何相同類型的其他變量一樣使用,但不能改變其值。如果嘗試為一個const變量賦值,編譯時將會報錯。

const關鍵字定義的常量,遵守 variable scoping 管轄的其他變量的規(guī)則。這一點加上使用 #define的缺陷 ,使 const 關鍵字成為定義常量的一個的首選方法。
例子

const float pi = 3.14;
float x;
 
// ....
 
x = pi * 2;    // 在數學表達式中使用常量不會報錯
 
pi = 7;        // 錯誤的用法 - 你不能修改常量值,或給常量賦值。

#define 或 const

您可以使用 const 或 #define 創(chuàng)建數字或字符串常量。但 arrays, 你只能使用 const。 一般 const 相對 的#define是首選 的定義常量語法。






輔助工具

sizeof() (sizeof運算符)

描述

sizeof操作符返回一個變量類型的字節(jié)數,或者該數在數組中占有的字節(jié)數。
語法

sizeof(variable)

參數

  • variable: 任何變量類型或數組(如int,float,byte)

示例代碼

sizeof操作符用來處理數組非常有效,它能很方便的改變數組的大小而不用破壞程序的其他部分。

這個程序一次打印出一個字符串文本的字符。嘗試改變一下字符串。

char myStr[] = "this is a test";
int i;
 
void setup(){
  Serial.begin(9600);
}
 
{0}void{/0}{1} {/1}{2}loop{/2}{1}() {{/1}
  for (i = 0; i < sizeof(myStr) - 1; i++){
    Serial.print(i, DEC);
    Serial.print(" = ");
    Serial.println(myStr[i], BYTE);
  }
}

請注意sizeof返回字節(jié)數總數。因此,較大的變量類型,如整數,for循環(huán)看起來應該像這樣。

for (i = 0; i < (sizeof(myInts)/sizeof(int)) - 1; i++) {
  //用myInts[i]來做些事
}





ASCII碼表

代碼	字符	代碼	字符	代碼	字符	代碼	字符 
0		32	[空格]	64	@	96	` 
1		33	!	65	A	97	a 
2		34	"	66	B	98	b 
3		35	#	67	C	99	c 
4		36	$	68	D	100	d 
5		37	%	69	E	101	e 
6		38	&	70	F	102	f 
7		39	'	71	G	103	g 
8		40	(	72	H	104	h 
9		41	)	73	I	105	i 
10		42	*	74	J	106	j 
11		43	+	75	K	107	k 
12		44	,	76	L	108	l 
13		45	-	77	M	109	m 
14		46	.	78	N	110	n 
15		47	/	79	O	111	o 
16		48	0	80	P	112	p 
17		49	1	81	Q	113	q 
18		50	2	82	R	114	r 
19		51	3	83	S	115	s 
20		52	4	84	T	116	t 
21		53	5	85	U	117	u 
22		54	6	86	V	118	v 
23		55	7	87	W	119	w 
24		56	8	88	X	120	x 
25		57	9	89	Y	121	y 
26		58	:	90	Z	122	z 
27		59	;	91	[	123	{ 
28		60	<	92	\	124	| 
29		61	=	93	]	125	} 
30		62	>	94	^	126	~ 
31		63	?	95	_	127	 





基本函數

(本節(jié)由柴樹杉[翻譯整理] (chaishushan@gmail.com))

數字I/O

pinMode()

void pinMode (uint8_t pin, uint8_t mode)

設置引腳模式

配置引腳為輸出或輸出模式.

參數:

  • pin 引腳編號
  • mode: INPUT, OUTPUT, 或 INPUT_PULLUP.

例子:

int ledPin = 13;                 // LED connected to digital pin 13

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  digitalWrite(ledPin, HIGH);   // sets the LED on
  delay(1000);                  // waits for a second
  digitalWrite(ledPin, LOW);    // sets the LED off
  delay(1000);                  // waits for a second
}

注解:

  • 模擬引腳也可以當作數字引腳使用, 編號為14(對應模擬引腳0)到19(對應模擬引腳5).




digitalWrite()

void digitalWrite (uint8_t pin, uint8_t value)

寫數字引腳

寫數字引腳, 對應引腳的高低電平. 在寫引腳之前, 需要將引腳設置為OUTPUT模式.

參數:

  • pin 引腳編號
  • value HIGH 或 LOW

用法:

int ledPin = 13;                 // LED connected to digital pin 13

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  digitalWrite(ledPin, HIGH);   // 點亮LED
  delay(1000);                  // 等待1秒
  digitalWrite(ledPin, LOW);    // 關
  delay(1000);                  // waits for a second
}

注解:

  • 模擬引腳也可以當作數字引腳使用, 編號為14(對應模擬引腳0)到19(對應模擬引腳5).




digitalRead()

int digitalRead (uint8_t pin)  	

讀數字引腳

讀數字引腳, 返回引腳的高低電平. 在讀引腳之前, 需要將引腳設置為INPUT模式.

參數:

  • pin 引腳編號

返回:
HIGH或LOW

int ledPin = 13; // LED connected to digital pin 13
int inPin = 7;   // pushbutton connected to digital pin 7
int val = 0;     // variable to store the read value

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin 13 as output
  pinMode(inPin, INPUT);      // sets the digital pin 7 as input
}

void loop()
{
  val = digitalRead(inPin);   // read the input pin
  digitalWrite(ledPin, val);    // sets the LED to the button's value
}

注解:

   如果引腳沒有鏈接到任何地方, 那么將隨機返回 HIGH 或 LOW. 




模擬I/O

analogReference()

void analogReference (uint8_t type)

配置參考電壓

配置模式引腳的參考電壓. 函數 analogRead 在讀取模擬值之后, 將根據參考電壓將 模擬值轉換到[0,1023]區(qū)間. 有以下類型:


DEFAULT : 默認5V. INTERNAL: 低功耗模式. ATmega168和ATmega8對應1.1V到2.56V. EXTERNAL: 擴展模式. 通過AREF引腳獲取參考電壓.

參數:

  • type 參考類型(DEFAULT/INTERNAL/EXTERNAL)





analogRead()

int analogRead (uint8_t pin)  	

讀模擬引腳

讀模擬引腳, 返回[0-1023]之間的值. 每讀一次需要花1微妙的時間.

參數:

  • pin 引腳編號

返回:

  • 0到1023之間的值

例子:

int analogPin = 3;     // potentiometer wiper (middle terminal) connected to analog pin 3
                       // outside leads to ground and +5V
int val = 0;           // variable to store the value read

void setup()
{
  Serial.begin(9600);          //  setup serial
}

void loop()
{
  val = analogRead(analogPin);    // read the input pin
  Serial.println(val);             // debug value
}




analogWrite()

void analogWrite (uint8_t pin, int value)    

寫模擬引腳
參數:

  • pin 引腳編號
  • value 0到255之間的值, 0對應off, 255對應on

寫一個模擬值(PWM)到引腳. 可以用來控制LED的亮度, 或者控制電機的轉速. 在執(zhí)行該操作后, 應該等待一定時間后才能對該引腳進行下一次的讀或寫操作. PWM的頻率大約為490Hz.

在一些基于ATmega168的新的Arduino控制板(如Mini 和BT)中, 該函數支持以下引腳: 3, 5, 6, 9, 10, 11. 在基于ATmega8的型號中支持9, 10, 11引腳.

例子:

int ledPin = 9;      // LED connected to digital pin 9
int analogPin = 3;   // potentiometer connected to analog pin 3
int val = 0;         // variable to store the read value

void setup()
{
  pinMode(ledPin, OUTPUT);   // sets the pin as output
}

void loop()
{
  val = analogRead(analogPin);   // read the input pin
  analogWrite(ledPin, val / 4);  // analogRead values go from 0 to 1023, analogWrite values from 0 to 255
}




高級I/O

shiftOut()

void shiftOut (uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val)    

位移輸出函數

輸入value數據后Arduino會自動把數據移動分配到8個并行輸出端. 其中dataPin為連接DS的引腳號, clockPin為連接SH_CP的引腳號, bitOrder為設置數據位移順序, 分別為高位先入MSBFIRST或者低位先入LSBFIRST.


參數:

  • dataPin 數據引腳
  • clockPin 時鐘引腳
  • bitOrder 移位順序 ( MSBFIRST 或 LSBFIRST)
  • val 數據


// Do this for MSBFIRST serial
int data = 500;
// shift out highbyte
shiftOut(dataPin, clock, MSBFIRST, (data >> 8));  
// shift out lowbyte
shiftOut(dataPin, clock, MSBFIRST, data);

// Or do this for LSBFIRST serial
data = 500;
// shift out lowbyte
shiftOut(dataPin, clock, LSBFIRST, data);  
// shift out highbyte
shiftOut(dataPin, clock, LSBFIRST, (data >> 8)); 




pulseIn()

unsigned long pulseIn (uint8_t pin, uint8_t state, unsigned long timeout) 			

讀脈沖

讀引腳的脈沖, 脈沖可以是 HIGH 或 LOW. 如果是 HIGH, 函數將先等引腳變?yōu)楦唠娖? 然后 開始計時, 一直到變?yōu)榈碗娖綖橹? 返回脈沖持續(xù)的時間長短, 單位為微秒. 如果超時還沒有 讀到的話, 將返回0.

參數:

  1. pin 引腳編號
  2. state 脈沖狀態(tài)
  3. timeout 超時時間

下面的例子演示了統(tǒng)計高電平的繼續(xù)時間:

int pin = 7;
unsigned long duration;

void setup()
{
  pinMode(pin, INPUT);
}

void loop()
{
  duration = pulseIn(pin, HIGH);
}


時間

millis()

unsigned long millis (void)

毫秒時間

獲取機器運行的時間長度, 單位毫秒. 系統(tǒng)最長的記錄時間為9小時22分, 如果超出時間將從0開始.
警告:

   時間為 unsigned long類型, 如果用 int 保存時間將得到錯誤結果:

delay(ms)

void delay (unsigned long ms)   

延時(毫秒)

延時, 單位毫秒(1秒有1000毫秒).


警告:
參數為unsigned long, 因此在延時參數超過32767(int型最大值)時, 需要用"UL"后綴表示為無符號 長整型, 例如: delay(60000UL);. 同樣在參數表達式, 切表達式中有int類型時, 需要強制轉換為 unsigned long類型, 例如: delay((unsigned long)tdelay * 100UL);.
一下例子設置13引腳對應的LED等以1秒頻率閃爍:

int ledPin = 13;                 // LED connected to digital pin 13

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  digitalWrite(ledPin, HIGH);   // sets the LED on
  delay(1000);                  // waits for a second
  digitalWrite(ledPin, LOW);    // sets the LED off
  delay(1000);                  // waits for a second
}




delayMicroseconds(us)

void delayMicroseconds (unsigned int us)   

延時(微秒)

延時, 單位為微妙(1毫秒有1000微妙). 如果延時的時間有幾千微妙, 那么建議使用 delay 函數. 目前參數最大支持16383微妙(不過以后的版本中可能會變化).

以下代碼向第8號引腳發(fā)送脈沖, 每次脈沖持續(xù)50微妙的時間.


int outPin = 8;                 // digital pin 8

void setup()
{
  pinMode(outPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  digitalWrite(outPin, HIGH);   // sets the pin on
  delayMicroseconds(50);        // pauses for 50 microseconds      
  digitalWrite(outPin, LOW);    // sets the pin off
  delayMicroseconds(50);        // pauses for 50 microseconds      
}




數學庫

min()

#define min(a, b) ((a)<(b)?(a):(b))

最小值

取兩者之間最小值. 例如:

sensVal = min(sensVal, 100); // assigns sensVal to the smaller of sensVal or 100
                             // ensuring that it never gets above 100.




max()

#define max(a, b) ((a)>(b)?(a):(b))

最大值

取兩者之間最大值. 例如:

sensVal = max(senVal, 20); // assigns sensVal to the larger of sensVal or 20
                           // (effectively ensuring that it is at least 20)




abs()

abs(x)   ((x)>0?(x):-(x))

求絕對值




constrain()

#define constrain(amt, low, high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))

調整到區(qū)間

如果值 amt 小于 low, 則返回 low; 如果 amt 大于 high, 則返回 high; 否則, 返回 amt . 一般可以用于將值歸一化到某個區(qū)間.

例如:

sensVal = constrain(sensVal, 10, 150);
// limits range of sensor values to between 10 and 150 




map()

long map  ( long  x,  
  long  in_min,  
  long  in_max,  
  long  out_min,  
  long  out_max   
 )    

等比映射

將位于[in_min, in_max]之間的x映射到[out_min, out_max].


參數:

  • x 要映射的值
  • in_min 映射前區(qū)間
  • in_max 映射前區(qū)間
  • out_min 映射后區(qū)間
  • out_max 映射后區(qū)間

例如下面的代碼中用 map 將模擬量從[0,1023]映射到[0,255]區(qū)間:

// Map an analog value to 8 bits (0 to 255)
void setup() {}

void loop()
{
  int val = analogRead(0);
  val = map(val, 0, 1023, 0, 255);
  analogWrite(9, val);
}

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}




pow()

double 	pow (float base, float exponent)
指數函數 <br>




sqrt()

double 	sqrt (double x)
//開平方 




三角函數

sin(),cos(),tan()

float sin (float rad)
//正弦函數 
float cos (float rad)
//余弦函數 
float tan (float rad)
//正切函數 




隨機數

randomSeed()

void randomSeed  ( unsigned int  seed   )   

設置隨機種子

可以用當前時間作為隨機種子. 隨機種子的設置對產生的隨機序列有影響.

參數:

  • seed 隨機種子




random()

long random (long howbig)   

生成隨機數

生成[0, howbig-1]范圍的隨機數.

參數:

  • howbig 最大值



long random (long howsmall, long howbig)    

生成隨機數

生成[howsmall, howbig-1]范圍的隨機數.

參數:

  • howsmall 最小值
  • howbig 最大值





位操作

位操作

#define  lowByte(w)   ((w) & 0xff) 
  //取低字節(jié) 

#define  highByte(w)   ((w) >> 8) 
  //取高字節(jié) 

#define  bitRead(value, bit)   (((value) >> (bit)) & 0x01) 
  //讀一個bit 

#define  bitWrite(value, bit, bitvalue)   (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) 
  //寫一個bit 

#define  bitSet(value, bit)   ((value) |= (1UL << (bit))) 
  //設置一個bit 

#define  bitClear(value, bit)   ((value) &= ~(1UL << (bit))) 
  //清空一個bit 

#define  bit(b)   (1 << (b)) 
  //生成相應bit  




設置中斷函數

attachInterrupt()

void attachInterrupt (uint8_t interruptNum, void(*)(void)userFunc, int mode)

設置中斷

指定中斷函數. 外部中斷有0和1兩種, 一般對應2號和3號數字引腳.


參數:

  • interrupt 中斷類型, 0或1
  • fun 對應函數
  • mode 觸發(fā)方式. 有以下幾種:
    • LOW 低電平觸發(fā)中斷
    • CHANGE 變化時觸發(fā)中斷
    • RISING 低電平變?yōu)楦唠娖接|發(fā)中斷
    • FALLING 高電平變?yōu)榈碗娖接|發(fā)中斷


注解:
在中斷函數中 delay 函數不能使用, millis 始終返回進入中斷前的值. 讀串口數據的話, 可能會丟失. 中斷函數中使用的變量需要定義為 volatile 類型.
下面的例子如果通過外部引腳觸發(fā)中斷函數, 然后控制LED的閃爍.

int pin = 13;
volatile int state = LOW;

void setup()
{
  pinMode(pin, OUTPUT);
  attachInterrupt(0, blink, CHANGE);
}

void loop()
{
  digitalWrite(pin, state);
}

void blink()
{
  state = !state;
}




detachInterrupt()

void detachInterrupt (uint8_t interruptNum)	

取消中斷

取消指定類型的中斷.

參數:

  • interrupt 中斷的類型.




interrupts()

#define interrupts() sei()

開中斷

例子:


void setup() {}

void loop()
{
  noInterrupts();
  // critical, time-sensitive code here
  interrupts();
  // other code here
}

noInterrupts()

#define noInterrupts() cli()

關中斷

例子:

void setup() {}

void loop()
{
  noInterrupts();
  // critical, time-sensitive code here
  interrupts();
  // other code here
}




串口通訊

(該小節(jié)為最新翻譯)

void begin (long) 打開串口

uint8_t available (void) 有串口數據返回真

int read (void) //讀串口

void flush (void) //刷新串口數據

virtual void write (uint8_t) //寫串口 </pre>




begin()

void HardwareSerial::begin  (long speed)   

打開串口

參數:

  • speed 波特率




available()

獲取串口上可讀取的數據的字節(jié)數。該數據是指已經到達并存儲在接收緩存(共有64字節(jié))中。available()繼承自Stream實用類。
語法:

Serial.available()

Arduino Mega only: Serial1.available() Serial2.available() Serial3.available()

參數:

返回值:

  • 返回可讀取的字節(jié)數

示例:

int incomingByte = 0;   // for incoming serial data

void setup() {
        Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
}

void loop() {

        // send data only when you receive data:
        if (Serial.available() > 0) {
                // read the incoming byte:
                incomingByte = Serial.read();

                // say what you got:
                Serial.print("I received: ");
                Serial.println(incomingByte, DEC);
        }
}

Arduino Mega example:

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);

}

void loop() {
  // read from port 0, send to port 1:
  if (Serial.available()) {
    int inByte = Serial.read();
    Serial1.print(inByte, BYTE);

  }
  // read from port 1, send to port 0:
  if (Serial1.available()) {
    int inByte = Serial1.read();
    Serial.print(inByte, BYTE);
  }
}





read()

讀串口數據,read()繼承自Stream實用類。 語法:

Serial.read()

Arduino Mega only: Serial1.read() Serial2.read() Serial3.read()

參數:

返回值:
串口上第一個可讀取的字節(jié)(如果沒有可讀取的數據則返回-1)- int型。

示例:

int incomingByte = 0;   // 用于存儲從串口讀到的數據

void setup() {
        Serial.begin(9600);     // 打開串呂,設置速率為9600 bps
}

void loop() {

        // 只在收到數據時發(fā)送數據
        if (Serial.available() > 0) {
                // 讀取傳入的字節(jié)
                incomingByte = Serial.read();

                // 指示你收到的數據
                Serial.print("I received: ");
                Serial.println(incomingByte, DEC);
        }
}





flush()

刷新串口數據

print()

往串口發(fā)數據,無換行 描述
以人類可讀的ASCII碼形式向串口發(fā)送數據,該函數有多種格式。整數的每一數位將以ASCII碼形式發(fā)送。浮點數同樣以ASCII碼形式發(fā)送,默認保留小數點后兩位。字節(jié)型數據將以單個字符形式發(fā)送。字符和字符串會以其相應的形式發(fā)送。例如:


    Serial.print(78) 發(fā)送 "78"
    Serial.print(1.23456) 發(fā)送 "1.23"
    Serial.print('N') 發(fā)送 "N"
    Serial.print("Hello world.") 發(fā)送 "Hello world." 

可選的第二個參數用于指定數據的格式。允許的值為:BIN (binary二進制), OCT (octal八進制), DEC (decimal十進制), HEX (hexadecimal十六進制)。對于浮點數,該參數指定小數點的位數。例如:

    Serial.print(78, BIN) gives "1001110"
    Serial.print(78, OCT) gives "116"
    Serial.print(78, DEC) gives "78"
    Serial.print(78, HEX) gives "4E"
    Serial.println(1.23456, 0) gives "1"
    Serial.println(1.23456, 2) gives "1.23"
    Serial.println(1.23456, 4) gives "1.2346" 

你可以用F()把待發(fā)送的字符串包裝到flash存儲器。例如:

    Serial.print(F(“Hello World”)) 

要發(fā)送單個字節(jié)數據,請使用Serial.write()。

語法:

Serial.print(val)
Serial.print(val, format)

參數:

  • val: 要發(fā)送的數據(任何數據類型)
  • format: 指定數字的基數(用于整型數)或者小數的位數(用于浮點數)。

返回值:<>

  • size_t (long): print()返回發(fā)送的字節(jié)數(可丟棄該返回值)。

示例:

/*
Uses a FOR loop for data and prints a number in various formats.
*/
int x = 0;    // variable

void setup() {
  Serial.begin(9600);      // open the serial port at 9600 bps:    
}

void loop() {  
  // print labels
  Serial.print("NO FORMAT");       // prints a label
  Serial.print("\t");              // prints a tab

  Serial.print("DEC");  
  Serial.print("\t");      

  Serial.print("HEX");
  Serial.print("\t");  

  Serial.print("OCT");
  Serial.print("\t");

  Serial.print("BIN");
  Serial.print("\t");

  for(x=0; x< 64; x++){    // only part of the ASCII chart, change to suit

    // print it out in many formats:
    Serial.print(x);       // print as an ASCII-encoded decimal - same as "DEC"
    Serial.print("\t");    // prints a tab

    Serial.print(x, DEC);  // print as an ASCII-encoded decimal
    Serial.print("\t");    // prints a tab

    Serial.print(x, HEX);  // print as an ASCII-encoded hexadecimal
    Serial.print("\t");    // prints a tab

    Serial.print(x, OCT);  // print as an ASCII-encoded octal
    Serial.print("\t");    // prints a tab

    Serial.println(x, BIN);  // print as an ASCII-encoded binary
    //                             then adds the carriage return with "println"
    delay(200);            // delay 200 milliseconds
  }
  Serial.println("");      // prints another carriage return
}

編程技巧:
在版本1.0時,串口傳輸是異步的,Serial.print()會在數據發(fā)送完成前返回。




println()

往串口發(fā)數據,類似Serial.print(),但有換行

write()

寫二進制數據到串口,數據是一個字節(jié)一個字節(jié)地發(fā)送的,若以字符形式發(fā)送數字請使用print()代替。
語法:

Serial.write(val)
Serial.write(str)
Serial.write(buf, len) 

Arduino Mega也支持:Serial1, Serial2, Serial3(在Serial的位置)

參數:

  • val: 作為單個字節(jié)發(fā)送的數據
  • str: 由一系列字節(jié)組成的字符串
  • buf: 同一系列字節(jié)組成的數組
  • len: 要發(fā)送的數組的長度

返回:

  • byte

write()會返回發(fā)送的字節(jié)數,所以讀取該返回值是可選的。

示例:

void setup(){
  Serial.begin(9600);
}

void loop(){
  Serial.write(45); //以二進制形式發(fā)送數字45

   int bytesSent = Serial.write(“hello”); //發(fā)送字符串“hello” 并返回該字符串的長度。
}





peak()

描述:
返回收到的串口數據的下一個字節(jié)(字符),但是并不把該數據從串口數據緩存中清除。就是說,每次成功調用peak()將返回相同的字符。與read()一樣,peak()繼承自Stream實用類。 語法:
可參照Serail.read()





serialEvent()

描述:
當串口有數據到達時調用該函數(然后使用Serial.read()捕獲該數據)。
注意:目前serialEvent()并不兼容于Esplora, Leonardo, 或 Micro。

語法:


void serialEvent(){
//statements
}

Arduino Mega only:
void serialEvent1(){
//statements
}

void serialEvent2(){
//statements
}

void serialEvent3(){
//statements
}

statements可以是任何有效的語句。