Arduino - 串口操作函数与示例代码大全

官网地址

https://www.arduino.cc/reference/en/language/functions/communication/serial/

Arduino - 串口操作函数与示例代码大全

转载原文地址:https://blog.csdn.net/iracer/article/details/50334041
在原文的基础上,进行进一步整理,感谢iracer(https://me.csdn.net/iracer)

本文总结了Arduino常用串口操作函数,函数说明部分来源于Arduino 官网串口使用指南,示例与实验部分为自编。本文是对Arduino串口操作函数的较全面总结,可作为工具贴查找使用。

1.串口设置

Serial.begin();

  • 说明
    开启串口,通常置于setup()函数中。
  • 语法
    Serial.begin(speed);
    Serial.begin(speed,config);
  • 参数
    speed: 波特率,一般取值300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600,115200
    config: 设置数据位、校验位和停止位。例如Serial.begin(speed,Serial_8N1); Serial_8N1中:8表示8个数据位,N表示没有校验,1表示有1个停止位。
  • 返回

None

  • 示例
    void setup() { 
    Serial.begin(9600); // opensserial port, sets data rate to 9600 bps 
    }

Serial.end();

  • 说明
    禁止串口传输函数。此时串口传输的pin脚可以作为数字IO脚使用。
  • 语法
    Serial.end()
  • 参数
    None
  • 返回
    None

2.清空串口缓存

Serial.flush();

  • 说明
    1.0版本之前为清空串口缓存,现在该函数作用为等待输出数据传送完毕。如果要清空串口缓存的话,可以使用:while(Serial.read() >= 0)来代替。
  • 语法
    Serial.flush ()
  • 参数
    None
  • 返回
    None

while(Serial.read()>= 0){}

  • 说明
    在此代码之前最好加入Serial.flush()语句,使得串口数据传输完毕,再进行清空。
    因Serial.read()函数读取串口缓存中的一个字符,并删除已读字符。因此可以用这句代码来清空串口缓存。实验代码详见下文代码。
  • 语法
Serial.flush();
while(Serial.read() >=0){}
  • 参数
    None
  • 返回
    None
  • 示例
void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()) {
    int n = Serial.parseInt();
    Serial.println(n);
    Serial.flush();
    while (Serial.read() >= 0) {}
  }
}

3.输出串口数据

Serial.print();

  • 说明
    串口输出数据函数,写入字符串数据到串口。
  • 语法
    Serial.print(val)
    Serial.print(val,format)
  • 参数
    val: 打印的值,任意数据类型
    format: 输出的数据格式,包括整数类型和浮点型数据的小数点位数。
  • 示例
Serial.print(78, BIN) 得到 "1001110"
Serial.print(78, OCT) 得到 "116"
Serial.print(78, DEC) 得到 "78"
Serial.print(78, HEX) 得到 "4E"
Serial.print(1.23456, 0) 得到 "1"
Serial.print(1.23456, 2) 得到 "1.23"
Serial.print(1.23456, 4) 得到 "1.2346"
Serial.print('N') 得到 "N"
Serial.print("Hello world.") 得到 "Hello world."

Serial.println();

  • 说明
    写入字符串数据,并换行。实验代码详见下文。

  • 语法
    Serial.println(val)
    Serial.println(val,format)

  • 参数
    val: 打印的值,任意数据类型
    format: 输出的数据格式,包括整数类型和浮点型数据的小数点位数。

  • 返回

字节

Serial.SerialEvent();

串口数据准备好时触发的事件函数,即串口数据准备好调用该函数。使用Serial.read()捕捉到了这个数据。

  • 语法
void serialEvent() {
  //statements
}

对于具有附加串行端口的电路板(请参见串行主页上每个电路板的可用串行端口列表):

void serialEvent1() {
  //statements
}

void serialEvent2() {
  //statements
}

void serialEvent3() {
  //statements
}

示例代码

/ *
Serial事件示例

当新的串行数据到达时,此草图将其添加到String。
收到换行符时,循环打印字符串并清除它。

对此的一个很好的测试是尝试使用发出
NMEA 0183句子的GPS接收器。

