Arduino 串行通讯
本文翻译自 Arduino 串行通讯的官方文档。
本文的最新版本位于:https://github.com/iwhales/arduino_notes
转载请注明出处:https://www.jianshu.com/u/5e6f798c903a
1. 简介
Arduino 板卡使用 Serial 与电脑或其它设备进行通讯。所有 Arduino 板卡至少拥有一个串行端口(也称URAT 或USART):Serial。Serial 工作于数字引脚 0 (RX) 和 1 (TX) ,同时也通过 USB 与电脑通讯。因此,如果需要使用 Serial 功能,便不能同时将引脚 0 和 1 用作数字输入和输出。 我们可以通过 Arduino IDE 内置的串口监视器与 Arduino 板卡进行通讯。在 IDE 的工具栏中点击串口监视器的图标,并将波特率设置为 begin()
的实参值,便可与 Arduino 进行串口通讯。
位于 TX/RX 引脚上的串行通讯采用 TTL 电平(根据电路板的设计方式,可能采用 5V 或 3.3V)。请勿将 TX/RX 引脚直接连接到 RS232 串行端口;RS232 的工作电压是 +/- 12V,可能会对 Arduino 造成损坏。
Arduino Mega 拥有三个额外的串行端口: Serial1 位于 19 (RX) 和 18 (TX) 引脚;Serial2 位于 17 (RX) 和 16 (TX) 引脚;Serial3 位于 15 (RX) 和 14 (TX) 引脚。如果想使用这些引脚与 PC 进行通讯,则需要自行提供 USB-to-serial 适配器 —— 因为这些额外的串行端口并没有被连接到 Mega 自带的 USB-to-serial 适配器上。如果想要通过这些额外的串行端口与外部 TTL 串行设备进行通讯,那么需要将外部设备的 TX 和 RX 引脚分别连接至 Mega 的 RX 和 TX 引脚,同时将 Mega 的地线与外部设备的地线直接相连。
Arduino Due 拥有三个额外的 3.3V TTL 串行端口:Serial1 位于 19 (RX) 和 18 (TX) 引脚;Serial2 位于 17 (RX) 和 16 (TX) 引脚;Serial3 位于 15 (RX) 和 14 (TX) 引脚。引脚 0 和 1 同样也被连接到了 ATmega16U2 USB-to-TTL 串口芯片的对应引脚,用于连接 USB 调试端口。此外,SAM3X 芯片还拥有一个原生 USB-serial 端口——SerialUSB' 。
Arduino Leonardo 在引脚 0 (RX) 和 1 (TX) 上使用 Serial1 进行通讯,Serial1 也是 5V TTL。Serial 用作 USB CDC 通讯。欲了解更多信息,请参阅 Leonardo 的相关页面。
2. 函数
if (Serial)
-
描述
用于指示指定的串口是否已准备就绪。 在 Leonardo 上,
if(Serial)
用于指示 USB CDC 串行连接是否开放。对于所有其他情况,包括 Leonardo 的if (Serial1)
,将始终返回true
。 -
语法
All boards:
if (Serial)
Arduino Leonardo specific:
if (Serial1)
Arduino Mega specific:
if (Serial1)
if (Serial2)
if (Serial3)
-
参数
Nothing
-
返回值
boolean
:如果指定串口可用,将返回true
。仅在 Leonardo 的 USB CDC 串行连接准备好之前进行查询时,会返回false
。 -
示例代码
void setup() { //初始化串行端口,并等待端口开启: Serial.begin(9600); while (!Serial) { ; // 等待串口连接。需要原生USB } } void loop() { //proceed normally }
Serial.available()
-
描述
获取可以从串行端口读取的可用字节(字符)数。该数据表示已经到达并存储在串行接受缓冲区中的字节数——接受缓冲区可存储 64 字节的数据。
available()
继承自 Stream utility class。 -
语法
Serial.available()
Arduino Mega only:
Serial1.available()
Serial2.available()
Serial3.available()
-
参数
Nothing
-
返回值
返回可供读取的字节数
-
示例代码
以下代码将返回通过串口接受的字符
int incomingByte = 0; // for incoming serial data void setup() { Serial.begin(9600); // opens serial port, sets data rate to 9600 bps } void loop() { // reply only when you receive data: if (Serial.available() > 0) { // read the incoming byte: incomingByte = Serial.read(); // say what you got: Serial.print("I received: "); Serial.println(incomingByte, DEC); } }
Arduino Mega 的示例:该代码可以将从 Arduino Mega 的某个串口接受到的数据发送到另一个串口。利用这段代码可将串行设备通过 Arduino 连接到电脑。
void setup() { Serial.begin(9600); Serial1.begin(9600); } void loop() { // read from port 0, send to port 1: if (Serial.available()) { int inByte = Serial.read(); Serial1.print(inByte, DEC); } // read from port 1, send to port 0: if (Serial1.available()) { int inByte = Serial1.read(); Serial.print(inByte, DEC); } }
Serial.availableForWrite()
-
描述
获取可用于写入串行缓冲区的字节(字符)数,并且不会阻塞写入操作。
-
语法
Serial.availableForWrite()
Arduino Mega only:
Serial1.availableForWrite()
Serial2.availableForWrite()
Serial3.availableForWrite()
-
参数
Nothing
-
返回值
可用于写操作的字节数
Serial.begin()
-
描述
设置串行数据传输的速率,单位是 bits/秒 (baud 波特)。与计算机进行通讯时,可使用以下速率中的一个:300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200。当然,你可以指定其它速率 —— 例如,通过引脚 0 和 1 连接一个需求特定波特率的元件时。
可选的第二参数用于配置数据位数、奇偶校验和停止位。默认是 8 数据位、无奇偶校验、1 位停止位。
-
语法
Serial.begin(speed)
Serial.begin(speed, config)
Arduino Mega only:
Serial1.begin(speed)
Serial2.begin(speed)
Serial3.begin(speed)
Serial1.begin(speed, config)``Serial2.begin(speed, config)
Serial3.begin(speed, config)
-
参数
speed
: bits/秒 (baud) -long
config
: 设置数据位数、奇偶校验和停止位。 有效值如下SERIAL_5N1
SERIAL_6N1
SERIAL_7N1
SERIAL_8N1
(the default)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
-
返回值
Nothing
-
示例代码
void setup() { Serial.begin(9600); // opens serial port, sets data rate to 9600 bps } void loop() {}
Arduino Mega example:
// Arduino Mega using all four of its Serial ports // (Serial, Serial1, Serial2, Serial3), // with different baud rates: 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() {}
Serial.end()
-
描述
禁用串行通讯,并允许 RX 和 TX 引脚被用作通用输入和输出。再次调用
Serial.begin()
可重新启用串行通讯,启用后 RX 和 TX 便不能再被用作通用输入和输出。 -
语法
Serial.end()
Arduino Mega only:
Serial1.end()
Serial2.end()
Serial3.end()
-
参数
Nothing
-
返回值
Nothing
Serial.find()
-
描述
需要注意,流解析只过一遍,没有办法折返回去试图发现或得到更多东西。
Serial.find( )
从串口缓冲区中读取数据直到给定长度的目标字符串被发现为止。如果发现目标字符串将返回true
;如果超时则返回false
。 假如目标字符串被发现,该函数返回 true,如果超时则为 false。Serial.flush()
继承自 Stream utility class。 -
语法
Serial.find(target)
-
参数
target
: 要搜索的字符串(char) -
返回值
boolean
Serial.findUntil()
-
描述
Serial.findUntil()
从串口缓冲区中读取数据直到给定长度的目标字符串,或终止字符串被发现为止。 如果发现目标字符串将返回true
;如果超时则返回false
。Serial.findUntil()
继承自 Stream utility class. -
语法
Serial.findUntil(target, terminal)
-
参数
target
: 要搜索的字符串(char)terminal
: 终止搜索的字符串(char) -
返回值
boolean
Serial.flush()
-
描述
等待传出的串行数据完成传输(在 Arduino 1.0 之前,这反而会移除任何已缓存的传入数据 )。如果需要丢弃接受缓冲区中的所有数据,可使用
while(Serial.read( ) >= 0);
flush()
继承自 Stream utility class. -
语法
Serial.flush()
Arduino Mega only:
Serial1.flush()
Serial2.flush()
Serial3.flush()
-
参数
Nothing
-
返回值
Nothing
Serial.parseFloat()
-
描述
Serial.parseFloat()
返回串行缓冲区中第一个有效的浮点数。解析时,非数值(或减号)字符会被跳过。parseFloat()
会在第一个非浮点数值处终止。Serial.parseFloat()
继承自 Stream utility class. -
语法
Serial.parseFloat()
-
参数
Nothing
-
返回值
float
Serial.parseInt()
-
描述
在输入串行数据中查找下一个有效的整型。
stream.parseInt()
继承自 Stream utility class。特点:
- 非数值或负号的初始字符会被跳过;
- 如果在(可配置)超时值内没有读取到字符,或是读取到了一个非数值字符,解析将停止。
- 如果发生超时(
Serial.setTimeout()
)时,并没有读取到有效数值,将会返回 0;
-
语法
Serial.parseInt()
Serial.parseInt(char skipChar)
Arduino Mega only:
Serial1.parseInt()
Serial2.parseInt()
Serial3.parseInt()
-
参数
skipChar
:在搜索时,用于跳过指定字符。例如用来跳过千位分隔符,如 32,767 将被解析为 32767。 -
返回值
long
:下一个有效整型
Serial.peek()
-
描述
返回输入串行数据的下一个字节(字符),但不会从内部串行缓冲区移除该字节。也就是说,在下一次调用
read()
之前,如果连续调用peek()
的话,将返回相同的字符。peek()
继承自 Stream utility class. -
语法
Serial.peek()
Arduino Mega only:
Serial1.peek()
Serial2.peek()
Serial3.peek()
-
参数
Nothing
-
返回值
输入串行数据的第一个可用字节(如果没有数据可用,则返回 -1 )-
int
Serial.print()
-
描述
将数据以人类可读的 ASCII 文本打印到串口。该命令有多重形式。对于数值,会使用 ASCII 字符打印其每个数位。对于浮点数,同样会使用 ASCII 打印其每个数位,默认包含两位小数。Bytes 会以单个字符发送。字符和字符串按原样发送。例如 -
Serial.print(78) gives "78"
Serial.print(1.23456) gives "1.23"
Serial.print('N') gives "N"
Serial.print("Hello world.") gives "Hello world."
可选的第二参数用于指定底数(格式),允许的值有:
BIN(binary, or base 2)
,OCT(octal, or base 8)
,DEC(decimal, or base 10)
,HEX(hexadecimal, or base 16)
。对于浮点数,第二个参数用于指定小数的位数。例如 -Serial.print(78, BIN) gives "1001110"
Serial.print(78, OCT) gives "116"
Serial.print(78, DEC) gives "78"
Serial.print(78, HEX) gives "4E"
Serial.println(1.23456, 0) gives "1"
Serial.println(1.23456, 2) gives "1.23"
Serial.println(1.23456, 4) gives "1.2346"
可以将基于 flash-memory 的字符串通过
F()
包装(wrapping)后,传递到Serial.print()
中。例如Serial.print(F(“Hello World”))
发送单个 byte,需使用 Serial.write()。
-
语法
Serial.print(val)
Serial.print(val, format)
-
参数
val
: 用于打印输出的值 - 任何类型的数据。 -
返回值
size_t
:print()
返回向外写出的字节数,但可选择是否需获取该返回值。 -
示例代码
/* Uses a FOR loop for data and prints a number in various formats. */ int x = 0; // variable void setup() { Serial.begin(9600); // open the serial port at 9600 bps: } void loop() { // print labels Serial.print("NO FORMAT"); // prints a label Serial.print("\t"); // prints a tab Serial.print("DEC"); Serial.print("\t"); Serial.print("HEX"); Serial.print("\t"); Serial.print("OCT"); Serial.print("\t"); Serial.print("BIN"); Serial.println("\t"); // carriage return after the last label for(x=0; x< 64; x++){ // only part of the ASCII chart, change to suit // print it out in many formats: Serial.print(x); // print as an ASCII-encoded decimal - same as "DEC" Serial.print("\t\t"); // prints two tabs to accomodate the label lenght Serial.print(x, DEC); // print as an ASCII-encoded decimal Serial.print("\t"); // prints a tab Serial.print(x, HEX); // print as an ASCII-encoded hexadecimal Serial.print("\t"); // prints a tab Serial.print(x, OCT); // print as an ASCII-encoded octal Serial.print("\t"); // prints a tab Serial.println(x, BIN); // print as an ASCII-encoded binary // then adds the carriage return with "println" delay(200); // delay 200 milliseconds } Serial.println(""); // prints another carriage return }
-
注意和警告
从 1.0 版本开始,串行传输是异步的;
Serial.print()
将在任何字符被发送前返回。Serial.print()
和Serial.write()
不会阻塞程序。在 1.0 之前,代码会等到所有的字符发送之后才返回。在 1.0 及其以后,Serial.write()
会在后台中进行(使用了终端处理程序),这使得程序会理解恢复,并执行后续代码。这种方式通常可使程序更加快捷,但是入股需要等待所有字符发送完毕。可以通过在Serial.write()
之后调用Serial.flush()
来实现。
Serial.println()
-
描述
将数据以人类可读的 ASCII 文本打印到串口,并在文本结尾添加回车字符 (ASCII 13, or '\r') 和换行字符 (ASCII 10, 或 '\n')。该命令采用与 Serial.print() 相同的格式。
-
语法
Serial.println(val)
Serial.println(val, format)
-
参数
val
: 用于打印输出的值 - 任何类型的数据。format
: 指定底数(对于整形数据类型)或小数位数(对于浮点类型) -
返回值
size_t
:println()
返回向外写出的字节数,但可选择是否需获取该返回值 -
示例代码
/* Analog input reads an analog input on analog in 0, prints the value out. created 24 March 2006 by Tom Igoe */ int analogValue = 0; // variable to hold the analog value void setup() { // open the serial port at 9600 bps: Serial.begin(9600); } void loop() { // read the analog input on pin 0: analogValue = analogRead(0); // print it out in many formats: Serial.println(analogValue); // print as an ASCII-encoded decimal Serial.println(analogValue, DEC); // print as an ASCII-encoded decimal Serial.println(analogValue, HEX); // print as an ASCII-encoded hexadecimal Serial.println(analogValue, OCT); // print as an ASCII-encoded octal Serial.println(analogValue, BIN); // print as an ASCII-encoded binary // delay 10 milliseconds before the next reading: delay(10);
Serial.read()
-
描述
读取传入的串口的数据。
read() 继承自 Stream utility class.
-
语法
Serial.read()
Arduino Mega only:
Serial1.read()
Serial2.read()
Serial3.read()
-
参数
Nothing
-
返回值
串行输入数据的第一个可用字节(如果数据不可用,则返回 -1)-
int
。 -
示例代码
int incomingByte = 0; // for incoming serial data void setup() { Serial.begin(9600); // opens serial port, sets data rate to 9600 bps } void loop() { // send data only when you receive data: if (Serial.available() > 0) { // read the incoming byte: incomingByte = Serial.read(); // say what you got: Serial.print("I received: "); Serial.println(incomingByte, DEC); } }
Serial.readBytes()
-
描述
Serial.readBytes()
会从串行端口读取多个字符,并将它们存放到一个缓冲器中。如果已读取了指定数量的字符,或发生了超时 (Serial.setTimeout()),函数都将终止执行。Serial.readBytes()
会返回被存放到缓冲器中的字符数。0 意味着没有找到有效数据。Serial.readBytes()
继承自 Stream utility class。 -
语法
Serial.readBytes(buffer, length)
-
参数
buffer
: 用于存储字节的缓冲器 (char[]
orbyte[]
)length
: 指定需要读取的字节数 (int
) -
返回值
放入缓冲区的字节数 (
size_t
) 。
Serial.readBytesUntil()
-
描述
Serial.readBytesUntil()
用于从串口缓冲区读取多个字符到一个数组中。如果检测到终止字符,或是已读取了指定数量的字符,又或是发生了超时 (Serial.setTimeout()),函数都将终止执行。该函数读取的字符不包含终止字符,仅到终止字符的前一个字符为止。终止字符会被保留在串口缓冲区中。Serial.readBytesUntil()
会返回被存放到缓冲器中的字符数。0 意味着没有找到有效数据。Serial.readBytesUntil()
继承自 Stream utility class. -
语法
Serial.readBytesUntil(character, buffer, length)
-
参数
character
: 终止字符 (char
)buffer
: 用于存储字节的缓冲器 (char[]
orbyte[]
)length
: 指定需要读取的字节数 (int
) -
返回值
size_t
Serial.setTimeout()
-
描述
Serial.setTimeout()
用于设置等待串行数据的最大毫秒数,对于 serial.readBytesUntil() 或 serial.readBytes() 有效。默认值是 1000 毫秒。Serial.setTimeout()
继承自 Stream utility class. -
语法
Serial.setTimeout(time)
-
参数
time
: 超时持续时间,单位是毫秒 (long
) 。 -
返回值
-
Nothing
Serial.write()
-
描述
向串行端口写入二进制数据。数据会以单个字节,或是以一系列字节被发送。如果发送的 characters 表示的一个数值的不同数位则应用
print()
函数代替。直接将变量的值以数值形式发送,发送时不会转换为ASCII,如整型值 65,会以65发送,若接收方以 ASCII 显示,则会显示A;若以 hex 显示,则显示41。
-
语法
Serial.write(val)
Serial.write(str)
Serial.write(buf, len)
Arduino Mega also supports:
Serial1
,Serial2
,Serial3
(in place ofSerial
) -
参数
val
: 以单个字节的形式发送值str
: 以一系列字节的形式发送字符串buf
: 以一系列字节的形式发送一个数组len
: 缓冲器的长度 -
返回值
size_t
:write()
将返回向外写出的字节数,但可选择是否需获取该返回值。 -
示例代码
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.write(45); // send a byte with the value 45
int bytesSent = Serial.write(“hello”); //send the string “hello” and return the length of the string.
}
Description
Writes binary data to the serial port. This data is sent as a byte or series系列 of bytes; to send the characters representing表示的 the digits of a number use the print() function instead.
Serial.serialEvent()
串口数据可用
-
描述
当数据可用时调用该函数。使用
Serial.read()
便可俘获可用数据。NB : 目前
serialEvent()
不兼容 Esplora, Leonardo, 以及 Micro 。 -
语法
void serialEvent(){ //statements }
Arduino Mega only:
void serialEvent1(){ //statements } void serialEvent2(){ //statements } void serialEvent3(){ //statements }
-
参数
statements
: 任何有效语句 -
返回值
Nothing