• Serial.begin


     

    串口波特率的设置:通常我们使用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.5r2hardwarearduinocoresarduinoHardwareSerial.cpp中的  #define SERIAL_BUFFER_SIZE 64 修改为 #define SERIAL_BUFFER_SIZE 128   这样就有128字节的缓冲区了  Arduino MEGAArduino DUE上其他串口用法: serial1serial2serial3和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,连成一串。这个问题是串口通信本身造成的,一定会出现。
    
    
    **
    
    
    ----------
    
    
    **
    
    
    ----------
    
    
    ----------
    
    
    一种解决方法是,通过在接收端缓存数据来解决这个问题。
    为传输数据设置一个结束标记,如’
    ’(换行符),就能在接收到的数据流中识别到一个字符串的结尾。当未遇到结束标记,就一直将串口数据保存在一个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('
    ');  //buffer until meet '
    ', 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 '
    '
      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) == '
    '){
            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 '
    '
      delay(1000);
    }
  • 相关阅读:
    关于一个标准的poi下载文件模板 可拿来来直接使用
    关于史上最简单的导出(导出excal)
    关于spring MVC的面试题
    关于响应式布局(pc端访问自适应 手机端访问自适应)
    密码生成器
    关于poi的导出(POI)
    关于MUI一个很实用的前端框架
    (转载)插画版Kubernetes指南(小孩子也能看懂的kubernetes教程)
    (转载)Python tips: 什么是*args和**kwargs?
    python编程中的if __name__ == 'main': 的作用和原理
  • 原文地址:https://www.cnblogs.com/MCSFX/p/11290272.html
Copyright © 2020-2023  润新知