注意:Leonardo,Micro或  其他基于ATmega32U4的主板上不提供serialEvent()功能。
由Tom Igoe   于2011年5月9日创建   此示例代码在公共领域。
http://www.arduino.cc/en/Tutorial/SerialEvent
* /

String inputString = "";         //一个用于保存传入数据的字符串
bool stringComplete = false;  //字符串是否完整

void setup () {
  // initialize serial:
  Serial.begin(9600 );
  //为inputString保留200个字节:
  inputStringreserve(200);
}

void loop () {
  //在换行符到达时打印字符串:
  if (stringComplete) {
    Serial.println( inputString);
    //清除字符串:
    inputString = “” ;
    stringComplete = false ;
  }
}

/ *
每当有新的数据进入硬件序列RX发生的serialEvent。此
例程在每个时间循环()运行之间运行,因此使用内部循环
延迟可以延迟响应。可以使用多个字节的数据。
* /
void serialEvent () {
  while (Serial.available()) {
    //获取新的字节:
    char inChar = (char)Serial.read();
    //将它添加到inputString:
    inputString + = inChar ;
    //如果传入的字符是换行符,请设置一个标志,以便主循环可以
    //对它做一些事情:
    if ( inChar == ' \ n ' ) {
      stringComplete = true ;
    }
  }
}
  • 参数
    statements: 任何有效的语句。
  • 注意事项:
    serialEvent()不适用于Leonardo,Micro或Yún。
    serialEvent()与serialEvent1()不适用于Arduino SAMD板
    serialEvent(),serialEvent1(),serialEvent2(),serialEvent3() 不使用Arduino Due。

4.读串口缓存区数据

Serial.available();

  • 说明

判断串口缓冲器的状态函数,用以判断数据是否送达串口。注意使用时通常用delay(100)以保证串口字符接收完毕,即保证Serial.available()返回的是缓冲区准确的可读字节数。

  • 语法
    Serial.available();
  • 参数
    None
  • 返回
    返回缓冲区可读字节数目
  • 示例
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}//clear serialbuffer
}
 
void loop() {
   if (Serial.available() > 0) {
    delay(100); // 等待数据传完
    int numdata = Serial.available();
    Serial.print("Serial.available = :");
    Serial.println(numdata);
  }
  while(Serial.read()>=0){} //清空串口缓存
}
  • 实验结果

Serial.read();

  • 说明
    读取串口数据,一次读一个字符,读完后删除已读数据。
  • 语法
    Serial.read();
  • 参数
    None
  • 返回
    返回串口缓存中第一个可读字节,当没有可读数据时返回-1,整数类型。
  • 示例
char comchar;
 
void setup() {
  Serial.begin(9600);
  while(Serial.read()>= 0){}/ /clear serialbuffer
}
 
void loop() {
  // read data from serial port
 
  while(Serial.available()>0){
    comchar = Serial.read();//读串口第一个字节
    Serial.print("Serial.read: ");
    Serial.println(comchar);
    delay(100); 
    }
 }
  • 实验结果

从实验结果可以看出:Serial.read()每次从串口缓存中读取第一个字符,并将读过的字符删除。

Serial.peek();

  • 说明

读串口缓存中下一字节的数据(字符型),但不从内部缓存中删除该数据。也就是说,连续的调用peek()将返回同一个字符。而调用read()则会返回下一个字符。

  • 语法
    Serial.peek();
  • 参数
    None
  • 返回
    返回串口缓存中下一字节(字符)的数据,如果没有返回-1,整数int型
  • 示例
char comchar;

void setup() {
 Serial.begin(9600);
 while(Serial.read()>= 0){}//clear serialbuffer
}

void loop() {
 // read data from serial port

 while(Serial.available()>0){
   comchar = Serial.peek();
   Serial.print("Serial.peek: ");
   Serial.println(comchar);
   delay(100); 
   }
}
  • 实验结果
    从实验结果可以看出:Serial.peek()每次从串口缓存中读取一个字符,并不会将读过的字符删除。第二次读取时仍然为同一个字符。

Serial.readBytes(buffer,length);

  • 说明
    从串口读取指定长度length的字符到缓存数组buffer。
  • 语法
    Serial.readBytes(buffer,length);
  • 参数
    buffer: 缓存变量
    length:设定的读取长度
  • 返回
    返回存入缓存的字符数,0表示没有有效数据。
  • 示例
