電子工程系車用電子與資訊組
Arduino序列通訊
吳錫修
sswu@nkut.edu.tw
Revised on July 6, 2018
UART傳輸協定、RS232標準、Serial程式庫、
使用Serial Monitor顯示狀態,序列傳輸命令控制LED
Makeeachdaycount
 資料是1個bit接著1個bit傳送
 每個資料封包 (package) 由起始位元、資料位元、檢查位元及結束位
元組成
 在開始傳輸資料之前,Tx與Rx接腳都為⾼電位,要傳送資料時,先送出⼀
個代表「要開始傳送的通知」的起始位元 (start bit,低電位)
 每組資料位元 (data bits) ⻑度可以是5~8位元
 資料位元之後可以送出⼀個檢查位元
 無 (None)
不加檢查位元
非同步序列傳輸協定 1/3
2
Makeeachdaycount
 奇同位 (Odd)
當資料位元有偶數個1時,則檢查位元為1,補成奇數;資料位元有奇數個1時,
則檢查位元為0,維持奇數
 偶同位 (Even)
當資料位元有奇數個1時,則檢查位元為1,補成偶數;資料位元有偶數個1時,
則檢查位元為0,維持偶數
 標記 (Mark)
檢查位元始終為1
 空格 (Space)
檢查位元始終為0
 封包最後是代表「傳送完畢」的停止位元 (stop bit),1~2位元
非同步序列傳輸協定 2/3
3
Makeeachdaycount
 傳輸協定 (protocol) 代表通訊裝置雙方所遵循的規範和參數,通訊雙
方的設定必須⼀致,才能相互溝通
 送收雙方須議定傳輸速率及封包格式
 傳輸速率:每秒傳送的位元數 (bit per second,bps),也稱為鮑率 (baud
rate)
 取樣
 通常是以鮑率的 16 倍頻⼯作,並在中⼼點附近取樣三次,三次結果⼀致
才視為正確
非同步序列傳輸協定 3/3
4
Makeeachdaycount
 RS232C是最早廣泛使用之序列埠標準,傳輸距離約15m。
 在USB普及之前,許多周邊裝置 (滑鼠、搖桿、條碼機、數據機…) 都
採用RS-232C介面
 ⼀般使用DB-9端子,其中RXD、TXD及GND為最重要接腳
 數據傳送 (Transmitter,Tx)
 數據接收 (Receiver,Rx)
 接地 (Ground,GND)
RS232標準 1/2
5
DB-9公端子
Makeeachdaycount
 RS232電氣訊號為負邏輯
 3V~15V表示0 (Space)
 -3V~-15V表示1 (Mark)
 TTL電氣訊號為正邏輯
 0.8V以下為0
 2.0V以上為1
 Arduino與RS232設備間需加裝訊號轉換元件 (如MAX232)
RS232標準 2/2
6
Makeeachdaycount
 序列埠監控視窗是⼀個透過序列埠和Arduino微控制器溝通的⼯具程式
 選單命令Tools>Serial Monitor
Serial Monitor
7
顥示接收到的訊息
傳輸速率
在此輸入要傳送之訊息 傳送
Makeeachdaycount
 Arduino IDE內建處理序列傳輸的Serial程式庫
 Serial.begin(speed)
Serial.begin(speed, config)
 設定序列傳輸速率,使用預設8n1傳輸格式
 傳輸格式常數:
SERIAL_5N1、SERIAL_6N1、SERIAL_7N1、SERIAL_8N1 (預設值)、SERIAL_5N2、
SERIAL_6N2、SERIAL_7N2、SERIAL_8N2、SERIAL_5E1、SERIAL_6E1、
SERIAL_7E1、SERIAL_8E1、SERIAL_5E2、SERIAL_6E2、SERIAL_7E2、
SERIAL_8E2、SERIAL_5O1、SERIAL_6O1、SERIAL_7O1、SERIAL_8O1、
SERIAL_5O2、SERIAL_6O2、SERIAL_7O2、SERIAL_8O2
Serial.begin(9600); //設定使用9600bps,8n1傳輸格式
使用Serial程式庫 1/8
8
Makeeachdaycount
 Serial.end()
 停用序列傳輸功能,允許RX和TX接腳做為通用輸入和輸出。調用
Serial.begin()可重新啟用序列傳輸
 Serial.available()
 傳回序列接收緩衝區 (64 bytes) 中已收到的位元組數
 Serial.availableForWrite()
 傳回還可寫入到序列緩衝區的位元組數
 Serial.find (target_string)
 從序列緩衝區讀取資料,直到找到指定字串。 如果找到指定字串,則傳回
true,如果逾時則傳回false
Serial.find("ON");
使用Serial程式庫 2/8
9
Makeeachdaycount
 Serial.findUntil(target, terminal)
 從序列緩衝區讀取資料,直到找到指定字串或終止字串
Serial.findUntil("ON","#");
 Serial.flush()
 等待序列緩衝區資料傳送完畢
 Serial.parseFloat()
 解析序列緩衝區資料並回傳第⼀個有效的浮點數值。非數字或減號的字元
會被略過,都找不到時回傳0.00
 Serial.parseFloat()
 解析序列緩衝區資料並回傳第⼀個有效的整數值。非數字或減號的字元會
被略過,都找不到時回傳0
使用Serial程式庫 3/8
10
Makeeachdaycount
 Serial.peek()
 讀取序列緩衝區的第⼀個字元,但並不將其從緩衝區中移除。若序列緩衝
