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