char buffer[18];
int numdata=0;
    
void setup() {
    Serial.begin(9600);
    while(Serial.read()>= 0){}//clear serial port
}
    
void loop() {
    // read data from serial port
    if(Serial.available()>0){
        delay(100);
        numdata = Serial.readBytes(buffer,3);
        Serial.print("Serial.readBytes:");
        Serial.println(buffer);    
    }
    // clear serial buffer
    while(Serial.read() >= 0){}
    for(int i=0; i<18; i++){
        buffer[i]='\0';
    }
}
  • 实验结果
    从串口缓存读取指定长度为3的字节。

Serial.readBytesUntil(character,buffer,length);

  • 说明
    从串口缓存读取指定长度的字符到数组buffer,遇到终止字符character后停止。
  • 语法
    Serial.readBytesUntil(character ,buffer,length);
  • 参数
    character : 查找的字符 (char)
    buffer: 存储读取数据的缓存(char[] 或byte[])
    length:设定的读取长度
  • 返回
    返回存入缓存的字符数,0表示没有有效数据。
  • 示例
    char buffer[18];
    char character = ','; //终止字符
    int numdata=0;
     
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}//clear serialport
    }
     
    void loop() {
      // read data from serial port
      if(Serial.available()>0){
          delay(100);
          numdata =Serial.readBytesUntil(character,buffer,3);
          Serial.print("Serial.readBytes:");
          Serial.println(buffer);    
        }
        // clear serial buffer
      while(Serial.read() >= 0){}
      for(int i=0; i<18; i++){
            buffer[i]='\0';
        }
    }
  • 实验结果
    从串口缓存中读取3个字符,当遇到","时终止读取。

Serial.readString();

  • 说明
    从串口缓存区读取全部数据到一个字符串型变量。
  • 语法
    Serial.readString();
  • 参数
    None
  • 返回
    返回从串口缓存区中读取的一个字符串。
  • 示例
String comdata = "";
    
void setup() {
    Serial.begin(9600);
    while(Serial.read()>= 0){} //clear serialbuffer
}
    
void loop() {
    // read data from serial port
    if(Serial.available()>0){
        delay(100);
        comdata = Serial.readString();
        Serial.print("Serial.readString:");
        Serial.println(comdata);
    }
    comdata = "";
}
  • 实验结果
    从实验结果可以看出:Serial.readString()从串口缓存中读取字符至字符串。

Serial.readStringUntil();

  • 说明
    从串口缓存区读取字符到一个字符串型变量,直至读完或遇到某终止字符。
  • 语法
    Serial.readStringUntil(terminator)
  • 参数
    terminator:终止字符(cha型)
  • 返回
    从串口缓存区中读取的整个字符串,直至检测到终止字符。
  • 示例
String comdata = "";
char terminator = ',';
void setup() {
    Serial.begin(9600);
    while(Serial.read()>= 0){} //clear serialbuffer
}
    
void loop() {
    // read data from serial port
    if(Serial.available()>0){
        delay(100);
        comdata =Serial.readStringUntil(terminator);
        Serial.print("Serial.readStringUntil: ");
        Serial.println(comdata);
    }
    while(Serial.read()>= 0){}
}
  • 实验结果
    从串口读取所有字符存放于字符串comdata,直至遇到字符","时终止读取。

Serial.parseFloat();

  • 说明
    读串口缓存区第一个有效的浮点型数据,数字将被跳过。当读到第一个非浮点数时函数结束。
  • 语法
    Serial.parseFloat()
  • 参数
    None
  • 返回
    返回串口缓存区第一个有效的浮点型数据,数字将被跳过。
  • 示例
    float comfloat;
     
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}//clear serialbuffer
    }
     
    void loop() {
      // read data from serial port
      if(Serial.available()>0){
          delay(100);
          comfloat = Serial.parseFloat();
          Serial.print("Serial.parseFloat:");
          Serial.println(comfloat);
        }
        // clear serial buffer
        while(Serial.read() >= 0){}
    }
  • 实验结果
    从实验结果可以看出:Serial. parseFloat()从串口缓存中读取第一个有效的浮点数,第一个有效数字之前的负号也将被读取,独立的负号将被舍弃。