區無資料則回傳-1
 Serial.read()
 取出序列緩衝區的第⼀個字元。若序列緩衝區無資料則回傳-1
 Serial.readBytes (buffer, length)
 從序列埠讀取資料儲存到緩衝區 (字元陣列),若已達指定資料⻑度或超時,
該函數終止
 buffer用來儲存資料之緩衝區 (char[] or byte[])
char buffer[20];
int size = Serial.readBytes(buffer, 20);
buffer[size]='0';
Serial.println(buffer);
使用Serial程式庫 4/8
11
Makeeachdaycount
 Serial.readBytesUntil(character, buffer, length)
 從序列埠讀取資料,直到檢測到終止字元或指定位元組數資料已被讀取或
逾時。終止字元並不會儲存到緩衝區
char buffer[20];
if (int size=Serial.readBytesUntil('#', buffer, 20)) {
buffer[size]='0';
Serial.println(buffer);
}
 Serial.readString()
 將序列緩衝區中的資料讀入字串
if (Serial.available()){
String buffer = Serial.readString();
Serial.println(buffer);
}
使用Serial程式庫 5/8
12
Makeeachdaycount
 Serial.readStringUntil(terminator)
 將序列緩衝區中的資料讀入字串,直到終止字元或逾時
if (Serial.available()){
String cmd = Serial.readStringUntil('#');
Serial.println(cmd);
}
 Serial.setTimeout(milliseconds)
 設定讀取序列資料逾時時間,預設為1000毫秒
使用Serial程式庫 6/8
13
Makeeachdaycount
 Serial.print(val)
Serial.print(val, format)
 將數據作為方便閱讀的文字輸出到序列埠。整數資料可以指定格式,BIN
表示2進制,OCT表示8進制,DEC表示10進制,HEX表示16進制; 浮號
數資料可以指定小數點位數,預設為小數點後兩位
Serial.print(78); //輸出"78"
Serial.print(1.23456); //輸出"1.23"
Serial.print('N'); //輸出"N"
Serial.print("Hello world."); //輸出"Hello world."
Serial.print(78, BIN); //輸出"1001110"
Serial.print(78, OCT); //輸出"116"
Serial.print(78, HEX); //輸出"4E"
Serial.print(1.23456, 0); //輸出"1"
使用Serial程式庫 7/8
14
Makeeachdaycount
 Serial.println(val)
Serial.println(val, format)
 功能如Serial.print()函式,但會在資料後加上回車字元 (ASCII 13, or 'r')
及換行字元 (ASCII 10, or 'n')
 Serial.write(val)
Serial.write(str)
Serial.write(buf, len)
 將二進制數值寫入序列埠。 這些數據以位元組或⼀系列位元組形式發送
Serial.write(45); //輸出'-'
Serial.write("Hello"); //輸出'H','e','l','l','o'
使用Serial程式庫 8/8
15
Makeeachdaycount
 實驗目的
 使用Serial Monitor監控開關狀態
 當開關被壓放時,在序列埠監控視窗顯示訊息
Lab 序列埠監控視窗顯示開關狀態 1/3
16
Makeeachdaycount
 參考程式
#define SW = 2
boolean lastState = HIGH;
byte click = 0;
void setup() {
pinMode(SW, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("start serial communication");
}
Lab 序列埠監控視窗顯示開關狀態 2/3
17
Makeeachdaycount
void loop() {
boolean b1 = digitalRead(SW); //讀取開關目前狀態
if (b1 != lastState) { //開關狀態改變
delay(20);
boolean b2 = digitalRead(SW);
if (b1 == b2) {
lastState = b1;
click++;
}
}
if (click == 2){ //已壓放⼀次開關
click = 0;
Serial.println("SW was clicked");
}
}
Lab 序列埠監控視窗顯示開關狀態 3/3
18
Makeeachdaycount
 實驗目的
 使用序列埠字元命令控制LED
 從Serial Monitor送出1時,點亮LED;送出0時,熄滅LED
Lab 使用序列埠字元命令控制LED 1/3
19
Makeeachdaycount
 參考程式
#define LED = 3
void setup() {
pinMode(LED, OUTPUT);
Serial.begin(9600);
Serial.println("start serial communication");
}
Lab 使用序列字元命令控制LED 2/3
20
Makeeachdaycount
void loop() {
if (Serial.available()){
byte cmd = Serial.read();
if (cmd == '1') { //從序列埠收到'1'
digitalWrite(LED, HIGH);
Serial.println("Turn LED on");
}
if (cmd == '0') { //從序列埠收到'0'
digitalWrite(LED, LOW);
Serial.println("Turn LED off");
}
}
}
Lab 使用序列字元命令控制LED 3/3
21
Makeeachdaycount
 實驗目的
 使用序列埠字元命令控制LED
 從Serial Monitor送出"ON"時,點亮LED;送出"OFF"時,熄滅LED
Lab 使用序列字串命令控制LED 1/3
22
Makeeachdaycount
 參考程式
#define LED = 3
void setup() {
pinMode(LED, OUTPUT);
Serial.begin(9600);
Serial.println("start serial communication");
}
Lab 使用序列字串命令控制LED 2/3
23
Makeeachdaycount
void loop() {
if (Serial.available()){
String cmd = Serial.readString();
if (cmd == "ON") { //從序列埠收到"ON"
digitalWrite(LED, HIGH);
Serial.println("Turn LED on");
}
if (cmd == "OFF") { //從序列埠收到"OFF"
digitalWrite(LED, LOW);
Serial.println("Turn LED off");
}
}
}
Lab 使用序列字串命令控制LED 3/3
24

Arduino序列通訊