串口波特率的設置:通常我們使用Serial.begin(speed)來完成串口的初始化,這種方式,只能配置串口的波特率。
使用Serial.begin(speed, config)可以配置數據位、校驗位、停止位等。例如Serial.begin(9600,SERIAL_8E2)是將串口波特率設為9600,數據位8,偶校驗,停止位2。
9600 串口波特率
SERIAL_8E2
8:8位
E:偶校驗
2:停止位
config可用配置如下:
1: 少用 if (Serial)的用法:串口打開為真,串口關閉為假。比較囧的是,這個方法只適用於Leonardo和micro的 Serial,也就是說連接連接到電腦USB的那個模擬串口。例如以下程序,當你沒有使用串口監視器打開串口時,程序就會一直循環運行while (!Serial) {;} ,當你打開串口監視器,程序會退出while循環,開始loop中的程序。
2: read和peek輸入方式的差異 串口接收到的數據都會暫時存放在接收緩沖區中,使用read()與peek()都是從接收緩沖區中讀取數據。不同的是: 使用read()讀取數據后,會將該數據從接收緩沖區移除; 使用peek()讀取時,不會移除接收緩沖區中的數據。
3: 串口讀入int型數據 實際上是串口讀入字符串,再轉換為int型數據。 輸出不同進制的文本 可以是用 Serial.print(val, format)的形式輸出不同進制的文本 。 參數val 是需要輸出的數據 參數format 是需要輸出的進制形式,可以使用如下參數: BIN(二進制) DEC(十進制) OCT(八進制) HEX(十六進制) 例如,使用Serial.print(123,BIN),你可以在串口調試器上看到1111011 使用Serial.print(123,HEX),你可以在串口調試器上看到7B 。 4: 修改串口緩沖區大小: Arduino串口緩沖區默認為64字節,如果單次傳輸的數據較多可以將arduino-1.0.5r2\hardware\arduino\cores\arduino\HardwareSerial.cpp中的 #define SERIAL_BUFFER_SIZE 64 修改為 #define SERIAL_BUFFER_SIZE 128 這樣就有128字節的緩沖區了 Arduino MEGA\Arduino DUE上其他串口用法: serial1\serial2\serial3和serial用法一樣,比如serial3.begin(9600);
重要之處: 經典的Processing與Arduino通信實例: 使用Serial.available()檢測:
import processing.serial.*; Serial myPort; void setup(){ myPort = new Serial(this,"/dev/ttyACM0", 115200); //Set Serial Port } void draw(){ if(myPort.available()>0){ String message = myPort.readString(); println(message); } } //Arduino code int data=12345; void setup() { Serial.begin(115200);//rate } void loop() { Serial.print(data); //send data delay(1000); } 然后我們期待着每次獲取“12345”並顯示在屏幕上,但事與願違,我們得到的情況是這樣的: 12345 123 45 12345 12345 輸出時的中斷是怎樣產生的呢?要探究這個問題的根源,需要重新審視 ***串口通信的原理**。* ******************** 串口通訊就像一趟公共汽車,每個字節是一個在等車的人。他來到車站(發送數據),車還沒有來,所以新來的人就一直等待(緩存)。當公共汽車來了的時候,將這些人一次接走(讀取數據),當然車也是有容量的,只能載一定數量的人(緩存大小)。現在有一個旅行團(字符串/字符數組),一部分人走在前面剛剛趕上了車(被讀取),而另一部分人沒趕上,只能等待下一班車(下一次讀取)。另一種情況是,兩個旅行團都在車站等車,被同一班車接走了。這就是為什么我們讀取的時候字符串會斷成兩節,或者並起來。 核心原因是:串口流通的數據都是bytes而沒有字符串概念,所有發送數據都會按一個byte一個byte緩存,不論是否是連續字符串;而讀取時會取走所有緩存bytes,不論它們是否是一個、半個還是多個字符串。 ** ---------- ** Arduino和Processing的數據收發速度是不一樣的。如果用Arduino延時較長時間,Processing可能讀取一個字符串或字符串的一部分。如果Arduino延時較短,Processing可能讀取多個字符串,但不一定完整。在讀取字符串的時候,無法確定上一個字符串是否被讀取了,當前字符串是否緩存完畢,因為字符串都已經切成了bytes,連成一串。這個問題是串口通信本身造成的,一定會出現。 ** ---------- ** ---------- ---------- 一種解決方法是,通過在接收端緩存數據來解決這個問題。 為傳輸數據設置一個結束標記,如’\n’(換行符),就能在接收到的數據流中識別到一個字符串的結尾。當未遇到結束標記,就一直將串口數據保存在一個buffer變量中,繼續接收。 Processing的SerialEvent事件類型就提供了這種方式,使用bufferUntil(ch)可以在遇到某個指定字符時才完成緩存。 ---------- ---------- 程序實例: //Processing Code import processing.serial.*; Serial myPort; void setup(){ myPort = new Serial(this,"/dev/ttyACM0", 115200); //in fact, any rate is ok... myPort.bufferUntil('\n'); //buffer until meet '\n', then call the event listener } void draw(){ } //listen to the event. when buffer filled, run this method void serialEvent(Serial p) { String inString = p.readString(); print(inString); } //then the buffer will reveive all the bytes //Arduino Code int data=12345; void setup() { Serial.begin(115200);//rate } void loop() { Serial.println(data); //send data, end up with '\n' delay(1000); } 當然,這種方法也可以用在普通的串口通信中,不必使用SerialEvent。接收的數據不直接使用,而是作為緩存。若未遇到結束標記,就繼續讀取下一次。當遇到結束標記,即完成緩存。 ---------- ---------- ---------- 程序實例: //Processing Code import processing.serial.*; String message; String temp; Serial myPort; void setup(){ myPort = new Serial(this,"/dev/ttyACM0", 115200); //Set Serial Port } void draw(){ if(myPort.available()>0){ temp = myPort.readString(); //temp for read bytes for(int i = 0; i < temp.length(); i++){ //if meet the end mark if(temp.charAt(i) == '\n'){ println(message); message = ""; //clean string } else message += temp.charAt(i); //store byte } } } //Arduino Code int data=12345; void setup() { Serial.begin(115200);//rate } void loop() { Serial.println(data); //send data, end up with '\n' delay(1000); }