Serial.parseInt()

  • 说明
    从串口接收数据流中读取第一个有效整数(包括负数)。

注意:
非数字的首字符或者负号将被跳过
当可配置的超时值没有读到有效字符时,或者读不到有效整数时,分析停止
如果超时且读不到有效整数时,返回0

  • 语法
    Serial.parseInt()
    Serial.parseInt(charskipChar)
  • 参数
    skipChar用于在搜索中跳过指定字符(此用法未知)
  • 返回
    返回下一个有效整型值。
  • 示例
int comInt;
    
voidsetup() {
    Serial.begin(9600);
    while(Serial.read()>= 0){}//clear serialbuffer
}
    
void loop() {
    // read data from serial port
    if(Serial.available()>0){
        delay(100);
        comInt = Serial.parseInt();
        Serial.print("Serial.parseInt:");
        Serial.println(comInt);
    }
    // clear serial buffer
    while(Serial.read() >= 0){}
}
  • 实验结果
    从实验结果可以看出:Serial. parseInt()从串口缓存中读取第一个有效整数,第一个有效数字之前的负号也将被读取,独立的负号将被舍弃。
  • 示例二
    1. 需要硬件
      - Arduino或Genuino董事会
      - 共阳极RGB LED
      - 3 220欧姆电阻器
      - 连接线
      - 线路板
    2. 电路
      在这里插入图片描述
/ *
读取串行ASCII编码的字符串。
该草图演示了Serial parseInt()函数。
它查找以逗号分隔的值的ASCII字符串。
它将它们解析为整数, 并使用它们淡化RGB LED。

电路:共阴极RGB LED如此接线:
- 红色阳极:数字引脚3
- 绿色阳极:数字引脚5
- 蓝色阳极:数字引脚6
- 阴极:GND

创建于2012年4月13日
由Tom Igoe
修改2016年3月14日
由Arturo Guadalupi

此示例代码位于公共域中。
* /

// LED的引脚:
const int redPin = 3 ;
const int greenPin = 5 ;
const int bluePin = 6 ;

void setup () {
  // initialize serial:
  Serial.begin(9600 );
  //使引脚输出:
  pinMode ( redPin , OUTPUT );
  pinMode ( greenPin , OUTPUT );
  pinMode ( bluePin , OUTPUT );
}

void loop() {
  //如果有任何可用的串行,读它:
  while (Serial.available() > 0 ) {

    //外表输入串行数据流中下一个有效的整数:
    INT red = Serial.parseInt();
    //再做一次:
    int green = Serial.parseInt();
    //再做一次:
    int blue = Serial.parseInt();

    //寻找换行符。这是你的句子结束:
    if (Serial.read() == '\n' ) {
      //约束值设置为0 - 255,反转
      //如果您使用的是共阴极LED,只是用“constrain(颜色,0,255);“
      red = 255 - constrain(red, 0 , 255 );
      green = 255 - constrain(green, 0 , 255 );
      blue = 255 - constrain(blue, 0 , 255 );

      //淡化LED的红色,绿色和蓝色腿:
      analogWrite(redPin , red);
      analogWrite(greenPin , green);
      analogWrite(bluePin , blue);

      //将一个字符串中的三个数字打印为十六进制:
      Serial.print(red, HEX);
      Serial.print(green, HEX);
      Serial.println(blue, HEX);
    }
  }
}

关于contain函数说明:

constrain()

  • Description
    Constrains a number to be within a range.

  • Syntax
    constrain(x, a, b)

  • Parameters
    x: the number to constrain, all data types a: the lower end of the range, all data types b: the upper end of the range, all data types

  • Returns
    x: if x is between a and b
    a: if x is less than a
    b: if x is greater than b

  • Example Code
    The code limits the sensor values to between 10 to 150.
    sensVal = constrain(sensVal, 10, 150); // limits range of sensor values to between 10 and 150

  • Notes and Warnings
    Because of the way the constrain() function is implemented, avoid using other functions inside the brackets, it may lead to incorrect results.
    This code will yield incorrect results:

