|
用慣Arduino串口傳輸?shù)呐笥讯贾,Arduino的Serial.read()每次只能讀一個(gè)字節(jié),但是有時(shí)想進(jìn)行字符串通訊,就很麻煩了。
廢話少講,直接上完整例子:
編譯只要一塊Arduino,不需要任何外置元件。
用Arduino編譯器的串口監(jiān)視器即可看到結(jié)果,我們打什么文字進(jìn)去,下面就會(huì)返回什么文字
String comdata = "";
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available() > 0)
{
comdata += char(Serial.read());
delay(2);
}
if (comdata.length() > 0)
{
Serial.println(comdata);
comdata = "";
}
}
代碼很簡(jiǎn)單,comdata是一個(gè)字符串類型變量。Serial.available()是當(dāng)前串口緩沖池的數(shù)據(jù)量。Serial.read()是讀緩沖池的語(yǔ)句,每次只能讀一個(gè)字節(jié)。
用了String類型變量,很簡(jiǎn)單的實(shí)現(xiàn)了字符到字符串的加入,還有字符串輸出,賦值等麻煩問(wèn)題,所以很簡(jiǎn)單的代碼就能處理串口數(shù)據(jù)。
特別留意的是讀串口時(shí)的delay(2)不能刪掉,否則串口緩沖區(qū)不夠時(shí)間接受數(shù)據(jù)。即使調(diào)小延時(shí)也會(huì)出錯(cuò)。具體數(shù)值也可以實(shí)驗(yàn)決定。
再提醒一個(gè):comdata說(shuō)是一個(gè)字符串,也是一個(gè)數(shù)組,引用每個(gè)字的話可以用comdata[0],comdata[1]。。。comdata[n]。如果我們要每個(gè)字節(jié)取出的話,可以每個(gè)引用。
效果:輸入什么字符串,輸出就是什么。
輸入:
按send之后:
再附送一個(gè)例子,在串口輸入1011101..的話,就會(huì)令A(yù)rduino的D2~Dx引腳產(chǎn)生高/低電平,當(dāng)然,一次發(fā)送的數(shù)據(jù)視Arduino引腳數(shù)而定,比如Arduino UNO/nano之類的,只有D2~D13十二個(gè)引腳。我們打12個(gè)數(shù)字就好。比如101101011010,如果中間有非0和1的字符,則自動(dòng)跳過(guò)該位設(shè)置:比如122202221222這樣。因?yàn)?不是允許范圍內(nèi),就只設(shè)置D2/D6/D10的值了:String comdata = "";
void setup()
{
Serial.begin(9600);
for(int i = 2; i <= 13; i++) pinMode(i, OUTPUT);
}
void loop()
{
while (Serial.available() > 0)
{
comdata += int(Serial.read()) - '0';
delay(2);
}
if(comdata.length() > 0)
{
for(int i = 0; i < comdata.length(); i++)
{
if(comdata[i]=='0'||comdata[i]=='1')
{
digitalWrite(i + 2, comdata[i] - '0');
Serial.print("Pin ");
Serial.print(i + 2);
Serial.print(" is ");
Serial.println(comdata[i]);
}
}
comdata = "";
}
}
再來(lái)一個(gè):進(jìn)階版(有待測(cè)試)
輸入六個(gè)逗號(hào)分隔數(shù)比如:50,20,5,255,20,20
就能令A(yù)rduino的PWM引腳(3,5,6,9,10,11):按照PWM值發(fā)光。所以逗號(hào)分割數(shù)必須是0~255
String comdata = "";
int numdata[6] = {0}, PWMPin[6] = {3, 5, 6, 9, 10, 11}, mark = 0;
void setup()
{
for(int i = 0; i < 6; i++) pinMode(PWMPin[i], OUTPUT);
Serial.begin(9600);
}
void loop()
{
int j = 0;
while (Serial.available() > 0)
{
comdata += char(Serial.read());
delay(2);
mark = 1;
}
if(mark == 1)
{
Serial.println(comdata);
Serial.println(comdata.length());
for(int i = 0; i < comdata.length() ; i++)
{
if(comdata[i] == ',')
{
j++;
}
else
{
numdata[j] = numdata[j] * 10 + (comdata[i] - '0');
}
}
comdata = String("");
for(int i = 0; i < 6; i++)
{
Serial.print("Pin ");
Serial.print(PWMPin[i]);
Serial.print(" = ");
Serial.println(numdata[i]);
analogWrite(PWMPin[i], numdata[i]);
numdata[i] = 0;
}
mark = 0;
}
}
(補(bǔ)充) - 在串口讀取多個(gè)字符串,并且轉(zhuǎn)換為數(shù)字?jǐn)?shù)組
功能如題目。
在串口收到逗號(hào)分割的6串?dāng)?shù)字比如
100,200,45,4,87,99
然后在6個(gè)PWM端口3, 5, 6, 9, 10, 11輸出對(duì)應(yīng)PWM值
代碼注釋很詳細(xì)了,就不再說(shuō)明了。
- //定義一個(gè)comdata字符串變量,賦初值為空值
- String comdata = "";
- //numdata是分拆之后的數(shù)字?jǐn)?shù)組
- int numdata[6] = {0}, PWMPin[6] = {3, 5, 6, 9, 10, 11}, mark = 0;
- void setup()
- {
- //定義0~6腳是輸出
- for(int i = 0; i < 6; i++) pinMode(PWMPin[i], OUTPUT);
- Serial.begin(9600);
- }
-
- void loop()
- {
- //j是分拆之后數(shù)字?jǐn)?shù)組的位置記數(shù)
- int j = 0;
-
- //不斷循環(huán)檢測(cè)串口緩存,一個(gè)個(gè)讀入字符串,
- while (Serial.available() > 0)
- {
- //讀入之后將字符串,串接到comdata上面。
- comdata += char(Serial.read());
- //延時(shí)一會(huì),讓串口緩存準(zhǔn)備好下一個(gè)數(shù)字,不延時(shí)會(huì)導(dǎo)致數(shù)據(jù)丟失,
- delay(2);
- //標(biāo)記串口讀過(guò)數(shù)據(jù),如果沒(méi)有數(shù)據(jù)的話,直接不執(zhí)行這個(gè)while了。
- mark = 1;
- }
-
- if(mark == 1) //如果接收到數(shù)據(jù)則執(zhí)行comdata分析操作,否則什么都不做。
- {
- //顯示剛才輸入的字符串(可選語(yǔ)句)
- Serial.println(comdata);
- //顯示剛才輸入的字符串長(zhǎng)度(可選語(yǔ)句)
- Serial.println(comdata.length());
-
- /*******************下面是重點(diǎn)*******************/
- //以串口讀取字符串長(zhǎng)度循環(huán),
- for(int i = 0; i < comdata.length() ; i++)
- {
- //逐個(gè)分析comdata[i]字符串的文字,如果碰到文字是分隔符(這里選擇逗號(hào)分割)則將結(jié)果數(shù)組位置下移一位
- //即比如11,22,33,55開始的11記到numdata[0];碰到逗號(hào)就j等于1了,
- //再轉(zhuǎn)換就轉(zhuǎn)換到numdata[1];再碰到逗號(hào)就記到numdata[2];以此類推,直到字符串結(jié)束
- if(comdata[i] == ',')
- {
- j++;
- }
- else
- {
- //如果沒(méi)有逗號(hào)的話,就將讀到的數(shù)字*10加上以前讀入的數(shù)字,
- //并且(comdata[i] - '0')就是將字符'0'的ASCII碼轉(zhuǎn)換成數(shù)字0(下面不再敘述此問(wèn)題,直接視作數(shù)字0)。
- //比如輸入數(shù)字是12345,有5次沒(méi)有碰到逗號(hào)的機(jī)會(huì),就會(huì)執(zhí)行5次此語(yǔ)句。
- //因?yàn)樽筮叺臄?shù)字先獲取到,并且numdata[0]等于0,
- //所以第一次循環(huán)是numdata[0] = 0*10+1 = 1
- //第二次numdata[0]等于1,循環(huán)是numdata[0] = 1*10+2 = 12
- //第三次是numdata[0]等于12,循環(huán)是numdata[0] = 12*10+3 = 123
- //第四次是numdata[0]等于123,循環(huán)是numdata[0] = 123*10+4 = 1234
- //如此類推,字符串將被變成數(shù)字0。
- numdata[j] = numdata[j] * 10 + (comdata[i] - '0');
- }
- }
- //comdata的字符串已經(jīng)全部轉(zhuǎn)換到numdata了,清空comdata以便下一次使用,
- //如果不請(qǐng)空的話,本次結(jié)果極有可能干擾下一次。
- comdata = String("");
-
-
- //循環(huán)輸出numdata的內(nèi)容,并且寫到PWM引腳
- for(int i = 0; i < 6; i++)
- {
- Serial.print("Pin ");
- Serial.print(PWMPin[i]);
- Serial.print(" = ");
- Serial.println(numdata[i]);
- analogWrite(PWMPin[i], numdata[i]);
- numdata[i] = 0;
- }
- //輸出之后必須將讀到數(shù)據(jù)的mark置0,不置0下次循環(huán)就不能使用了。
- mark = 0;
- }
- }
復(fù)制代碼
|
|