Arduino 的程序可以划分為三個主要部分:結構、變量(變量與常量)、函數。
結構部分
一、結構
1.1 setup()
1.2 loop()
二、結構控制
2.1 if
2.2 if...else
2.3 for
2.4 switch case
2.5 while
2.6 do... while
2.7 break
2.8 continue
2.9 return
2.10 goto
三、擴展語法
3.1 ;(分號)
3.2 {}(花括號)
3.3 //(單行注釋)
3.4 /* */(多行注釋)
3.5 #define
3.6 #include
四、算數運算符
4.1 =(賦值運算符)
4.2 +(加)
4.3 -(減)
4.4 *(乘)
4.5 /(除)
4.6 %(模)
五、比較運算符
5.1 ==(等於)
5.2 !=(不等於)
5.3 <(小於)
5.4 >(大於)
5.5 <=(小於等於)
5.6 >=(大於等於)
六、布爾運算符
6.1 &&(與)
6.2 ||(或)
6.3 !(非)
七、指針運算符
7.1 * 取消引用運算符
7.2 & 引用運算符
八、位運算符
8.1 & (bitwise and)
8.2 | (bitwise or)
8.3 ^ (bitwise xor)
8.4 ~ (bitwise not)
8.5 << (bitshift left)
8.6 >> (bitshift right)
九、復合運算符
9.1 ++ (increment)
9.2 -- (decrement)
9.3 += (compound addition)
9.4 -= (compound subtraction)
9.5 *= (compound multiplication)
9.6 /= (compound division)
9.6 &= (compound bitwise and)
9.8 |= (compound bitwise or)
變量部分
十、常量
10.1 HIGH|LOW(引腳電壓定義)
10.2 INPUT|OUTPUT(數字引腳(Digital pins)定義)
10.3 true | false(邏輯層定義)
10.4 integer constants(整數常量)
10.5 floating point constants(浮點常量)
十一、數據類型
11.1 void
11.2 boolean(布爾)
11.3 char(有號數據類型)
11.4 unsigned char(無符號數據類型)
11.5 byte(無符號數)
11.6 int(整型)
11.7 unsigned int(無符號整型)
11.8 word
11.9 long(長整數型)
11.10 unsigned long(無符號長整數型)
11.11 float(浮點型數)
11.12 double(雙精度浮點數)
11.13 string(char array/字符串)
11.14 String object(String類)
11.15 array (數組)
十二、數據類型轉換
12.1 char()
12.2 byte()
12.3 int()
12.4 word()
12.5 long()
12.6 float()
十三、變量作用域 & 修飾符
13.1 variable scope(變量的作用域)
13.2 static(靜態變量)
13.3 volatile
13.4 const
十四、輔助工具
14.1 sizeof()
函數部分
十五、數字 I/O
15.1 pinMode()
15.2 digitalWrite()
15.3 digitalRead()
十六、模擬 I/O
16.1 analogReference()
16.2 analogRead()
16.3 analogWrite() PWM
十七、高級 I/O
17.1 tone()
17.2 noTone()
17.3 shiftOut()
17.4 shiftIn()
17.5 pulseIn()
十八、時間
18.1 millis()
18.2 micros()
18.3 delay()
18.4 delayMicroseconds()
十九、數學運算
19.1 min()
19.2 max()
19.3 abs()
19.4 constrain()
19.5 map()
19.6 pow()
19.7 sqrt()
19.8 ceil()
19.9 exp()
19.10 fabs()
19.11 floor()
19.12 fma()
19.13 fmax()
19.14 fmin()
19.15 fmod()
19.16 ldexp()
19.17 log()
19.18 log10()
19.19 round()
19.20 signbit()
19.21 sq()
19.22 square()
19.23 trunc()
二十、三角函數
20.1 sin()
20.2 cos()
20.3 tan()
20.4 acos()
20.5 asin()
20.6 atan()
20.7 atan2()
20.8 cosh()
20.9 degrees()
20.10 hypot()
20.11 radians()
20.12 sinh()
20.13 tanh()
二十一、隨機數
21.1 randomSeed()
21.2 random()
二十二、位操作
22.1 lowByte()
22.2 highByte()
22.3 bitRead()
22.4 bitWrite()
22.5 bitSet()
22.6 bitClear()
22.7 bit()
二十三、設置中斷函數
23.1 attachInterrupt()
23.2 detachInterrupt()
二十四、開關中斷
24.1 interrupts()(中斷)
24.2 noInterrupts()(禁止中斷)
二十五、通訊
25.1 Serial
25.1.1 if (Serial)
25.1.2 Serial.available()
25.1.3 Serial.begin()
25.1.4 Serial.end()
25.1.5 Serial.find()
25.1.6 Serial.findUntil()
25.1.7 Serial.flush()
25.1.8 Serial.parseFloat()
25.1.9 Serial.parseInt()
25.1.10 Serial.peek()
25.1.11 Serial.print()
25.1.12 Serial.println()
25.1.13 Serial.read()
25.1.14 Serial.readBytes()
25.1.15 Serial.readBytesUntil()
25.1.16 Serial.setTimeout()
25.1.17 Serial.write()
25.1.18 Serial.SerialEvent()
25.2 Stream
二十六、USB(僅適用於 Leonardo 和 Due)
26.1 Mouse(鍵盤)
26.2 Keyboard(鼠標)
以下是示例部分含詳細注解
結構部分
一、結構
1.1 setup()
在Arduino中程序運行時將首先調用 setup() 函數。用於初始化變量、設置針腳的輸出\輸入類型、配置串口、引入類庫文件等等。每次 Arduino 上電或重啟后,setup 函數只運行一次。
示例
int buttonPin = 3;//定義一個變量buttonPin為針腳3
void setup()
{
Serial.begin(9600);//定義初始串口波特率為9600
pinMode(buttonPin, INPUT);//定義buttonPin也就是前面定義的針腳3為input輸入針腳
}
void loop()
{
// ...
}
1.2 loop()
在 setup() 函數中初始化和定義了變量,然后執行 loop() 函數。顧名思義,該函數在程序運行過程中不斷的循環,根據一些反饋,相應改變執行情況。通過該函數動態控制 Arduino 主控板。
示例
int buttonPin = 3; // setup 中初始化串口和按鍵針腳.
void setup()
{
beginSerial(9600);
pinMode(buttonPin, INPUT);
}
// loop 中每次都檢查按鈕,如果按鈕被按下,就發送信息到串口
void loop()
{
if (digitalRead(buttonPin) == HIGH)//通過eigitalRead讀取到針腳3的電平值是否為高
serialWrite('H');//是高就通過串口寫出H
else
serialWrite('L');//如果不是就通過串口寫出L
delay(1000);//延時1000毫秒,也就是1秒
}
二、結構控制
2.1 if
if(條件判斷語句)和 ==、!=、<、>(比較運算符)
if 語句與比較運算符一起用於檢測某個條件是否達成,如某輸入值是否在特定值之上等。if 語句的語法是:
if (someVariable > 50)
{
// 執行某些語句
}
本程序測試 someVariable 變量的值是否大於 50。當大於 50 時,執行一些語句。換句話說,只要 if 后面括號里的結果(稱之為測試表達式)為真,則執行大括號中的語句(稱之為執行語句塊);若為假,則跳過大括號中的語句。 if 語句后的大括號可以省略。若省略大括號,則只有一條語句(以分號結尾)成為執行語句。
下面幾種寫法都是正確的:
第一種:
if (x > 120) digitalWrite(LEDpin, HIGH);//判斷x的值是不是大於120,是的話就讓LEDpin這個針腳的電平成為高電平
第二種:
if (x > 120)
digitalWrite(LEDpin, HIGH);
第三種:
if (x > 120){ digitalWrite(LEDpin, HIGH); }
第四種:
if (x > 120){
digitalWrite(LEDpin1, HIGH);
digitalWrite(LEDpin2, HIGH);
}
在小括號里求值的表達式,需要以下操作符:
比較運算操作符:
x == y(x 等於 y)注意這是等於,並不是賦值,賦值是=
x != y(x 不等於 y)
x < y(x 小於 y)
x > y(x 大於 y)
x <= y(x 小於等於 y)
x >= y(x 大於等於 y)
警告:
注意使用賦值運算符的情況(如 if (x = 10))。一個“=”表示的是賦值運算符,作用是將 x 的值設為 10(將值 10 放入 x 變量的內存中)。兩個“=”表示的是比較運算符(如 if (x == 10)),用於測試 x 和 10 是否相等。后面這個語句只有 x 是 10 時才為真,而前面賦值的那個語句則永遠為真。
這是因為 C 語言按以下規則進行運算 if (x=10):10 賦值給 x(只要非 0 的數賦值的語句,其賦值表達式的值永遠為真),因此 x 現在值為 10。此時 if 的測試表達式值為 10,該值永遠為真,因為非 0 值永遠為真。所以,if (x = 10) 將永遠為真,這就不是我們運行 if 所期待的結果。另外,x 被賦值為 10,這也不是我們所期待的結果。
if 的另外一種分支條件控制結構是 if...else 形式。
2.2 if...else
if/else是比if更為高級的流程控制語句,它可以進行多次條件測試。比如,檢測模擬輸入的值,當它小於500時該執行哪些操作,大於或等於500時執行另外的操作。代碼如下:
if (pinFiveInput < 500)
{
// 執行A操作
}
else
{
// 執行B操作
}
else可以進行額外的if檢測,所以多個互斥的條件可以同時進行檢測。
測試將一個一個進行下去,直到某個測試結果為真,此時該測試相關的執行語句塊將被運行,然后程序就跳過剩下的檢測,直接執行到if/else的下一條語句。當所有檢測都為假時,若存在else語句塊,將執行默認的else語句塊。
注意else if語句塊可以沒有else語句塊。else if分支語句的數量無限制。
if (pinFiveInput < 500)
{
// 執行A操作
}
else if (pinFiveInput >= 1000)
{
// 執行B操作
}
else
{
// 執行C操作
}
另外一種進行多種條件分支判斷的語句是switch case語句。
2.3 for
for語句
描述
for語句用於重復執行一段在花括號之內的代碼。通常使用一個增量計數器計數並終止循環。for語句用於重復性的操作非常有效,通常與數組結合起來使用來操作數據、引腳。
for循環開頭有3個部分:
(初始化;條件;增量計數){
//語句
}
“初始化”只在循環開始執行一次。每次循環,都會檢測一次條件;如果條件為真,則執行語句和“增量計數”,之后再檢測條件。當條件為假時,循環終止。
例子
//用PWM引腳將LED變暗
int PWMpin = 10; //將一個LED與47Ω電阻串聯接在10號針腳
void setup()
{
//無需設置
}
void loop()
{
for (int i=0; i <= 255; i++)//定義一個變量i,並賦值為0,當i小於等於255的時候i就加1,也可寫成i+=5,這樣每循環一次i就加5
{
analogWrite(PWMpin, i);//讓10號針腳的電平改變為i
delay(10);//延時10毫秒
}
}
編程提示
C語言的for循環語句比BASIC和其他電腦編程語言的for語句更靈活。除了分號以外,其他3個元素都能省略。同時,初始化,條件,增量計算可以是任何包括無關變量的有效C語句,任何C數據類型包括float。這些不尋常的for語句可能會解決一些困難的編程問題。
例如,在增量計數中使用乘法可以得到一個等比數列:
for(int x = 2; x < 100; x = x * 1.5){//定義X為2,當X小於100的時候X重新賦值為它自己的1.5倍
println(x);//打印輸出x的值
}
生成:2,3,4,6,9,13,19,28,42,63,94
另一個例子,使用for循環使LED產生漸亮漸滅的效果:
int PWMpin = 10; //將一個LED與47Ω電阻串聯接在10號針腳
void setup()
{
//無需設置
}
void loop()
{
int x = 1; //定義一個整數變量x賦值為1
for (int i = 0; i > -1; i = i + x) //定義i為0當i小於負一的時候,i的值為它自己加上X,也就是加上1,燈就依次變亮了
{
analogWrite(PWMpin, i); //讓PWMpin針腳的電平變為i
if (i == 255) x = -1; // 當i等於最大值255的時候,把x改變為負一,這樣再循環上去的時候i的值就會依次減一,就由亮變暗了
delay(10); //延時10毫秒,如果還想讓燈由暗變亮的話就再寫個判斷
if(i==0) x=1; //當i減小到0的時候又把x變成1,這樣i就又依次加1,燈由暗變亮了
delay(10);
}
}
2.4 switch case
switch / case語句
和if語句相同,switch…case通過程序員設定的在不同條件下執行的代碼控制程序的流程。特別地,switch語句將變量值和case語句中設定的值進行比較。當一個case語句中的設定值與變量值相同時,這條case語句將被執行。
關鍵字break可用於退出switch語句,通常每條case語句都以break結尾。如果沒有break語句,switch語句將會一直執行接下來的語句(一直向下)直到遇見一個break,或者直到switch語句結尾。
語法也是先switch然后跟括號()括號內寫上變量值,后面跟大括號,大括號里寫上case分支
例子
switch (var) {
case 1: //case 1后面是冒號
//當var等於1時,執行一些語句
break;
case 2
//當var等於2時,執行一些語句
break;
default:
//如果沒有任何匹配,執行default
//default可有可不有
}
語法
switch (var) { //定義檢查var的值
case label1: //如果var的值是label1的就就執行下面的語句
// 程序語句
break;
case label2: //如果var的值是label2的就就執行下面的語句
//程序語句
break;
default: //如果var的值都不在上面的里面的話就執行下面的語句
//程序語句
}
參數
var: 用於與下面的case中的標簽進行比較的變量值
label: 與變量進行比較的值
2.5 while
while循環
描述
while循環會無限的循環,直到括號內的判斷語句變為假。必須要有能改變判斷語句的東西,要不然while循環將永遠不會結束。這在您的代碼表現為一個遞增的變量,或一個外部條件,如傳感器的返回值。
語法
while(表達){
//語句
}
參數
表達:為真或為假的一個計算結果
例子
var = 0; //定義一個變量var賦值為0
while(var < 200){ //當var的值小於200的時候執行下面的語句
var++ //var依次加1,加200次,直到var的值不小於200為止
}
2.6 do...while
do…while循環與while循環運行的方式是相近的,不過它的條件判斷是在每個循環的最后,所以這個語句至少會被運行一次,然后才被結束。
do
{
//語句
}while(測試條件);
例子
do
{
delay(50); //延時50秒
X = readSensors(); //給X賦值
}while(X <100); //當x小於100時,繼續運行,當x不小於100的時候就不運行了
2.7 break
break用於退出do,for,while循環,能繞過一般的判斷條件。它也能夠用於退出switch語句。
例子
for (x = 0; x < 255; x ++)
{
digitalWrite(PWMpin, x);
sens = analogRead(sensorPin);
if (sens > threshold){
x = 0;
break; //這里用break就打斷循環了,相當於在此結束了,程序就不再循環了
}
delay(50);
}
2.8 continue
continue語句跳過當前循環中剩余的迭代部分( do,for 或 while )。它通過檢查循環條件表達式,並繼續進行任何后續迭代。
例子
for (x = 0; x < 255; x ++)
{
if (x > 40 && x < 120){
continue; // 當x在40與120之間時,跳過后面兩句,即迭代。
}
digitalWrite(PWMpin, x);
delay(50);
}
2.9 return
終止一個函數,如有返回值,將從此函數返回給調用函數。
語法
return;
return value; // 兩種形式均可
參數
value:任何變量或常量的類型
例子
一個比較傳感器輸入閾值的函數
int checkSensor(){ //這兒定義了一個整數形函數checkSensor
if (analogRead(0) > 400) { //如果讀取0針腳的數據大於400的話
return 1;} //返回1,相當於調用這個函數后得到的值是1
else{
return 0; //返回0,相當於調用這個函數后得到的值是0
}
}
return關鍵字可以很方便的測試一段代碼,而無需“comment out(注釋掉)” 大段的可能存在bug的代碼。
void loop(){
//寫入漂亮的代碼來測試這里。
return;
//剩下的功能異常的程序
//return后的代碼永遠不會被執行
}
2.10 goto
程序將會從程序中已有的標記點開始運行,這個東西,少用
語法
label:
goto label; //從label處開始運行
提示
不要在C語言中使用goto編程,某些C編程作者認為goto語句永遠是不必要的,但用得好,它可以簡化某些特定的程序。許多程序員不同意使用goto的原因是, 通過毫無節制地使用goto語句,很容易創建一個程序,這種程序擁有不確定的運行流程,因而無法進行調試。感覺就像你明明在1上一下就跳到了8上,並 不是從上而下的過程。
的確在有的實例中goto語句可以派上用場,並簡化代碼。例如在一定的條件用if語句來跳出高度嵌入的for循環。
例子
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; //這兒有一個goto語句所以程序會跳轉到下一個bailout
}
//更多的語句...
}
}
}
bailout: //goto語句跳轉到這兒繼續執行
三、擴展語法
3.1 ;(分號)
用於表示一句代碼的結束。
例子
int a = 13;
提示
在每一行忘記使用分號作為結尾,將導致一個編譯錯誤。錯誤提示可能會清晰的指向缺少分號的那行,也可能不會。如果彈出一個令人費解或看似不合邏輯的編譯器錯誤,第一件事就是在錯誤附近檢查是否缺少分號。
3.2 {}(花括號也稱大括號)
大括號(也稱為“括號”或“大括號”)是C編程語言中的一個重要組成部分。它們被用來區分幾個不同的結構,下面列出的,有時可能使初學者混亂。
左大括號“{”必須與一個右大括號“}”形成閉合。這是一個常常被稱為括號平衡的條件。在Arduino IDE(集成開發環境)中有一個方便的功能來檢查大括號是否平衡。只需選擇一個括號,甚至單擊緊接括號的插入點,就能知道這個括號的“伴侶括號”。
目前此功能稍微有些錯誤,因為IDE會經常會認為在注釋中的括號是不正確的。
對於初學者,以及由BASIC語言轉向學習C語言的程序員,經常不清楚如何使用括號。畢竟,大括號還會在”return函數”、“endif條件句”以及“loop函數”中被使用到。
由於大括號被用在不同的地方,這有一種很好的編程習慣以避免錯誤:輸入一個大括號后,同時也輸入另一個大括號以達到平衡。然后在你的括號之間輸入回車,然后再插入語句。這樣一來,你的括號就不會變得不平衡了。
不平衡的括號常可導致許多錯誤,比如令人費解的編譯器錯誤,有時很難在一個程序找到這個錯誤。由於其不同的用法,括號也是一個程序中非常重要的語法,如果括號發生錯誤,往往會極大地影響了程序的意義。
大括號中的主要用途
功能 函數
void myfunction(datatype argument){
statements(s)
}
循環
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)
}
3.3 //(單行注釋)
Comments(注釋)
注釋用於提醒自己或他人程序是如何工作的。它們會被編譯器忽略掉,也不會傳送給處理器,不會執行,所以它們在Atmega芯片上不占用體積。 注釋的唯一作用就是使你自己理解或幫你回憶你的程序是怎么工作的或提醒他人你的程序是如何工作的。編寫注釋有兩種寫法:
例子
x = 5; // 這是一條注釋斜杠后面本行內的所有東西是注釋
/* 這是多行注釋-用於注釋一段代碼
if (gwb == 0){ // 在多行注釋內可使用單行注釋
x = 3; /* 但不允許使用新的多行注釋-這是無效的
}
// 別忘了注釋的結尾符號-它們是成對出現的!
*/
小提示
當測試代碼的時候,注釋掉一段可能有問題的代碼是非常有效的方法。這能使這段代碼成為注釋而保留在程序中,而編譯器能忽略它們。這個方法用於尋找問題代碼或當編譯器提示出錯或錯誤很隱蔽時很有效。
3.4 /* */(多行注釋)
Comments(注釋)
上面已經講過了跟單行同類型
例子
x = 5; // 這是一條注釋斜杠后面本行內的所有東西是注釋
/* 這是多行注釋-用於注釋一段代碼
if (gwb == 0){ // 在多行注釋內可使用單行注釋
x = 3; /* 但不允許使用新的多行注釋-這是無效的
}
// 別忘了注釋的結尾符號-它們是成對出現的!
*/
小提示
當測試代碼的時候,注釋掉一段可能有問題的代碼是非常有效的方法。這能使這段代碼成為注釋而保留在程序中,而編譯器能忽略它們。這個方法用於尋找問題代碼或當編譯器提示出錯或錯誤很隱蔽時很有效。
3.5 #define
#define 是一個很有用的C語法,它允許程序員在程序編譯之前給常量命名。在Arduino中,定義的常量不會占用芯片上的任何程序內存空間。在編譯時編譯器會用事先定義的值來取代這些常量。
然而這樣做會產生一些副作用,例如,一個已被定義的常量名已經包含在了其他常量名或者變量名中。在這種情況下,文本將被#defined 定義的數字或文本所取代。
通常情況下,優先考慮使用 const 關鍵字替代 #define 來定義常量。
Arduino 擁有和 C 相同的語法規范。
語法
#define 常量名 常量值 注意,#是必須的。
例子
#define ledPin 3
//在編譯時,編譯器將使用數值 3 取代任何用到 ledPin 的地方。
提示
在#define 聲明后不能有分號。如果存在分號,編譯器會拋出語義不明的錯誤,甚至關閉頁面。
#define ledPin 3; //這是一種錯誤寫法
類似的,在#define聲明中包含等號也會產生語義不明的編譯錯誤從而導致關閉頁面。
#define ledPin = 3 //這是一種錯誤寫法
不能包含等號只能用空格
3.6 #include
#include用於調用程序以外的庫。這使得程序能夠訪問大量標准C庫,也能訪問用於arduino的庫。 AVR C庫(Arduino基於AVR標准語法)語法手冊請點擊這里。 注意#include和#define一樣,不能在結尾加分號,如果你加了分號編譯器將會報錯。
例子
此例包含了一個庫,用於將數據存放在flash空間內而不是ram內。這為動態內存節約了空間,大型表格查表更容易實現。
#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};
四、算數運算符
4.1 =(賦值運算符)
= 賦值運算符(單等號) 注意:這個是賦值的=號並不是相比較的==號
賦值運算符(單等號)
將等號右邊的數值賦值給等號左邊的變量
在C語言中,單等號被稱為賦值運算符,它與數學上的等號含義不同,賦值運算符告訴單片機,將等號的右邊的數值或計算表達式的結果,存儲在等號左邊的變量中。
例子
int sensVal; //聲明一個名為sensVal的整型變量
senVal = analogRead(0); //將模擬引腳0的輸入電壓存儲在SensVal變量中
編程技巧
要確保賦值運算符(=符號)左側的變量能夠儲存右邊的數值。如果沒有大到足以容納右邊的值,存儲在變量中的值將會發生錯誤。
比如你要把一個浮點型小數賦值給一個整數就不對
不要混淆賦值運算符[=](單等號)與比較運算符[==](雙等號),認為這兩個表達式是相等的。
4.2 +(加)
加,減,乘,除
描述
這些運算符返回兩個操作數的和,差,乘積,商。這些運算是根據操作數的數據類型來計算的,比如 9和4都是int類型,所以9 / 4 結果是 2.這也就代表如果運算結果比數據類型所能容納的范圍要大的話,就會出現溢出(例如. 1加上一個整數 int類型 32,767 結果變成-32,768)。如果操作數是不同類型的,結果是”更大”的那種數據類型。如果操作數中的其中一個是 float類型或者double類型, 就變成了浮點數運算。
例子
y = y + 3; //這里的Y得是整數型 int 類型才行,如果y是2輸出結果為5
y=y+"你好啊"; //這里的y得是字符串類型 str 才行,如果y是“逗B”,輸出結果就是“逗B你好啊”
//加可以用來做字符串相加,減的話必須是主內容包含被減掉的內容才可以。
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 會得到一個負數結果.那么if(60*1000 > 0) ,if得到的是一個false值。
在選擇變量的數據類型時,一定要保證變量類型的范圍要足夠大,以至於能容納下你的運算結果。
要知道你的變量在哪個點會”翻身”,兩個方向上都得注意.如: (0 - 1) 或 (0 - - 32768)
一些數學上的分數處理,要用浮點數,但其缺點是:占用字節長度大,運算速度慢。
使用類型轉換符,例如 (int)myFloat 將一個變量強制轉換為int類型。
4.3 -(減)
詳見4.2 +(加)
4.4 *(乘)
詳見4.2 +(加)
4.5 /(除)
詳見4.2 +(加)
4.6 %(取模)
描述
一個整數除以另一個數,其余數稱為模。它有助於保持一個變量在一個特定的范圍(例如數組的大小)。
語法
結果=被除數%除數
參數
被除數:一個被除的數字
除數:一個數字用於除以其他數
返回
余數(模)
舉例
X = 7%5; // X為2,商為1余2
X = 9% 5;// X為4商為1余4
X = 5% 5;// X為0商為1余0
X = 4%5; // X為4除不動就為它本身4了
示例代碼
/*通過循環計算1到10的模*/
int values[10];
int i = 0;
void setup () {
}
void loop()
{
values [i] = analogRead(0); //所以讀取的值就是10以內的除以10之后的余數
i =(i + 1)%10; //取模運算
}
提示
模運算符對浮點數不起作用。
五、比較運算符
5.1 ==(等於)比較是否等於
if(條件判斷語句)和 ==、!=、<、>(比較運算符)
復習一下if語句
if 語句與比較運算符一起用於檢測某個條件是否達成,如某輸入值是否在特定值之上等。if 語句的語法是:
if (someVariable > 50)
{
// 執行某些語句
}
本程序測試 someVariable 變量的值是否大於 50。當大於 50 時,執行一些語句。換句話說,只要 if 后面括號里的結果(稱之為測試表達式)為真,則執行大括號中的語句(稱之為執行語句塊);若為假,則跳過大括號中的語句。 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);
} // 以上所有書寫方式都正確
在小括號里求值的表達式,需要以下操作符:
比較運算操作符:
x == y(x 等於 y)
x != y(x 不等於 y)
x < y(x 小於 y)
x > y(x 大於 y)
x <= y(x 小於等於 y)
x >= y(x 大於等於 y)
警告
注意使用賦值運算符的情況(如 if (x = 10))。一個“=”表示的是賦值運算符,作用是將 x 的值設為 10(將值 10 放入 x 變量的內存中)。兩個“=”表示的是比較運算符(如 if (x == 10)),用於測試 x 和 10 是否相等。后面這個語句只有 x 是 10 時才為真,而前面賦值的那個語句則永遠為真。
這是因為 C 語言按以下規則進行運算 if (x=10):10 賦值給 x(只要非 0 的數賦值的語句,其賦值表達式的值永遠為真),因此 x 現在值為 10。此時 if 的測試表達式值為 10,該值永遠為真,因為非 0 值永遠為真。所以,if (x = 10) 將永遠為真,這就不是我們運行 if 所期待的結果。另外,x 被賦值為 10,這也不是我們所期待的結果。
if 的另外一種分支條件控制結構是 if...else 形式。
5.2 !=(不等於)
詳見5.1 ==(等於)
5.3 <(小於)
詳見5.1 ==(等於)
5.4 >(大於)
詳見5.1 ==(等於)
5.5 <=(小於等於)
詳見5.1 ==(等於)
5.6 >=(大於等於)
詳見5.1 ==(等於)
六、布爾運算符
6.1 &&(與)
布爾運算符
這些運算符可以用於if條件句中。不會打&沒關系英文輸入狀態按SHIFT+7
&&(邏輯與)就是同時的意思,小明買了一支筆&&買了一本書
只有兩個運算對象為“真”,才為“真”,如:
if (digitalRead(2) == HIGH && digitalRead(3) == HIGH) { // 讀取2號針腳和3號針腳的電平
}
如果當兩個輸入都為高電平,則為“真”。
||(邏輯或)
只要一個運算對象為“真”,就為“真”,如:
if (x > 0 || y > 0) {
//其中x大於0或是y大於0都可執行程序
}
如果x或y是大於0,則為“真”。
!(邏輯非)
如果運算對象為“假”,則為“真”,例如
if (!x) {
// ...
}
如果x為“假”,則為真(即如果x等於0)。
警告
千萬不要誤以為,符號為&(單符號)的位運算符”與”就是布爾運算符的“與”符號為&&(雙符號)。他們是完全不同的符號。
同樣,不要混淆布爾運算符||(雙豎)與位運算符“或”符號為| (單豎)。
位運算符〜(波浪號)看起來與布爾運算符not有很大的差別!(正如程序員說:“驚嘆號”或“bang”),但你還是要確定哪一個運算符是你想要的。
舉例
if (a >= 10 && a <= 20){} // 如果a的值在10至20之間,則為“真”
6.2 ||(或)
詳見6.1 &&(與)
6.3 !(非)
詳見6.1 &&(與)
七、指針運算符
7.1 * 取消引用運算符
指針運算符
& (取地址) 和 * (取地址所指的值)
指針對C語言初學者來說是一個比較復雜的內容,但是編寫大部分arduino代碼時可以不用涉及到指針。然而,操作某些數據結構時,使用指針能夠簡化代碼,但是指針的操作知識很難在工具書中找到,可以參考C語言相關工具書。
7.2 & 引用運算符
詳見7.1 *取消引用運算符
八、位運算符
8.1 & (按位與)
按位與(&)
按位操作符對變量進行位級別的計算。它們能解決很多常見的編程問題。下面的材料大多來自這個非常棒的按位運算指導。
說明和語法
下面是所有的運算符的說明和語法。進一步的詳細資料,可參考教程。
按位與(&)
位操作符與在C + +中是一個&符,用在兩個整型變量之間。按位與運算符對兩側的變量的每一位都進行運算,規則是:如果兩個運算元都是1,則結果為1,否則輸出0.另一種表達方式:
0 0 1 1 運算元1
0 1 0 1 運算元2
----------
0 0 0 1(運算元1&運算元2)-返回結果
在Arduino中,int類型為16位,所以在兩個int表達式之間使用&會進行16個並行按位與計算。代碼片段就像這樣:
int a = 92; //二進制: 0000000001011100
int b = 101; // 二進制: 0000000001100101
int c = a & b; // 結果: 0000000001000100, 或10進制的68
a和b的16位每位都進行按位與計算,計算結果存在c中,二進制結果是01000100,十進制結果是68.
按位與最常見的作用是從整型變量中選取特定的位,也就是屏蔽。見下方的例子。
按位或(|)
按位或操作符在C++中是|。和&操作符類似,|操作符對兩個變量的為一位都進行運算,只是運算規則不同。按位或規則:只要兩個位有一個為1則結果為1,否則為0。換句話說:
0 0 1 1 運算元1
0 1 0 1 運算元2
----------
0 1 1 1(運算元1 | 運算元2) - 返回的結果
這里是一個按位或運算在C + +代碼片段:
int a = 92; // 二進制: 0000000001011100
int b = 101; //二進制: 0000000001100101
int c = a | b; // 結果: 0000000001111101, 或十進制的125
示例程序
按位與和按位或運算常用於端口的讀取-修改-寫入。在微控制器中,一個端口是一個8位數字,它用於表示引腳狀態。對端口進行寫入能同時操作所有引腳。
PORTD是一個內置的常數,是指0,1,2,3,4,5,6,7數字引腳的輸出狀態。如果某一位為1,着對應管腳為HIGH。(此引腳需要先用pinMode()命令設置為輸出)因此如果我們這樣寫,PORTD=B00110001;則引腳2、3、7狀態為HIGH。這里有個小陷阱,我們可能同時更改了引腳0、1的狀態,引腳0、1是Arduino串行通信端口,因此我們可能會干擾通信。
我們的算法的程序是:
讀取PORT並用按位與清除我們想要控制的引腳
用按位或對PORTD和新的值進行運算
int i; // 計數器
int j;
void setup()
DDRD = DDRD | B11111100; //設置引腳2~7的方向,0、1腳不變(xx|00==xx)
//效果和pinMode(pin,OUTPUT)設置2~7腳為輸出一樣
serial.begin(9600);
}
void loop () {
for (i=0; i<64; i++){
PORTD = PORTD & B00000011; // 清除2~7位,0、1保持不變(xx & 11 == xx)
j = (i << 2); //將變量左移為·2~7腳,避免0、1腳
PORTD = PORTD | j; //將新狀態和原端口狀態結合以控制LED腳
Serial.println(PORTD, BIN); // 輸出掩蓋以便調試
delay(100);
}
}
按位異或(^)
C++中有一個不常見的操作符叫按位異或,也叫做XOR(通常讀作”eks-or“)。按位異或操作符用‘^'表示。此操作符和按位或(|)很相似,區別是如果兩個位都為1則結果為0:
0 0 1 1 運算元1
0 1 0 1 運算元2
----------
0 1 1 0(運算元1 ^運算元2) - 返回的結果
按位異或的另一種解釋是如果兩個位值相同則結果為0,否則為1。
下面是一個簡單的代碼示例:
int x = 12; // 二進制: 1100
int y = 10; // 二進制: 1010
int z = x ^ y; // 二進制: 0110, 或十進制 6
// Blink_Pin_5
//演示“異或”
void setup(){
DDRD = DDRD | B00100000; / /設置數字腳5設置為輸出
serial.begin(9600);
}
void loop () {
PORTD = PORTD ^ B00100000; // 反轉第5位(數字腳5),其他保持不變
delay(100);
}
8.2 | (按位或)
詳見8.1 &(按位與)
8.3 ^ (按位異或)
詳見8.1 &(按位與)
8.4 ~ (按位非)
按位取反 (~)
按位取反在C+ +語言中是波浪號~。與&(按位與)和|(按位或)不同,按位取反使用在一個操作數的右側。按位取反將操作數改變為它的“反面”:0變為1,1變成0。例如:
0 1 operand1
----------
1 0 ~ operand1
int a = 103; // 二進制: 0000000001100111
int b = ~a; // 二進制: 1111111110011000 = -104
你可能會驚訝地看到結果為像-104這樣的數字。這是因為整數型變量的最高位,即所謂的符號位。如果最高位是1,這個數字將變為負數。這個正數和負數的編碼被稱為補。想了解更多信息,請參考Wikipedia文章two's complement.
順便說一句,有趣的是,要注意對於任何整數型操作數X,〜X和-X-1是相同的。
有時,對帶有符號的整數型操作數進行位操作可以造成一些不必要的意外。
8.5 <<(左移位運算符)
bitshift left (<<), bitshift right (>>)
描述
出自Playground的 The Bitmath Tutorial 在C++語言中有兩個移位運算符:左移位運算符(«)和右移運算符(»)。這些操作符可使左運算元中的某些位移動右運算元中指定的位數。
語法
variable « number_of_bits variable » number_of_bits
參數
variable - (byte, int, long) number_of_bits integer ⇐ 32
例子
int a = 5; // 二進制數: 0000000000000101
int b = a << 3; // 二進制數: 0000000000101000, 或十進制數:40
int c = b >> 3; // 二進制數: 0000000000000101, 或者說回到開始時的5
//當你將x左移y位時(x«y),x中最左邊的y位會逐個逐個的丟失:
int a = 5; // 二進制: 0000000000000101
int b = a << 14; // 二進制: 0100000000000000 - 101中最左邊的1被丟棄
如果你確定位移不會引起數據溢出,你可以簡單的把左移運算當做對左運算元進行2的右運算元次方的操作。例如,要產生2的次方,可使用下面的方式:
1 << 0 == 1
1 << 1 == 2
1 << 2 == 4
1 << 3 == 8
...
1 << 8 == 256
1 << 9 == 512
10 << 1 == 1024
...
當你將x右移y位(x»y),如果x最高位是1,位移結果將取決於x的數據類型。如果x是int類型,最高位為符號位,確定是否x是負數或不是,正如我們上面的討論。如果x類型為int,則最高位是符號位,正如我們以前討論過,符號位表示x是正還是負。在這種情況下,由於深奧的歷史原因,符號位被復制到較低位:
X = -16; //二進制:1111111111110000
Y = X >> 3 //二進制:1111111111111110
這種結果,被稱為符號擴展,往往不是你想要的行為。你可能希望左邊被移入的數是0。右移操作對無符號整型來說會有不同結果,你可以通過數據強制轉換改變從左邊移入的數據:
X = -16; //二進制:1111111111110000
int y = (unsigned int)x >> 3; // 二進制: 0001111111111110
如果你能小心的避免符號擴展問題,你可以將右移操作當做對數據除2運算。例如:
INT = 1000;
Y = X >> 3; 8 1000 //1000整除8,使y=125
8.6 >> (右移位運算符)
詳見 8.5 <<(左移位運算符)
九、復合運算符
9.1 ++ (遞增)
++ (遞增) / -- (遞減)
描述
遞增或遞減一個變量
語法
x++; //x自增1返回x的舊值
++x; // x自增1返回x的新值
x--; // x自減1返回x的舊值
--x; //x自減1返回x的新值
參數
x: int或long(可能是unsigned)
返回
變量進行自增/自減操作后的原值或新值。
例子
x = 2;
y = ++x; // 現在x=3,y=3
y = x--; // 現在x=2,y還是3
9.2 -- (遞減)
詳見 9.1 ++ (遞增)
9.3 += (復合加)
+= , -= , *= , /=
描述
執行常量或變量與另一個變量的數學運算。+= 等運算符是以下擴展語法的速記。
語法
X += Y; //相當於表達式X = X + Y;
X -= Y; //相當於表達式X = X - Y;
X *= Y; //相當於表達式X = X * Y;
X /= Y; //相當於表達式X = X / Y;
參數
X:任何變量類型
Y:任何變量類型或常數
例子
x = 2;
x += 4; // x 現在等於6
x -= 3; // x 現在等於3
x *= 10; // x 現在等於30
x /= 2; // x 現在等於15
9.4 -= (復合減)
詳見 9.3 += (復合加)
9.5 *= (復合乘)
詳見 9.3 += (復合加)
9.6 /= (復合除)
詳見 9.3 += (復合加)
9.6 &= (復合運算按位與)
描述
復合運算按位與運算符(&=)經常被用來將一個變量和常量進行運算使變量某些位變為0。這通常被稱為“清算”或“復位”位編程指南。
語法
x &= y; // 等價於 x = x & y;
參數
x:char,int或long類型變量
Y:char,int或long類型常量
例如
首先,回顧一下按位與(&)運算符
0 0 1 1 運算元1
0 1 0 1 運算元2
----------
0 0 0 1(運算元1&運算元2) - 返回的結果
任何位與0進行按位與操作后被清零,如果myBite是變量
myByte&B00000000 = 0;
因此,任何位與1進行“按位與運算”后保持不變
myByte B11111111 = myByte;
注意:因為我們用位操作符來操作位,所以使用二進制的變量會很方便。如果這些數值是其他值將會得到同樣結果,只是不容易理解。同樣,B00000000是為了標示清楚,0在任何進制中都是0(恩。。有些哲學的味道) 因此 - 清除(置零)變量的任意位0和1,而保持其余的位不變,可與常量B11111100進行復合運算按位與(&=)
1 0 1 0 1 0 1 0變量
1 1 1 1 1 1 0 0 mask
----------------------
1 0 1 0 1 0 0 0
變量不變 位清零
將變量替換為x可得到同樣結果
X X X X X X X X變量
1 1 1 1 1 1 0 0 mask
----------------------
X X X X X X 0 0
變量不變 位清零
同理
myByte = 10101010;
myByte&= B1111100 == B10101000;
9.8 |= (復合運算按位或)
描述
復合按位或操作符(| =)經常用於變量和常量“設置”(設置為1),尤其是變量中的某一位。
語法
x |= y; //等價於 x = x | y;
參數
x: char,int或long類型
y:整數,int或long類型
例如
首先,回顧一下OR(|)運算符
0 0 1 1 運算元1
0 1 0 1 運算元2
----------
0 1 1 1(運算元1 | 運算元2) - 返回的結果
如果變量myByte中某一位與0經過按位或運算后不變。
myByte | B00000000 = myByte;
與1經過或運算的位將變為1.
myByte | B11111111 B11111111;
因此 - 設置變量的某些位為0和1,而變量的其他位不變,可與常量B00000011進行按位與運算(| =)
1 0 1 0 1 0 1 0變量
0 0 0 0 0 0 1 1
----------------------
1 0 1 0 1 0 1 1
變量保持不變 位設置
接下來的操作相同,只是將變量用x代替
X X X X X X X X變量
0 0 0 0 0 0 1 1 mask
----------------------
X X X X X X 1 1
變量保持不變 位設置
同上:
myByte = B10101010;
myByte | = B00000011 == B10101011;
變量部分
十、常量
10.1 HIGH|LOW(引腳電壓定義)
引腳電壓定義,HIGH和LOW
當讀取(read)或寫入(write)數字引腳時只有兩個可能的值: HIGH 和 LOW 。
HIGH
HIGH(參考引腳)的含義取決於引腳(pin)的設置,引腳定義為INPUT或OUTPUT時含義有所不同。當一個引腳通過pinMode被設置為INPUT,並通過digitalRead讀取(read)時。如果當前引腳的電壓大於等於3V,微控制器將會返回為HIGH。 引腳也可以通過pinMode被設置為INPUT,並通過digitalWrite設置為HIGH。輸入引腳的值將被一個內在的20K上拉電阻 控制 在HIGH上,除非一個外部電路將其拉低到LOW。 當一個引腳通過pinMode被設置為OUTPUT,並digitalWrite設置為HIGH時,引腳的電壓應在5V。在這種狀態下,它可以 輸出電流 。例如,點亮一個通過一串電阻接地或設置為LOW的OUTPUT屬性引腳的LED。
LOW
LOW的含義同樣取決於引腳設置,引腳定義為INPUT或OUTPUT時含義有所不同。當一個引腳通過pinMode配置為INPUT,通過digitalRead設置為讀取(read)時,如果當前引腳的電壓小於等於2V,微控制器將返回為LOW。 當一個引腳通過pinMode配置為OUTPUT,並通過digitalWrite設置為LOW時,引腳為0V。在這種狀態下,它可以 倒灌 電流。例如,點亮一個通過串聯電阻連接到+5V,或到另一個引腳配置為OUTPUT、HIGH的的LED。
10.2 INPUT|OUTPUT(數字引腳(Digital pins)定義)
數字引腳(Digital pins)定義,INPUT和OUTPUT
數字引腳當作 INPUT 或 OUTPUT都可以 。用pinMode()方法使一個數字引腳從INPUT到OUTPUT變化。
引腳(Pins)配置為輸入(Inputs)
Arduino(Atmega)引腳通過pinMode()配置為 輸入(INPUT) 即是將其配置在一個高阻抗的狀態。配置為INPUT的引腳可以理解為引腳取樣時對電路有極小的需求,即等效於在引腳前串聯一個100兆歐姆(Megohms)的電阻。這使得它們非常利於讀取傳感器,而不是為LED供電。
引腳(Pins)配置為輸出(Outputs)
引腳通過pinMode()配置為 輸出(OUTPUT) 即是將其配置在一個低阻抗的狀態。
這意味着它們可以為電路提供充足的電流。Atmega引腳可以向其他設備/電路提供(提供正電流positive current)或倒灌(提供負電流negative current)達40毫安(mA)的電流。這使得它們利於給LED供電,而不是讀取傳感器。輸出(OUTPUT)引腳被短路的接地或5V電路上會受到損壞甚至燒毀。Atmega引腳在為繼電器或電機供電時,由於電流不足,將需要一些外接電路來實現供電。
10.3 true | false(邏輯層定義)
邏輯層定義,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,需要全部小寫。
10.4 integer constants(整數常量)
整數常量是直接在程序中使用的數字,如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前綴很可能無意產生很難發現的錯誤,因為你可能不小心在常量前加了個“0”,結果就悲劇了。
十六進制以16為基底,有效的字符為0-9和A-F。十六進制數用前綴“0x”(數字0,字母愛克斯)表示。請注意,A-F不區分大小寫,就是說你也可以用a-f。
示例
0x101 // 等同於十進制257 ((1 * 16^2) + (0 * 16^1) + 1)
U & L 格式
默認情況下,整型常量被視作int型。要將整型常量轉換為其他類型時,請遵循以下規則:
'u' or 'U' 指定一個常量為無符號型。(只能表示正數和0) 例如: 33u
'l' or 'L' 指定一個常量為長整型。(表示數的范圍更廣) 例如: 100000L
'ul' or 'UL' 這個你懂的,就是上面兩種類型,稱作無符號長整型。 例如:32767ul
10.5 floating point constants(浮點常量)
和整型常量類似,浮點常量可以使得代碼更具可讀性。浮點常量在編譯時被轉換為其表達式所取的值。
例子
n = .005; 浮點數可以用科學記數法表示。'E'和'e'都可以作為有效的指數標志。
浮點數 |
被轉換為 |
被轉換為 |
10.0 |
10 |
|
2.34E5 |
2.34 * 10^5 |
234000 |
67E-12 |
67.0 * 10^-12 |
0.000000000067 |
十一、數據類型
11.1 void
void只用在函數聲明中。它表示該函數將不會被返回任何數據到它被調用的函數中。
例子
//功能在“setup”和“loop”被執行
//但沒有數據被返回到高一級的程序中
void setup()
{
// ...
}
void loop()
{
// ...
}
11.2 boolean (布爾)
一個布爾變量擁有兩個值,true或false。(每個布爾變量占用一個字節的內存。)
例子
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; // 觸發running變量
digitalWrite(LEDpin, running) //點亮LED
}
}
11.3 char(字符或字符串)
一個數據類型,占用1個字節的內存存儲一個字符值。字符都寫在單引號,如'A';(多個字符(字符串)使用雙引號,如“ABC”)。
字符以編號的形式存儲。你可以在ASCII表中看到對應的編碼。這意味着字符的ASCII值可以用來作數學計算。(例如'A'+ 1,因為大寫A的ASCII值是65,所以結果為66)。如何將字符轉換成數字參考serial.println命令。
char數據類型是有符號的類型,這意味着它的編碼為-128到127。對於一個無符號一個字節(8位)的數據類型,使用byte數據類型。
例如
char myChar = 'A';
char myChar = 65; // both are equivalent
11.4 unsigned char(無符號數據類型)
一個無符號數據類型占用1個字節的內存。與byte的數據類型相同。
無符號的char數據類型能編碼0到255的數字。
為了保持Arduino的編程風格的一致性,byte數據類型是首選。
例子
unsigned char myChar = 240;
11.5 byte(無符號數)
一個字節存儲8位無符號數,從0到255。
例子
byte b = B10010; // "B" 是二進制格式(B10010等於十進制18)
11.6 int(整型)
整數是基本數據類型,占用2字節。整數的范圍為-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 現在是 32,767。
x = 32,767;
x = x + 1; // x 現在是 -32,768。
11.7 unsigned int(無符號整型)
描述
無符號整型變量擴充了變量容量以存儲更大的數據,它能存儲32位(4字節)數據。與標准長整型不同無符號長整型無法存儲負數,其范圍從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);
//等待一秒鍾,以免發送大量的數據
delay(1000);
}
語法
unsigned long var = val;
var - 你所定義的變量名
val - 給變量所賦的值
11.8 word
描述
一個存儲一個16字節無符號數的字符,取值范圍從0到65535,與unsigned int相同。
例子
word w = 10000;
11.9 long(長整數型)
描述
長整數型變量是擴展的數字存儲變量,它可以存儲32位(4字節)大小的變量,從-2,147,483,648到2,147,483,647。
例子
long speedOfLight = 186000L; //參見整數常量‘L’的說明
語法
long var = val;
var - 長整型變量名
var - 賦給變量的值
11.10 unsigned long(無符號長整數型)
描述
無符號長整型變量擴充了變量容量以存儲更大的數據,它能存儲32位(4字節)數據。與標准長整型不同無符號長整型無法存儲負數,其范圍從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);
//等待一秒鍾,以免發送大量的數據
delay(1000);
}
語法
unsigned long var = val;
var - 你所定義的變量名
val - 給變量所賦的值
11.11 float(浮點型數)
描述
float,浮點型數據,就是有一個小數點的數字。浮點數經常被用來近似的模擬連續值,因為他們比整數更大的精確度。浮點數的取值范圍在3.4028235 E+38 ~ -3.4028235E +38。它被存儲為32位(4字節)的信息。
float只有6-7位有效數字。這指的是總位數,而不是小數點右邊的數字。與其他平台不同的是,在那里你可以使用double型得到更精確的結果(如15位),在Arduino上,double型與float型的大小相同。
浮點數字在有些情況下是不准確的,在數據大小比較時,可能會產生奇怪的結果。例如 6.0 / 3.0 可能不等於 2.0。你應該使兩個數字之間的差額的絕對值小於一些小的數字,這樣就可以近似的得到這兩個數字相等這樣的結果。
浮點運算速度遠遠慢於執行整數運算,例如,如果這個循環有一個關鍵的計時功能,並需要以最快的速度運行,就應該避免浮點運算。程序員經常使用較長的程式把浮點運算轉換成整數運算來提高速度。
舉例
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)
11.12 double(雙精度浮點數)
描述
雙精度浮點數。占用4個字節。
目前的arduino上的double實現和float相同,精度並未提高。
提示
如果你從其他地方得到的代碼中包含了double類變量,最好檢查一遍代碼以確認其中的變量的精確度能否在arduino上達到。
11.13 string(char array/字符串)
string(字符串)
描述
文本字符串可以有兩種表現形式。你可以使用字符串數據類型(這是0019版本的核心部分),或者你可以做一個字符串,由char類型的數組和空終止字符('\0')構成。(求助,待潤色-Leo)本節描述了后一種方法。而字符串對象(String object)將讓你擁有更多的功能,同時也消耗更多的內存資源,關於它的詳細信息,請參閱頁面(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())知道一個字符串的結束。否則,他們將從內存繼續讀取后續字節,而這些並不屬於所需字符串的一部分。
這意味着,你的字符串比你想要的文字包含更多的個字符空間。這就是為什么Str2和Str5需要八個字符,即使“Arduino”只有七個字符 - 最后一個位置會自動填充空字符。str4將自動調整為八個字符,包括一個額外的空。在Str3的,我們自己已經明確地包含了空字符(寫入'\ 0')。
需要注意的是,字符串可能沒有一個最后的空字符(例如在Str2中您已定義字符長度為7,而不是8)。這會破壞大部分使用字符串的功能,所以不要故意而為之。如果你注意到一些奇怪的現象(在字符串中操作字符),基本就是這個原因導致的了。
單引號?還是雙引號?
定義字符串時使用雙引號(例如“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);
}
}
11.14 String object(String類)
描述
String類,是0019版的核心的一部分,允許你實現比運用字符數組更復雜的文字操作。你可以連接字符串,增加字符串,尋找和替換子字符串以及其他操作。它比使用一個簡單的字符數組需要更多的內存,但它更方便。
僅供參考,字符串數組都用小寫的string表示而String類的實例通常用大寫的String表示。注意,在“雙引號”內指定的字符常量通常被作為字符數組,並非String類實例。
函數
String
charAt()
compareTo()
concat()
endsWith()
equals()
equalsIgnoreCase()
GetBytes()
indexOf()
lastIndexOf
length
replace()
setCharAt()
startsWith()
substring()
toCharArray()
toLowerCase()
toUpperCase()
trim()
操作符
[](元素訪問)
+(串連)
==(比較)
舉例
StringConstructors
StringAdditionOperator
StringIndexOf
StringAppendOperator
StringLengthTrim
StringCaseChanges
StringReplace
StringCharacters
StringStartsWithEndsWith
StringComparisonOperators
StringSubstring
11.15 array (數組)
數組是一種可訪問的變量的集合。Arduino的數組是基於C語言的,因此這會變得很復雜,但使用簡單的數組是比較簡單的。
創建(聲明)一個數組
下面的方法都可以用來創建(聲明)數組。
myInts [6];
myPins [] = {2,4,8,3,6};
mySensVals [6] = {2,4,-8,3,2};
char message[6] = "hello";
你聲明一個未初始化數組,例如myPins。
在myPins中,我們聲明了一個沒有明確大小的數組。編譯器將會計算元素的大小,並創建一個適當大小的數組。
當然,你也可以初始化數組的大小,例如在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),則將從其他內存中讀取數據。從這些地方讀取的數據,除了產生無效的數據外,沒有任何作用。向隨機存儲器中寫入數據絕對是一個壞主意,通常會導致不愉快的結果,如導致系統崩潰或程序故障。要排查這樣的錯誤是也是一件難事。 不同於Basic或JAVA,C語言編譯器不會檢查你訪問的數組是否大於你聲明的數組。
指定一個數組的值
mySensVals [0] = 10;
從數組中訪問一個值:
X = mySensVals [4];
數組和循環
數組往往在for循環中進行操作,循環計數器可用於訪問每個數組元素。例如,將數組中的元素通過串口打印,你可以這樣做:
int i;
for (i = 0; i < 5; i = i + 1) {
Serial.println(myPins[i]);
}
例子
如果你需要一個演示數組的完整程序,請參考Knight Rider exampel。
十二、數據類型轉換
12.1 char()
描述
將一個變量的類型變為char。
語法
char(x)
參數
x:任何類型的值
返回
char
12.2 byte()
描述
將一個值轉換為字節型數值。
語法
byte(x)
參數
X:任何類型的值
返回
字節
12.3 int()
描述
將一個值轉換為int類型。
語法
int(x)
參數
x:一個任何類型的值
返回值
int類型的值
12.4 word()
描述
把一個值轉換為word數據類型的值,或由兩個字節創建一個字符。
語法
word(x)
word(h, l)
參數
X:任何類型的值
H:高階(最左邊)字節
L:低序(最右邊)字節
返回值
字符
12.5 long()
描述
將一個值轉換為長整型數據類型。
語法
long(x)
參數
x:任意類型的數值
返回值
長整型數
12.6 float()
描述
將一個值轉換為float型數值。
語法
float(x)
參數
X:任何類型的值
返回值
float型數
注釋
見float中關於Arduino浮點數的精度和限制的詳細信息。
十三、變量作用域 & 修飾符
13.1 variable scope(變量的作用域)
變量的作用域
在Arduino使用的C編程語言的變量,有一個名為 作用域(scope) 的屬性 。這一點與類似BASIC的語言形成了對比,在BASIC語言中所有變量都是 全局(global) 變量。
在一個程序內的全局變量是可以被所有函數所調用的。局部變量只在聲明它們的函數內可見。在Arduino的環境中,任何在函數(例如,setup(),loop()等)外聲明的變量,都是全局變量。
當程序變得更大更復雜時,局部變量是一個有效確定每個函數只能訪問其自己變量的途徑。這可以防止,當一個函數無意中修改另一個函數使用的變量的程序錯誤。
有時在一個for循環內聲明並初始化一個變量也是很方便的選擇。這將創建一個只能從for循環的括號內訪問的變量。
例子
int gPWMval; // 任何函數都可以調用此變量
void setup()
{
// ...
}
void loop()
{
int i; // "i" 只在 "loop" 函數內可用
float f; // "f" 只在 "loop" 函數內可用
// ...
for (int j = 0; j <100; j++){
//變量j只能在循環括號內訪問
}
}
13.2 static(靜態變量)
static關鍵字用於創建只對某一函數可見的變量。然而,和局部變量不同的是,局部變量在每次調用函數時都會被創建和銷毀,靜態變量在函數調用后仍然保持着原來的數據。
靜態變量只會在函數第一次調用的時候被創建和初始化。
例子
/* RandomWalk
* Paul Badger 2007
* RandomWalk函數在兩個終點間隨機的上下移動
* 在一個循環中最大的移動由參數“stepsize”決定
*一個靜態變量向上和向下移動一個隨機量
*這種技術也被叫做“粉紅噪聲”或“醉步”
*/
#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中存儲變量
// 聲明為靜態因此它在函數調用之間能保持數據,但其他函數無法改變它的值
place = place + (random(-moveSize, moveSize + 1));
if (place < randomWalkLowRange){ //檢查上下限
place = place + (randomWalkLowRange - place); // 將數字變為正方向
}
else if(place > randomWalkHighRange){
place = place - (place - randomWalkHighRange); // 將數字變為負方向
}
return place;
}
13.3 volatile
volatile這個關鍵字是變量修飾符,常用在變量類型的前面,以告訴編譯器和接下來的程序怎么對待這個變量。
聲明一個volatile變量是編譯器的一個指令。編譯器是一個將你的C/C++代碼轉換成機器碼的軟件,機器碼是arduino上的Atmega芯片能識別的真正指令。
具體來說,它指示編譯器編譯器從RAM而非存儲寄存器中讀取變量,存儲寄存器是程序存儲和操作變量的一個臨時地方。在某些情況下,存儲在寄存器中的變量值可能是不准確的。
如果一個變量所在的代碼段可能會意外地導致變量值改變那此變量應聲明為volatile,比如並行多線程等。在arduino中,唯一可能發生這種現象的地方就是和中斷有關的代碼段,成為中斷服務程序。
例子
//當中斷引腳改變狀態時,開閉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;
}
13.4 const
const關鍵字代表常量。它是一個變量限定符,用於修改變量的性質,使其變為只讀狀態。這意味着該變量,就像任何相同類型的其他變量一樣使用,但不能改變其值。如果嘗試為一個const變量賦值,編譯時將會報錯。
const關鍵字定義的常量,遵守 variable scoping 管轄的其他變量的規則。這一點加上使用 #define的缺陷 ,使 const 關鍵字成為定義常量的一個的首選方法。
例子
const float pi = 3.14;
float x;
// ....
x = pi * 2; // 在數學表達式中使用常量不會報錯
pi = 7; // 錯誤的用法 - 你不能修改常量值,或給常量賦值。
#define 或 const
您可以使用 const 或 #define 創建數字或字符串常量。但 arrays, 你只能使用 const。 一般 const 相對 的#define是首選 的定義常量語法。
十四、輔助工具
14.1 sizeof()
描述
sizeof操作符返回一個變量類型的字節數,或者該數在數組中占有的字節數。
語法
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返回字節數總數。因此,較大的變量類型,如整數,for循環看起來應該像這樣。
for (i = 0; i < (sizeof(myInts)/sizeof(int)) - 1; i++) {
//用myInts[i]來做些事
}
函數部分
十五、數字 I/O
15.1 pinMode()
描述
將指定的引腳配置成輸出或輸入。詳情請見digital pins。
語法
pinMode(pin, mode)
參數
pin:要設置模式的引腳
mode:INPUT或OUTPUT
返回
無
例子
ledPin = 13 // LED連接到數字腳13
void setup()
{
pinMode(ledPin,OUTPUT); //設置數字腳為輸出
}
void loop()
{
digitalWrite(ledPin,HIGH); //點亮LED
delay(1000); // 等待一秒
digitalWrite(ledPin, LOW); // 滅掉LED
延遲(1000); //等待第二個
}
注意
模擬輸入腳也能當做數字腳使用,參見A0,A1等
15.2 digitalWrite()
描述
給一個數字引腳寫入HIGH或者LOW。
如果一個引腳已經使用pinMode()配置為OUTPUT模式,其電壓將被設置為相應的值,HIGH為5V(3.3V控制板上為3.3V),LOW為0V。
如果引腳配置為INPUT模式,使用digitalWrite()寫入HIGH值,將使內部20K上拉電阻(詳見數字引腳教程)。寫入LOW將會禁用上拉。上拉電阻可以點亮一個LED讓其微微亮,如果LED工作,但是亮度很低,可能是因為這個原因引起的。補救的辦法是 使用pinMode()函數設置為輸出引腳。
注意:數字13號引腳難以作為數字輸入使用,因為大部分的控制板上使用了一顆LED與一個電阻連接到他。如果啟動了內部的20K上拉電阻,他的電壓將在1.7V左右,而不是正常的5V,因為板載LED串聯的電阻把他使他降了下來,這意味着他返回的值總是LOW。如果必須使用數字13號引腳的輸入模式,需要使用外部上拉下拉電阻。
語法
digitalWrite(pin, value)
參數
pin: 引腳編號(如1,5,10,A0,A3)
value: HIGH or LOW
返回
無
例子
int ledPin = 13; // LED連接到數字13號端口
void setup()
{
pinMode(ledPin, OUTPUT); // 設置數字端口為輸入模式
}
void loop()
{
digitalWrite(ledPin, HIGH); // 使LED亮
delay(1000); // 延遲一秒
digitalWrite(ledPin, LOW); // 使LED滅
delay(1000); // 延遲一秒
}
13號端口設置為高電平,延遲一秒,然后設置為低電平。
注釋
模擬引腳也可以當做數字引腳使用,使用方法是輸入端口A0,A1,A2等。
15.3 digitalRead()
描述
讀取指定引腳的值,HIGH或LOW。
語法
digitalRead(PIN)
參數
pin:你想讀取的引腳號(int)
返回
HIGH 或 LOW
例子
ledPin = 13 // LED連接到13腳
int inPin = 7; // 按鈕連接到數字引腳7
int val = 0; //定義變量存以儲讀值
void setup()
{
pinMode(ledPin, OUTPUT); // 將13腳設置為輸出
pinMode(inPin, INPUT); // 將7腳設置為輸入
}
void loop()
{
val = digitalRead(inPin); // 讀取輸入腳
digitalWrite(ledPin, val); //將LED值設置為按鈕的值
}
將13腳設置為輸入腳7腳的值。
注意
如果引腳懸空,digitalRead()會返回HIGH或LOW(隨機變化)。
模擬輸入腳能當做數字腳使用,參見A0,A1等。
十六、模擬 I/O
16.1 analogReference()
描述
配置用於模擬輸入的基准電壓(即輸入范圍的最大值)。選項有:
DEFAULT:默認5V(Arduino板為5V)或3.3伏特(Arduino板為3.3V)為基准電壓。
INTERNAL:在ATmega168和ATmega328上以1.1V為基准電壓,以及在ATmega8上以2.56V為基准電壓(Arduino Mega無此選項)
INTERNAL1V1:以1.1V為基准電壓(此選項僅針對Arduino Mega)
INTERNAL2V56:以2.56V為基准電壓(此選項僅針對Arduino Mega)
EXTERNAL:以AREF引腳(0至5V)的電壓作為基准電壓。
參數
type:使用哪種參考類型(DEFAULT, INTERNAL, INTERNAL1V1, INTERNAL2V56, 或者 EXTERNAL)。
返回
無
注意事項
改變基准電壓后,之前從analogRead()讀取的數據可能不准確。
警告
不要在AREF引腳上使用使用任何小於0V或超過5V的外部電壓。如果你使用AREF引腳上的電壓作為基准電壓,你在調用analogRead()前必須設置參考類型為EXTERNAL。否則,你將會削短有效的基准電壓(內部產生)和AREF引腳,這可能會損壞您Arduino板上的單片機。
另外,您可以在外部基准電壓和AREF引腳之間連接一個5K電阻,使你可以在外部和內部基准電壓之間切換。請注意,總阻值將會發生改變,因為AREF引腳內部有一個32K電阻。這兩個電阻都有分壓作用。所以,例如,如果輸入2.5V的電壓,最終在在AREF引腳上的電壓將為2.5 * 32 /(32 + 5)= 2.2V。
16.2 analogRead()
描述
從指定的模擬引腳讀取數據值。 Arduino板包含一個6通道(Mini和Nano有8個通道,Mega有16個通道),10位模擬數字轉換器。這意味着它將0至5伏特之間的輸入電壓映射到0至1023之間的整數值。這將產生讀數之間的關系:5伏特/ 1024單位,或0.0049伏特(4.9 mV)每單位。輸入范圍和精度可以使用analogReference()改變。 它需要大約100微秒(0.0001)來讀取模擬輸入,所以最大的閱讀速度是每秒10000次。
語法
analogRead(PIN)
數值的讀取
引腳:從輸入引腳(大部分板子從0到5,Mini和Nano從0到7,Mega從0到15)讀取數值
返回
從0到1023的整數值
注意事項
如果模擬輸入引腳沒有連入電路,由analogRead()返回的值將根據多項因素(例如其他模擬輸入引腳,你的手靠近板子等)產生波動。
例子
int analogPin = 3; //電位器(中間的引腳)連接到模擬輸入引腳3
//另外兩個引腳分別接地和+5 V
int val = 0; //定義變量來存儲讀取的數值
void setup()
{
serial.begin(9600); //設置波特率(9600)
}
void loop()
{
val = analogRead(analogPin); //從輸入引腳讀取數值
serial.println(val); //顯示讀取的數值
}
16.3 analogWrite() PWM
描述
從一個引腳輸出模擬值(PWM)。可用於讓LED以不同的亮度點亮或驅動電機以不同的速度旋轉。analogWrite()輸出結束后,該引腳將產生一個穩定的特殊占空比方波,直到下次調用analogWrite()(或在同一引腳調用digitalRead()或digitalWrite())。PWM信號的頻率大約是490赫茲。
在大多數arduino板(ATmega168或ATmega328),只有引腳3,5,6,9,10和11可以實現該功能。在aduino Mega上,引腳2到13可以實現該功能。老的Arduino板(ATmega8)的只有引腳9、10、11可以使用analogWrite()。在使用analogWrite()前,你不需要調用pinMode()來設置引腳為輸出引腳。
analogWrite函數與模擬引腳、analogRead函數沒有直接關系。
語法
analogWrite(pin,value)
參數
pin:用於輸入數值的引腳。
value:占空比:0(完全關閉)到255(完全打開)之間。
返回
無
說明和已知問題
引腳5和6的PWM輸出將高於預期的占空比(輸出的數值偏高)。這是因為millis()和delay()功能,和PWM輸出共享相同的內部定時器。這將導致大多時候處於低占空比狀態(如:0 - 10),並可能導致在數值為0時,沒有完全關閉引腳5和6。
例子
通過讀取電位器的阻值控制LED的亮度
int ledPin = 9; // LED連接到數字引腳9
int analogPin = 3; //電位器連接到模擬引腳3
int val = 0; //定義變量存以儲讀值
void setup()
{
pinMode(ledPin,OUTPUT); //設置引腳為輸出引腳
}
void loop()
{
val = analogRead(analogPin); //從輸入引腳讀取數值
analogWrite(ledPin,val / 4); // 以val / 4的數值點亮LED(因為analogRead讀取的數值從0到1023,而analogWrite輸出的數值從0到255)
}
十七、高級 I/O
17.1 tone()
描述
在一個引腳上產生一個特定頻率的方波(50%占空比)。持續時間可以設定,否則波形會一直產生直到調用noTone()函數。該引腳可以連接壓電蜂鳴器或其他喇叭播放聲音。
在同一時刻只能產生一個聲音。如果一個引腳已經在播放音樂,那調用tone()將不會有任何效果。如果音樂在同一個引腳上播放,它會自動調整頻率。
使用tone()函數會與3腳和11腳的PWM產生干擾(Mega板除外)。
注意:如果你要在多個引腳上產生不同的音調,你要在對下一個引腳使用tone()函數前對此引腳調用noTone()函數。
語法
tone(pin, frequency)
tone(pin, frequency, duration)
參數
pin:要產生聲音的引腳
frequency: 產生聲音的頻率,單位Hz,類型unsigned int
duration:聲音持續的時間,單位毫秒(可選),類型unsigned long
17.2 noTone()
描述
停止由tone()產生的方波。如果沒有使用tone()將不會有效果。
注意:如果你想在多個引腳上產生不同的聲音,你要在對下個引腳使用tone()前對剛才的引腳調用noTone().
語法
noTone(pin)
參數
pin: 所要停止產生聲音的引腳
17.3 shiftOut()
描述
將一個數據的一個字節一位一位的移出。從最高有效位(最左邊)或最低有效位(最右邊)開始。依次向數據腳寫入每一位,之后時鍾腳被拉高或拉低,指示剛才的數據有效。
注意:如果你所連接的設備時鍾類型為上升沿,你要確定在調用shiftOut()前時鍾腳為低電平,如調用digitalWrite(clockPin, LOW)。
注意:這是一個軟件實現;Arduino提供了一個硬件實現的SPI庫,它速度更快但只在特定腳有效。
語法
shiftOut(dataPin, clockPin, bitOrder, value)
參數
dataPin:輸出每一位數據的引腳(int)
clockPin:時鍾腳,當dataPin有值時此引腳電平變化(int)
bitOrder:輸出位的順序,最高位優先或最低位優先
value: 要移位輸出的數據(byte)
返回
無
注意
dataPin和clockPin要用pinMode()配置為輸出。 shiftOut目前只能輸出1個字節(8位),所以如果輸出值大於255需要分兩步。
//最高有效位優先串行輸出
int 數據= 500;
//移位輸出高字節
shiftOut(dataPin, clock, MSBFIRST, (data >> 8));
//移位輸出低字節
shiftOut(data, clock, MSBFIRST, data);
//最低有效位優先串行輸出
data = 500;
//移位輸出低字節
shiftOut(dataPin, clock, LSBFIRST, data);
//移位輸出高字節
shiftOut(dataPin, clock, LSBFIRST, (data >> 8));
例子
相應電路,查看tutorial on controlling a 74HC595 shift register
// ************************************************ ************** //
// Name : shiftOut代碼, Hello World //
// Author : Carlyn Maw,Tom Igoe //
// Date : 25 Oct, 2006 //
// 版本 : 1.0 //
// 注釋:使用74HC595移位寄存器從0到255計數 //
//
// ************************************************ ****************
//引腳連接到74HC595的ST_CP
int latchPin = 8;
//引腳連接到74HC595的SH_CP
int clockPin = 12;
// //引腳連接到74HC595的DS
int dataPin = 11;
void setup() {
//設置引腳為輸出
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
//向上計數程序
(J = 0; J <256; J + +){
//傳輸數據的時候將latchPin拉低
digitalWrite(latchpin, LOW);
shiftOut的 (dataPin,clockPin,LSBFIRST,J);
//之后將latchPin拉高以告訴芯片
//它不需要再接受信息了
digitalWrite(latchpin, HIGH);
delay(1000);
}
}
17.4 shiftIn()
描述
將一個數據的一個字節一位一位的移入。從最高有效位(最左邊)或最低有效位(最右邊)開始。對於每個位,先拉高時鍾電平,再從數據傳輸線中讀取一位,再將時鍾線拉低。
注意:這是一個軟件實現;Arduino提供了一個硬件實現的SPI庫,它速度更快但只在特定腳有效。
語法
shiftIn(dataPin,clockPin,bitOrder)
參數
dataPin:輸出每一位數據的引腳(int)
clockPin:時鍾腳,當dataPin有值時此引腳電平變化(int)
bitOrder:輸出位的順序,最高位優先或最低位優先
17.5 pulseIn()
描述
讀取一個引腳的脈沖(HIGH或LOW)。例如,如果value是HIGH,pulseIn()會等待引腳變為HIGH,開始計時,再等待引腳變為LOW並停止計時。返回脈沖的長度,單位微秒。如果在指定的時間內無脈沖函數返回。
此函數的計時功能由經驗決定,長時間的脈沖計時可能會出錯。計時范圍從10微秒至3分鍾。(1秒=1000毫秒=1000000微秒)
語法
pulseIn(pin, value)
pulseIn(pin, value, timeout)
參數
pin:你要進行脈沖計時的引腳號(int)。
value:要讀取的脈沖類型,HIGH或LOW(int)。
timeout (可選):指定脈沖計數的等待時間,單位為微秒,默認值是1秒(unsigned long)
返回
脈沖長度(微秒),如果等待超時返回0(unsigned long)
例子
int pin = 7;
unsigned long duration;
void setup()
{
pinMode(pin, INPUT);
}
void loop()
{
duration = pulseIn(pin, HIGH);;
}
十八、時間
18.1 millis()
描述
返回Arduino開發板從運行當前程序開始的毫秒數。這個數字將在約50天后溢出(歸零)。
參數
無
返回
返回從運行當前程序開始的毫秒數(無符號長整數)。
例子
unsigned long time;
void setup(){
Serial.begin(9600);
}
void loop(){
serial.print("Time:");
time = millis();
//打印從程序開始到現在的時間
serial.println(time);
//等待一秒鍾,以免發送大量的數據
delay(1000);
}
提示
注意,參數 millis 是一個無符號長整數,試圖和其他數據類型(如整型數)做數學運算可能會產生錯誤。
當中斷函數發生時,millis()的數值將不會繼續變化。
18.2 micros()
描述
返回 Arduino 開發板從運行當前程序開始的微秒數。這個數字將在約70分鍾后溢出(歸零)。在 16MHz 的 Arduino 開發板上(比如 Duemilanove 和 Nano),這個函數的分辨率為四微秒(即返回值總是四的倍數)。在 8MHz 的 Arduino 開發板上(比如 LilyPad),這個函數的分辨率為八微秒。
注意 :每毫秒是1,000微秒,每秒是1,000,000微秒。
參數
無
返回
返回從運行當前程序開始的微秒數(無符號長整數)。
例子
unsigned long time;
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.print(“Time:”);
time = micros();
//打印從程序開始的時間
Serial.println(time);
//等待一秒鍾,以免發送大量的數據
delay(1000);
}
18.3 delay()
描述
使程序暫定設定的時間(單位毫秒)。(一秒等於1000毫秒)
語法
delay(ms)
參數
ms:暫停的毫秒數(unsigned long)
返回
無
例子
ledPin = 13 / / LED連接到數字13腳
void setup()
{
pinMode(ledPin, OUTPUT); // 設置引腳為輸出
}
void loop()
{
digitalWrite(ledPin, HIGH); // 點亮LED
delay(1000); // 等待1秒
digitalWrite(ledPin, LOW); // 滅掉LED
delay(1000); // 等待一秒
}
警告
雖然創建一個使用delay()的閃爍LED很簡單,並且許多例子將很短的delay用於消除開關抖動,delay()確實擁有很多顯著的缺點。在delay函數使用的過程中,讀取傳感器值、計算、引腳操作均無法執行,因此,它所帶來的后果就是使其他大多數活動暫停。其他操作定時的方法請參加millis()函數和它下面的例子。大多數熟練的程序員通常避免超過10毫秒的delay(),除非arduino程序非常簡單。
但某些操作在delay()執行時任然能夠運行,因為delay函數不會使中斷失效。通信端口RX接收到得數據會被記錄,PWM(analogWrite)值和引腳狀態會保持,中斷也會按設定的執行。
18.4 delayMicroseconds()
描述
使程序暫停指定的一段時間(單位:微秒)。一秒等於1000000微秒。 目前,能夠產生的最大的延時准確值是16383。這可能會在未來的Arduino版本中改變。對於超過幾千微秒的延遲,你應該使用delay()代替。
語法
delayMicroseconds(us)
參數
us:暫停的時間,單位微秒(unsigned int)
返回
無
例子
int outPin = 8; // digital pin 8
void setup()
{
pinMode(outPin,OUTPUT); //設置為輸出的數字管腳
}
void loop()
{
digitalWrite(outPin,HIGH); //設置引腳高電平
delayMicroseconds(50); // 暫停50微秒
digitalWrite(outPin, LOW); // 設置引腳低電平
delayMicroseconds(50); // 暫停50微秒
}
將8號引腳配置為輸出腳。它會發出一系列周期100微秒的方波。
警告和已知問題
此函數在3微秒以以上工作的非常准確。我們不能保證,delayMicroseconds在更小的時間內延時准確。
Arduino0018版本后,delayMicroseconds()不再會使中斷失效。
十九、數學運算
19.1 min()
min(x, y)
描述
計算兩個數字中的最小值。
參數
X:第一個數字,任何數據類型
Y:第二個數字,任何數據類型
返回
兩個數字中的較小者。
舉例
sensVal = min(sensVal,100); //將 sensVal 或 100 中較小者賦值給 sensVal
//確保它永遠不會大於 100。
注釋
直觀的比較,max() 方法常被用來約束變量的下限,而 min() 常被用來約束變量的上限。
警告
由於 min() 函數的實現方式,應避免在括號內出現其他函數,這將導致不正確的結果。
min(a++, 100); //避免這種情況 - 會產生不正確的結果
a++;
min(a, 100); //使用這種形式替代 - 將其他數學運算放在函數之外
19.2 max()
max(x,y)
描述
計算兩個數的最大值。
參數
X:第一個數字,任何數據類型
Y:第二個數字,任何數據類型
返回
兩個參數中較大的一個。
例子
sensVal = max(senVal, 20); // 將20或更大值賦給sensVal
//(有效保障它的值至少為20)
注意
和直觀相反,max()通常用來約束變量最小值,而min()通常用來約束變量的最大值。
警告
由於max()函數的實現方法,要避免在括號內嵌套其他函數,這可能會導致不正確的結果。
max(a--, 0); //避免此用法,這會導致不正確結果
a--; // 用此方法代替
max(a, 0); // 將其他計算放在函數外
19.3 abs()
ABS(X)
描述
計算一個數的絕對值。
參數
X:一個數
返回
如果x大於或等於0,則返回它本身。 如果x小於0,則返回它的相反數。
警告
由於實現ABS()函數的方法,避免在括號內使用任何函數(括號內只能是數字),否則將導致不正確的結果。
ABS(a+ +); //避免這種情況,否則它將產生不正確的結果
a ++; //使用這段代碼代替上述的錯誤代碼
ABS(a); //保證其他函數放在括號的外部
19.4 constrain()
描述
將一個數約束在一個范圍內
參數
x:要被約束的數字,所有的數據類型適用。
a:該范圍的最小值,所有的數據類型適用。
b:該范圍的最大值,所有的數據類型適用。
返回值
x:如果 x是介於 a 和 b之間
a:如果 x小於a
b:如果 x大於b
例子
sensVal = constrain(sensVal, 10, 150);
//傳感器返回值的范圍限制在10到150之間
19.5 map()
map(value, fromLow, fromHigh, toLow, toHigh)
描述
將一個數從一個范圍映射到另外一個范圍。也就是說,會將 fromLow 到 fromHigh 之間的值映射到 toLow 在 toHigh 之間的值。
不限制值的范圍,因為范圍外的值有時是刻意的和有用的。如果需要限制的范圍, constrain() 函數可以用於此函數之前或之后。
注意,兩個范圍中的“下限”可以比“上限”更大或者更小,因此 map() 函數可以用來翻轉數值的范圍,例如:
y = map(x, 1, 50, 50, 1);
這個函數同樣可以處理負數,請看下面這個例子:
y = map(x, 1, 50, 50, -100);
是有效的並且可以很好的運行。
map() 函數使用整型數進行運算因此不會產生分數,這時運算應該表明它需要這樣做。小數的余數部分會被舍去,不會四舍五入或者平均。
參數
value:需要映射的值
fromLow:當前范圍值的下限
fromHigh:當前范圍值的上限
toLow:目標范圍值的下限
toHigh:目標范圍值的上限
返回值
被映射的值。
例子
/*映射一個模擬值到8位(0到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;
}
19.6 pow()
pow(base, exponent)
描述
計算一個數的冪次方。Pow()可以用來計算一個數的分數冪。這用來產生指數冪的數或曲線非常方便。
參數
base:底數(float)
exponent:冪(float)
返回
一個數的冪次方值(double)
例子
詳情見 庫代碼中的fscale函數。
19.7 sqrt()
sqrt(x)
描述
計算一個數的平方根。
參數
x:被開方數,任何類型
返回值
此數的平方根,類型double
二十、三角函數
20.1 sin()
sin(rad)
描述
計算角度的正弦(弧度)。其結果在-1和1之間。
參數
rad: 弧度制的角度(float)
返回
角度的正弦值(double)
20.2 cos()
cos(rad)
描述
計算一個角度的余弦值(用弧度表示)。返回值在 -1 和 1 之間。
參數
rad:用弧度表示的角度 (浮點數)
返回
角度的余弦值 (雙精度浮點數)
20.3 tan()
tan(rad)
描述
計算角度的正切(弧度)。結果在負無窮大和無窮大之間。
參數
rad:弧度制的角度(float)
返回值
角度的正切值
二十一、隨機數
21.1 randomSeed()
randomSeed(seed)
描述
使用randomSeed()初始化偽隨機數生成器,使生成器在隨機序列中的任意點開始。這個序列,雖然很長,並且是隨機的,但始終是同一序列。
如需要在一個random()序列上生成真正意義的隨機數,在執行其子序列時使用randomSeed()函數預設一個絕對的隨機輸入,例如在一個斷開引腳上的analogRead()函數的返回值。
反之,有些時候偽隨機數的精確重復也是有用的。這可以在一個隨機系列開始前,通過調用一個使用固定數值的randomSeed()函數來完成。
參數
long,int - 通過數字生成種子。
返回
沒有返回值
例子
long randNumber;
void setup(){
Serial.begin(9600);
randomSeed(analogRead(0));
}
void loop(){
randNumber = random(300);
Serial.println(randNumber);
delay(50);
}
21.2 random()
random()
描述
使用random()函數將生成偽隨機數。
語法
random(max)
random(min, max)
參數
min - 隨機數的最小值,隨機數將包含此值。 (此參數可選)
max - 隨機數的最大值,隨機數不包含此值。
返回
min和max-1之間的隨機數( 數據類型為long )
注意
如需要在一個random()序列上生成真正意義的隨機數,在執行其子序列時使用randomSeed()函數預設一個絕對的隨機輸入,例如在一個斷開引腳上的analogRead()函數的返回值。
反之,有些時候偽隨機數的精確重復也是有用的。這可以在一個隨機系列開始前,通過調用一個使用固定數值的randomSeed()函數來完成。
例子
long randNumber;
void setup(){
Serial.begin(9600);
//如果模擬輸入引腳0為斷開,隨機的模擬噪聲
//將會調用randomSeed()函數在每次代碼運行時生成
//不同的種子數值。
//randomSeed()將隨機打亂random函數。
randomSeed(analogRead(0));
}
void loop() {
//打印一個0到299之間的隨機數
randNumber = random(300);
Serial.println(randNumber);
//打印一個10到19之間的隨機數
randNumber = random(10, 20);
Serial.println(randNumber);
delay(50);
}
二十二、位操作
22.1 lowByte()
描述
提取一個變量(例如一個字)的低位(最右邊)字節。
語法
lowByte(x)
參數
x:任何類型的值
返回
字節
22.2 highByte()
描述
提取一個字節的高位(最左邊的),或一個更長的字節的第二低位。
語法
highByte(x)
參數
x:任何類型的值
返回
byte
22.3 bitRead()
描述
讀取一個數的位。
語法
bitRead(x, n)
參數
X:想要被讀取的數 N:被讀取的位,0是最低有效位(最右邊)
返回
該位的值(0或1)。
22.4 bitWrite()
描述
在位上寫入數字變量。
語法
bitWrite(x, n, b)
參數
X:要寫入的數值變量
N:要寫入的數值變量的位,從0開始是最低(最右邊)的位
B:寫入位的數值(0或1)
返回
無
22.5 bitSet()
描述
為一個數字變量設置一個位。
語句
bitSet(x, n)
語法
X:想要設置的數字變量
N:想要設置的位,0是最重要(最右邊)的位
返回
無
22.6 bitClear()
描述
清除一個數值型數值的指定位(將此位設置成 0)
語法
bitClear(x, n)
參數
X:指定要清除位的數值 N:指定要清除位的位置,從0開始,0 表示最右端位
返回值
無
22.7 bit()
描述
計算指定位的值(0位是1,1位是2,2位4,以此類推)。
語法
bit(n)
參數
n:需要計算的位
返回值
位值
二十三、設置中斷函數
23.1 attachInterrupt()
attachInterrupt(interrupt, function, mode)
描述
當發生外部中斷時,調用一個指定函數。當中斷發生時,該函數會取代正在執行的程序。大多數的Arduino板有兩個外部中斷:0(數字引腳2)和1(數字引腳3)。
arduino Mege有四個外部中斷:數字2(引腳21),3(20針),4(引腳19),5(引腳18)。
語法
interrupt:中斷引腳數
function:中斷發生時調用的函數,此函數必須不帶參數和不返回任何值。該函數有時被稱為中斷服務程序。
mode:定義何時發生中斷以下四個contstants預定有效值:
LOW 當引腳為低電平時,觸發中斷
CHANGE 當引腳電平發生改變時,觸發中斷
RISING 當引腳由低電平變為高電平時,觸發中斷
FALLING 當引腳由高電平變為低電平時,觸發中斷.
返回
無
注意事項
當中斷函數發生時,delay()和millis()的數值將不會繼續變化。當中斷發生時,串口收到的數據可能會丟失。你應該聲明一個變量來在未發生中斷時儲存變量。
使用中斷
在單片機自動化程序中當突發事件發生時,中斷是非常有用的,它可以幫助解決時序問題。一個使用中斷的任務可能會讀一個旋轉編碼器,監視用戶的輸入。
如果你想以確保程序始終抓住一個旋轉編碼器的脈沖,從來不缺少一個脈沖,它將使寫一個程序做任何事情都要非常棘手,因為該計划將需要不斷輪詢的傳感器線編碼器,為了趕上脈沖發生時。其他傳感器也是如此,如試圖讀取一個聲音傳感器正試圖趕上一按,或紅外線槽傳感器(照片滅弧室),試圖抓住一個硬幣下降。在所有這些情況下,使用一個中斷可以釋放的微控制器來完成其他一些工作。
程序示例
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;
}
23.2 detachInterrupt()
detachInterrupt(interrupt)
描述
關閉給定的中斷。
參數
interrupt: 中斷禁用的數(0或者1).
二十四、開關中斷
24.1 interrupts()(中斷)
描述
重新啟用中斷(使用noInterrupts()命令后將被禁用)。中斷允許一些重要任務在后台運行,默認狀態是啟用的。禁用中斷后一些函數可能無法工作,並傳入信息可能會被忽略。中斷會稍微打亂代碼的時間,但是在關鍵部分可以禁用中斷。
參數
無
返回
無
例子
void setup() {
}
void loop()
{
noInterrupts();
//重要、時間敏感的代碼
interrupts();
//其他代碼寫在這里
}
24.2 noInterrupts()(禁止中斷)
描述
禁止中斷(重新使能中斷interrupts())。中斷允許在后台運行一些重要任務,默認使能中斷。禁止中斷時部分函數會無法工作,通信中接收到的信息也可能會丟失。
中斷會稍影響計時代碼,在某些特定的代碼中也會失效。
參數
無
返回
無
例子
void setup()
void loop()
{
noInterrupts();
//關鍵的、時間敏感的代碼放在這
interrupts();
//其他代碼放在這
}
二十五、通訊
25.1 Serial
用於Arduino控制板和一台計算機或其他設備之間的通信。所有的Arduino控制板有至少一個串口(又稱作為UART或USART)。它通過0(RX)和1(TX)數字引腳經過串口轉換芯片連接計算機USB端口與計算機進行通信。因此,如果你使用這些功能的同時你不能使用引腳0和1作為輸入或輸出。
您可以使用Arduino IDE內置的串口監視器與Arduino板通信。點擊工具欄上的串口監視器按鈕,調用begin()函數(選擇相同的波特率)。
Arduino Mega 有三個額外的串口:Serial 1使用19(RX)和18(TX),Serial 2使用17(RX)和16(TX),Serial3使用15(RX)和14(TX)。 若要使用這三個引腳與您的個人電腦通信,你需要一個額外的USB轉串口適配器,因為這三個引腳沒有連接到Mega上的USB轉串口適配器。若要用它們來與外部的TTL串口設備進行通信,將TX引腳連接到您的設備的RX引腳,將RX引腳連接到您的設備的TX引腳,將GND連接到您的設備的GND。(不要直接將這些引腳直接連接到RS232串口;他們的工作電壓在+/- 12V,可能會損壞您的Arduino控制板。)
Arduino Leonardo板使用Serial 1通過0(RX)和1(TX)與viaRS-232通信,。Serial預留給使用Mouse and Keyboard libarariies的USB CDC通信 。更多信息,請參考Leonardo 開始使用頁和硬件頁。
函數
25.1.1 if (Serial)
25.1.2 available()
25.1.3 begin()
25.1.4 end()
25.1.5 find()
25.1.6 findUntil()
25.1.7 flush()
25.1.8 parseFloat()
25.1.9 parseInt()
25.1.10 peek()
25.1.11 print()
25.1.12 println()
25.1.13 read()
25.1.14 readBytes()
25.1.15 readBytesUntil()
25.1.16 setTimeout()
25.1.17 write()
25.1.18 SerialEvent()
25.1.1 if (Serial)
說明
表示指定的串口是否准備好。
在Leonardo上,if(Serial)表示不論有無USB CDC,串行連接都是開放的。對於所有其他的情況,包括Leonardo上的if(Serial1),將一直返回true。 這來自於 Arduino 1.0.1 版本的介紹.
語法
對於所有的arduino板:
if (Serial)
Arduino Leonardo 特有:
if (Serial1)
Arduino Mega 特有:
if (Serial1)
if (Serial2)
if (Serial3)
參數
無
返回
布爾值:如果指定的串行端口是可用的,則返回true。如果查詢Leonardo的USB CDC串行連接之前,它是准備好的,將只返回false。
例子
void setup() {
//初始化串口和等待端口打開:
Serial.begin(9600);
while (!Serial) {
//等待串口連接。只有 Leonardo 需要。
}
}
void loop() {
//正常進行
}
25.1.2 Serial.available()
說明
獲取從串口讀取有效的字節數(字符)。這是已經傳輸到,並存儲在串行接收緩沖區(能夠存儲64個字節)的數據。 available()繼承了 Stream類。
語法
Serial.available()
僅適用於Arduino Mega :
Serial1.available()
Serial2.available()
Serial3.available()
參數
無
返回
可讀取的字節數
例子
incomingByte = 0; //傳入的串行數據
void setup() {
Serial.begin(9600); // 打開串行端口,設置傳輸波特率為9600 bps
}
void loop() {
//只有當你接收到數據時才會發送數據,:
if (Serial.available() > 0) {
//讀取傳入的字節:
incomingByte = Serial.read();
//顯示你得到的數據:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
Arduino Mega 的例子:
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
}
void loop() {
//讀取端口0,發送到端口1:
if (Serial.available()) {
int inByte = Serial.read();
Serial1.print(inByte, BYTE);
}
//讀端口1,發送到端口0:
if (Serial1.available()) {
int inByte = Serial1.read();
Serial.print(inByte, BYTE);
}
}
25.1.3 Serial.begin() 初始化串口波特率
說明
將串行數據傳輸速率設置為位/秒(波特)。與計算機進行通信時,可以使用這些波特率:300,1200,2400,4800,9600,14400,19200,28800,38400,57600或115200。當然,您也可以指定其他波特率 - 例如,引腳0和1和一個元件進行通信,它需要一個特定的波特率。
語法
Serial.begin(speed) 僅適用於Arduino Mega : Serial1.begin(speed) Serial2.begin(speed) Serial3.begin(speed)
參數
speed: 位/秒 (波特) - long
返回
無
例子
void setup() {
Serial.begin(9600); // 打開串口,設置數據傳輸速率為9600bps
}
void loop() {
Arduino Mega 的例子:
// Arduino Mega 可以使用四個串口
// (Serial, Serial1, Serial2, Serial3),
// 從而設置四個不同的波特率:
void setup(){
Serial.begin(9600);
Serial1.begin(38400);
Serial2.begin(19200);
Serial3.begin(4800);
Serial.println("Hello Computer");
Serial1.println("Hello Serial 1");
Serial2.println("Hello Serial 2");
Serial3.println("Hello Serial 3");
}
void loop() {}
25.1.4 Serial.end()
說明
停用串行通信,使RX和TX引腳用於一般輸入和輸出。要重新使用串行通信, 需要 Serial.begin()語句。
語法
Serial.end()
僅適用於Arduino Mega: Serial1.end() Serial2.end() Serial3.end()
參數
無
返回
無
25.1.5 Serial.find()
說明
Serial.find() 從串行緩沖器中讀取數據,直到發現給定長度的目標字符串。如果找到目標字符串,該函數返回true,如果超時則返回false。
Serial.flush() 繼承了 Stream 類.
語法
Serial.find(target)
參數
target : 要搜索的字符串(字符)
返回
布爾型
25.1.6 Serial.findUntil()
說明
Serial.findUntil()從串行緩沖區讀取數據,直到找到一個給定的長度或字符串終止位。
如果目標字符串被發現,該函數返回true,如果超時則返回false。
Serial.findUntil()繼承了Stream類。
語法
Serial.findUntil(target, terminal)
參數
target : 要搜索的字符串(char) terminal : 在搜索中的字符串終止位 (char)
返回
布爾型
25.1.7 Serial.flush()
說明
等待超出的串行數據完成傳輸。(在1.0及以上的版本中,flush()語句的功能不再是丟棄所有進入緩存器的串行數據。)
flush()繼承了Stream類.
語法
Serial.flush()
僅 Arduino Mega 可以使用的語法:
Serial1.flush()
Serial2.flush()
Serial3.flush()
參數
無
返回
無
25.1.8 Serial.parseFloat()
描述
Serial.parseFloat()命令從串口緩沖區返回第一個有效的浮點數. Characters that are not digits (or the minus sign) are skipped. parseFloat() is terminated by the first character that is not a floating point number.
Serial.parseFloat()繼承了Stream類。
語法
Serial.parseFloat()
參數
無
返回
float
25.1.9 Serial.parseInt()
說明
查找傳入的串行數據流中的下一個有效的整數。 parseInt()繼承了Stream類。
語法
Serial.parseInt()
下面三個命令僅適用於Arduino Mega:
Serial1.parseInt()
Serial2.parseInt()
Serial3.parseInt()
參數
無
返回
int : 下一個有效的整數
25.1.10 Serial.peek()
說明
返回傳入的串行數據的下一個字節(字符),而不是進入內部串行緩沖器調取。也就是說,連續調用 peek()將返回相同的字符,與調用read()方法相同。peek()繼承自 Stream類。
語法
Serial.peek()
僅適用於Arduino Mega :
Serial1.peek()
Serial2.peek()
Serial3.peek()
參數
無
返回
傳入的串行數據的第一個字節(或-1,如果沒有可用的數據的話)- int
25.1.11 Serial.print() 從串口打印輸出數據
說明
以人們可讀的ASCII文本形式打印數據到串口輸出。此命令可以采取多種形式。每個數字的打印輸出使用的是ASCII字符。浮點型同樣打印輸出的是ASCII字符,保留到小數點后兩位。Bytes型則打印輸出單個字符。字符和字符串原樣打印輸出。Serial.print()打印輸出數據不換行,Serial.println()打印輸出數據自動換行處理。例如
Serial.print(78)輸出為“78”
Serial.print(1.23456)輸出為“1.23”
Serial.print(“N”)輸出為“N”
Serial.print(“Hello world.”)輸出為“Hello world.”
也可以自己定義輸出為幾進制(格式);可以是BIN(二進制,或以2為基數),OCT(八進制,或以8為基數),DEC(十進制,或以10為基數),HEX(十六進制,或以16為基數)。對於浮點型數字,可以指定輸出的小數數位。例如
Serial.print(78,BIN)輸出為“1001110”
Serial.print(78,OCT)輸出為“116”
Serial.print(78,DEC)輸出為“78”
Serial.print(78,HEX)輸出為“4E”
Serial.println(1.23456,0)輸出為“1”
Serial.println(1.23456,2)輸出為“1.23”
Serial.println(1.23456,4)輸出為“1.2346”
你可以通過基於閃存的字符串來進行打印輸出,將數據放入F()中,再放入Serial.print()。例如 Serial.print(F(“Hello world”)) 若要發送一個字節,則使用 Serial.write()。
語法
Serial.print(val)
Serial.print(val,格式)
參數
val:打印輸出的值 - 任何數據類型
格式:指定進制(整數數據類型)或小數位數(浮點類型)
返回
字節 print()將返回寫入的字節數,但是否使用(或讀出)這個數字是可設定的
例子
/ *
使用for循環打印一個數字的各種格式。
* /
int x = 0; // 定義一個變量並賦值
void setup() {
Serial.begin(9600); // 打開串口傳輸,並設置波特率為9600
}
void loop() {
/ /打印標簽
Serial.print("NO FORMAT"); // 打印一個標簽
Serial.print("\t"); // 打印一個轉義字符
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++){ // 打印ASCII碼表的一部分, 修改它的格式得到需要的內容
/ /打印多種格式:
Serial.print(x); // 以十進制格式將x打印輸出 - 與 "DEC"相同
Serial.print("\t"); // 橫向跳格
Serial.print(x, DEC); // 以十進制格式將x打印輸出
Serial.print("\t"); // 橫向跳格
Serial.print(x, HEX); // 以十六進制格式打印輸出
Serial.print("\t"); // 橫向跳格
Serial.print(x, OCT); // 以八進制格式打印輸出
Serial.print("\t"); // 橫向跳格
Serial.println(x, BIN); // 以二進制格式打印輸出
//然后用 "println"打印一個回車
delay(200); // 延時200ms
}
Serial.println(""); // 打印一個空字符,並自動換行
}
編程技巧 作為1.0版本,串行傳輸是異步的; Serial.print()將返回之前接收到的任何字符。
25.1.12 Serial.println()
說明
打印數據到串行端口,輸出人們可識別的ASCII碼文本並回車 (ASCII 13, 或 '\r') 及換行(ASCII 10, 或 '\n')。此命令采用的形式與Serial.print ()相同 。
語法
Serial.println(val)
Serial.println(val, format)
參數
val: 打印的內容 - 任何數據類型都可以
format: 指定基數(整數數據類型)或小數位數(浮點類型)
返回
字節(byte)
println()將返回寫入的字節數,但可以選擇是否使用它。
例子
/*
模擬輸入信號
讀取模擬口0的模擬輸入,打印輸出讀取的值。
由 Tom Igoe創建於2006年3月24日
*/
int analogValue = 0; // 定義一個變量來保存模擬值
void setup() {
//設置串口波特率為9600 bps:
Serial.begin(9600);
}
void loop() {
analogValue = analogRead(0); //讀取引腳0的模擬輸入:
//打印g各種格式:
Serial.println(analogValue); //打印ASCII編碼的十進制
Serial.println(analogValue, DEC); //打印ASCII編碼的十進制
Serial.println(analogValue, HEX); //打印ASCII編碼的十六進制
Serial.println(analogValue, OCT); //打印ASCII編碼的八進制
Serial.println(analogValue, BIN); //打印一個ASCII編碼的二進制
delay(10); // 延時10毫秒:
}
25.1.13 Serial.read()
說明
讀取傳入的串口的數據。read() 繼承自 Stream 類。
語法
serial.read()
Arduino Mega獨有:
serial1.read()
serial2.read()
serial3.read()
參數
無
返回
傳入的串口數據的第一個字節(或-1,如果沒有可用的數據)- int
例子
int incomingByte = 0; // 傳入的串行數據
void setup() {
Serial.begin(9600); // 打開串口,設置數據傳輸速率9600
}
void loop() {
// 當你接收數據時發送數據
if (Serial.available() > 0) {
// 讀取傳入的數據:
incomingByte = Serial.read();
//打印你得到的:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
25.1.14 Serial.readBytes()
說明
Serial.readBytes()從串口讀字符到一個緩沖區。如果預設的長度讀取完畢或者時間到了 (參見 Serial.setTimeout()),函數將終止.
Serial.readBytes()返回放置在緩沖區的字符數。返回0意味着沒有發現有效的數據。
Serial.readBytes()繼承自 Stream 類.
語法
Serial.readBytes(buffer, length)
參數
buffer:用來存儲字節(char[]或byte[])的緩沖區
length:讀取的字節數(int)
返回
byte
25.1.15 Serial.readBytesUntil()
說明
Serial.readBytesUntil()將字符從串行緩沖區讀取到一個數組。如果檢測到終止字符,或預設的讀取長度讀取完畢,或者時間到了 (參見 Serial.setTimeout())函數將終止。
Serial.readBytesUntil()返回讀入數組的字符數。返回0意味着沒有發現有效的數據。
Serial.readBytesUntil()繼承自 Stream類。
語法
Serial.readBytesUntil(character, buffer, length)
參數
character :要搜索的字符(char)
buffer :緩沖區來存儲字節(char[]或byte[])
length:讀的字節數(int)
返回
byte
25.1.16 Serial.setTimeout()
說明
Serial.setTimeout()設置使用Serial.readBytesUntil() 或Serial.readBytes()時等待串口數據的最大毫秒值. 默認為1000毫秒。
Serial.setTimeout()繼承自Stream 類。
語法
Serial.setTimeout(time)
參數
time :以毫秒為單位的超時時間(long)。
返回
無
25.1.17 Serial.write()
說明
寫入二級制數據到串口。發送的數據以一個字節或者一系列的字節為單位。如果寫入的數字為字符,需使用print()命令進行代替。
語法
Serial.write(val)
Serial.write(str)
Serial.write(buf, len)
Arduino Mega還支持:Serial1,Serial2,Serial3 (替代Serial)
參數
val: 以單個字節形式發的值
str: 以一串字節的形式發送的字符串
buf: 以一串字節的形式發送的數組
len: 數組的長度
返回
byte
write() 將返回寫入的字節數,但是否使用這個數字是可選的
例子
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.write(45); // 發送一個值為45的字節
int bytesSent = Serial.write(“hello”); //發送字符串“hello”,返回該字符串的長度.
}
25.1.18 Serial.SerialEvent()
暫無說明。
25.2 Stream
暫無說明。
二十六、USB(僅適用於 Leonardo 和 Due)
26.1 Mouse(鍵盤)
Mouse.begin()
Mouse.click()
Mouse.end()
Mouse.move()
Mouse.press()
Mouse.release()
Mouse.isPressed()
26.2 Keyboard(鼠標)
Keyboard.begin()
Keyboard.end()
Keyboard.press()
Keyboard.print()
Keyboard.println()
Keyboard.release()
Keyboard.releaseAll()
Keyboard.write()