int constrainedInput = constrain(Serial.parseInt(), minimumValue, maximumValue);   // avoid this

Use this instead:

int input = Serial.parseInt();  // keep other operations outside the constrain function
int constrainedInput = constrain(input, minimumValue, maximumValue);

5.串口查找指定字符串

Serial.find()

  • 说明
    从串口缓存区读取数据,寻找目标字符串target(char型)
  • 语法
    char target[] = ”目标字符串”;

Serial.find(target);

  • 参数
    target: 目标字符串(char型)
  • 返回
    找到目标字符串返回真,否则为假
  • 示例
char target[] ="test";
    
void setup() {
    Serial.begin(9600);
    while(Serial.read()>= 0){}//clear serialbuffer
}
    
void loop() {
    // read data from serial port
    if(Serial.available()>0){
        delay(100);
        if( Serial.find(target)){
            Serial.print("find traget:");
            Serial.println(target);       
        }
        }
    // clear serial buffer
    while(Serial.read() >= 0){}
}
  • 实验结果
    串口输入字符中只要有test,函数返回真,打印出目标字符串”test”,否则返回假,不打印任何值。

Serial.findUntil(target,terminal);

  • 说明
    从串口缓存区读取数据,寻找目标字符串target(char型数组),直到出现给定字符串terminal(char型),找到为真,否则为假。
  • 语法
    Serial.findUntil(target,terminal);
  • 参数
    target : 目标字符串(char型)
    terminal : 结束搜索字符串(char型)
  • 返回
    如果在找到终止字符terminal之前找到目标字符target,返回真,否则返回假。
  • 示例
char target[] ="test";
char terminal[] ="end";
void setup() {
    Serial.begin(9600);
    while(Serial.read()>= 0){}//clear serialbuffer
}
    
void loop() {
    // read data from serial port
    if(Serial.available()>0){
        delay(100);
        if( Serial.findUntil(target,terminal)){
            Serial.print("find traget:");
            Serial.println(target);
        }
        }
    // clear serial buffer
    while(Serial.read() >= 0){}
}
  • 实验结果
    如果串口缓存中有目标字符”test”,返回真,但如果先遇到终止字符串”end”则函数立即终止,不论字符串后面有没有目标字符”test”。

6.向串口写数据

Serial.write();

  • 说明
    将二进制数据写入串行端口。该数据作为字节或字节序列发送; 发送代表数字的数字字符使用print()函数代替。
  • 语法
    Serial.write(val)
    Serial.write(str)
    Serial.write(buf, len)
  • 参数
    val: 字节
    str: 一串字节
    buf: 字节数组
    len: buf的长度
  • 返回
    size_t
    write() 将返回写入的字节数,但读取该数字是可选的
  • 示例
void setup(){ 
Serial.begin(9600); 
}
void loop(){ 
    Serial.write(45); // send a byte with thevalue 45 
    int bytesSent = Serial.write(“hello”); //sendthe string “hello” and return the length of the string. 
}
  • 备注和警告
    从Arduino IDE 1.0开始,串行传输是异步的。如果发送缓冲区中有足够的空白空间,Serial.write()则在通过串行传输任何字符之前将返回。如果发送缓冲区已满,Serial.write()则将阻塞,直到缓冲区中有足够的空间。为避免调用Serial.write()阻塞,您可以首先使用availableForWrite()检查传输缓冲区中的可用空间量。

arduino串口的高级用法

1. 配置串口通信数据位、校验位、停止位

通常我们使用Serial.begin(speed)来完成串口的初始化,这种方式,只能配置串口的波特率。
而使用Serial.begin(speed, config)可以配置数据位、校验位、停止位等。
例如Serial.begin(9600,SERIAL_8E2)是将串口波特率设为9600,数据位8,偶校验,停止位2。
config可用配置如下:

config可选配置 数据位 校验位 停止位 config可选配置 数据位 校验位 停止位
SERIAL_5N1 5 1 SERIAL_5E2 5 2
SERIAL_6N1 6 1 SERIAL_6E2 6 2
SERIAL_7N1 7 1 SERIAL_7E2 7 2
SERIAL_8N1 8 1 SERIAL_8E2 8 2
SERIAL_5N2 5 2 SERIAL_5O1 5 1
SERIAL_6N2 6 2 SERIAL_6O1 6 1
SERIAL_7N2 7 2 SERIAL_7O1 7 1
SERIAL_8N2 8 2 SERIAL_8O1 8 1
SERIAL_5E1 5 1 SERIAL_5O2 5 2
SERIAL_6E1 6 1 SERIAL_6O2 6 2
SERIAL_7E1 7 1 SERIAL_7O2 7 2
SERIAL_8E1 8 1 SERIAL_8O2 8 2

2. if (Serial)的用法

当串口被打开时,Serial的值为真。串口被关闭时Serial的值为假。
比较囧的是,这个方法只适用于Leonardo和micro的Serial,也就是说连接连接到电脑USB的那个模拟串口。
例如以下程序,当你没有使用串口监视器打开串口时,程序就会一直循环运行while (!Serial) {;},当你打开串口监视器,程序会退出while循环,开始loop中的程序。

void setup() { 
  Serial.begin(9600); 
  while (!Serial) {;}
} 
void loop() { 
 }

3. read和peek输入方式的差异

串口接收到的数据都会暂时存放在接收缓冲区中,使用read()与peek()都是从接收缓冲区中读取数据。不同的是,使用read()读取数据后,会将该数据从接收缓冲区移除;而使用peek()读取时,不会移除接收缓冲区中的数据。
你可以使用以下程序,观察其运行结果:

char col;
void setup() { 
  Serial.begin(9600); 
} 
 
void loop() { 
  while(Serial.available()>0){
    col=Serial.read();
    Serial.print("Read: "); 
    Serial.println(col);
    delay(1000);
  } 
}
char col;
void setup() { 
  Serial.begin(9600); 
} 
 
void loop() { 
  while(Serial.available()>0){
    col=Serial.peek();
    Serial.print("Read: "); 
    Serial.println(col);
    delay(1000);
  } 
}

4. 串口读入int型数据

实际上是串口读入字符串,再转换为int型数据。

while (Serial.available() > 0) {
    int inChar = Serial.read();
    if (isDigit(inChar)) {
		inString += (char)inChar;
	}
	i=inString.toInt();
}

5. 输出不同进制的文本

我们可以是用 Serial.print(val, format)的形式输出不同进制的文本

  • 参数val 是需要输出的数据
  • 参数format 是需要输出的进制形式,你可以使用如下参数:
    - BIN(二进制)
    - DEC(十进制)
    - OCT(八进制)
    - HEX(十六进制)
    例如,使用Serial.print(123,BIN);,你可以在串口调试器上看到1111011
    使用Serial.print(123,HEX);,你可以在串口调试器上看到7B

6. Arduino MEGA\Arduino DUE上其他串口用法

serial1\serial2\serial3
和serial用法一样
比如serial3.begin(9600);

7. 修改串口缓冲区大小

Arduino串口缓冲区默认为64字节,如果你单次传输的数据较多可以将
arduino-1.0.5-r2\hardware\arduino\cores\arduino\HardwareSerial.cpp中的
#define SERIAL_BUFFER_SIZE 64
修改为
#define SERIAL_BUFFER_SIZE 128
这样就有128字节的缓冲区了

转载请注明:http://blog.csdn.net/iracer/article/details/50334041

作者:iracer
来源:CSDN
原文:https://blog.csdn.net/iracer/article/details/50334041
版权声明:本文为博主原创文章,转载请附上博文链接!

版权声明:本文为CSDN博主「acktomas」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/acktomas/article/details/88943922

生成海报
点赞 0

acktomas

我还没有学会写个人说明!

暂无评论

相关推荐

【翻译】arduino 内置示例

内置示例{#top} https://www.arduino.cc/en/Tutorial/BuiltInExamples 内置示例是Arduino软件(IDE)中包含的草图,单击工具栏菜单打开它们&

按键软件“消抖”处理

1. 说明: 最为常用的消抖方式就是通过软件消抖,该方法广泛应用于单片机硬件电路设计中,其基本的原理就是延时消抖,当按键的一刹那,并不让CPU立即处理指令,而