Arduino| 串口通讯、入门示例

Arduino串口通讯

为什么要做串口通讯

串口通讯:串口通信是用来在不同电子设备之间交换数据用的技术,其实就是要实现不同电子设备之间的"通讯对话"。

串口给通讯应用例子:刚拿到Arduino进行Blink测试,程序通过引脚控制了小灯亮起,但是如果我们想要改变当前小灯的亮度,想要把这个"想法"传递给Arduino的时候,就需要串口通讯了。可以通过串口通讯,从PC端告诉Arduino程序我们想要改变当前小灯的亮度。

串口:Arduino和其它设备通信的接口。

串口通讯原理

Arduino通讯串口:Arduino的串口通常称为UART或USART,通过0(RX)和1(TX)引脚以及USB 端口,来和其它设备进行通信。

UART(Universal Asynchronous Receiver/Transmitter):UART是通用异步收发器,采用异步串行通信协议,通过信号线把需要发送的数据以二进制的形式发出,高电平为数据"1",低电平为数据"0"。

通信传输线:串口通常会有三根线来完成通讯,分别是地线、发送线、接收线。串口通信是异步的,能够在一根线上发送数据同时在另一根线上接收数据,其他线用于握手。

数据帧:Arduino用Serial.print和Serial.println函数发送数据时候,其实是发出一连串数字信号,这些数字信号称为数据帧。数据帧通常由四个部分组成,分别是起始位、数据位、校验位和停止位。

  • 起始位:数据帧开始传输的信号,通常起始位电平为低电平。
  • 数据位:包含了实际发送的数据,Arduino默认使用8位数据,每次可以传输1B数据。
  • 校验位:数据检错的方式,可以设置为奇校验和偶校验,Arduino默认无校验位。
  • 停止位:表示该段数据帧传输结束,通常停止位都是高电平。

串口通讯缓冲区:Arduino的USB端口有串口寄存器,可以用来暂存电脑从USB发送的数据。Arduino从串口寄存器读取的速度比串口发送数据的速度快,所以串口通讯读取数据前需要加一定延时。和电脑通信的时候,Arduino UNO的串口寄存器空间默认是63帧的数据帧大小,超出后信息会挤掉前面的信息。

串口通讯函数

Serial 类:通过 Serial 类来使用开发板上的UART串口,只需要指定波特率,就能使用了。

波特率(Baud Rate):在信息传输通道中,携带数据信息的信号单元叫码元,单位时间内通过信道传输的码元数称为码元传输速率,简称波特率。常用的波特率为9600、115200、4800等,波特率越大表明通信的速率越快。。当传输的码元信息量刚好为1比特的时候,波特率等于比特率。通信双方需要使用一致的的波特率才能正常通信。

Serial.begin()

函数作用:开启串口。

使用方法:speed为波特率;config为设置数据位、校验位和停止位。

  • Serial.begin(speed)
  • Serial.begin(speed, config)

Serial.end()

函数作用:禁止串口传输,此时串口0(RX)和1(TX)引脚可以作为数字引脚使用。

Serial.print()

函数作用:串口输出数据,写入字符数据到串口。

使用方法:val是打印的值;config输出数据格式,BIN(二进制)、OCT(八进制)、DEC(十进制)、HEX(十六进制)等。

  • Serial.print(val)
  • Serial.print(val, format)

Serial.println()

函数作用:串口输出数据并换行。

使用方法:

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

Serial.available()

函数作用:判断串口缓冲区的状态,返回从串口缓冲区读取的字节数。

Serial.read()

函数作用:读取串口数据,一次读一个字符,读完后删除已读数据;当没有可读数据时返回-1,整数类型。

Serial.peek()

函数作用:读取串口数据,一次读一个字符,读完后不删除;当没有可读数据时返回-1,整数类型。。

Serial.readString()

函数作用:每次读取一个字符串,返回一个String类型。

Serial.readStringUntil()

函数作用:每次读取一个字符串,知道遇到截止字符,返回一个String类型。

使用方法:inByte为截止字符。

  • Serial.readStringUntil(inByte)

字符串常用函数

了解字符串的常用函数,可以更好进行串口通讯中复杂指令的处理。

获取字符串中的部分内容:

  • charAt(n):返回字符串中第n个字符。
  • substring(from, to):从指定的起始索引 " from " 到结束索引 " to " (不包括)截取字符串的子串。
  • substring(from):返回一个从给定索引" from " 到结尾的子串。

比较两个字符串:

  • compareTo(S2):与S2字符串比较,如果两个字符串相同,返回值等于0;否则,返回值不等于0。
  • equals(S2):比较两个字符串是否相等,区分大小写。

字符串类型转换:

  • toInt():数字字符串转为整数值。
  • toCharArray(buf,len) :把字符串转换成数组char[],其中buf是char[],len为复制长度。

获取字符串长度:

  • length():返回字符串中的字符数。
  • strlen():获取字符串的长度,不包括空终止符。
  • sizeof():获取字符串的长度,包括空终止符。

两个字符串之间的合并:

  • strcat(str1,str2):把str1(包括"\0")复制到str2后面(删除str2原来末尾的"\0")。
  • concat(S2):返回字符串和字符串S2合并后的新字符串

串口通讯示例

入门示例

先处理一个简单的指令。

示例代码的解释:往串口每次输入一串指令"a1"后,Arduino返回"YES"。

cpp 复制代码
String str;

void setup() {
  Serial.begin(115200);// 设置波特率,上位机的波特率要保证相同,不然无法识别
  str="";
}

void loop() {
  delay(100);//等待100ms=0.1s,加延时是因为Arduino从串口寄存器读取的速度比串口发送数据的速度快
  while (Serial.available() > 0)
  {
    str += char(Serial.read());// read是剪切,而不是复制
  }
  if(str=="a1\0"){
      Serial.println("YES");
  }
  str="";
}

测试串口通讯

程序验证上传到Arduino后。

点击IDE右上角有个串口监视器。

点击后会有下方会出现串口监视器,调整波特率和代码对应,然后输入没有结束符的消息"a1",就可以看到Arduino返回的"YES"。

复杂指令处理

在前面的入门示例中,要处理的上位机指令很简单,上位机每次只发送一个指令"a1"。

但是如果上位机发送的指令很长,而且还包含了数字,甚至可能发送指令的速度很快,"Serial.available() > 0"判断的时候可能有多条指令要区分。

下面是一个处理稍微复杂指令的示例代码,涵盖了处理复杂指令的基本操作。

示例代码的解释:指令格式为"指令类型+数字+\n",前4位为指令类型分别有1001、1002和1003,分别对应的功能为对数字进行1次方、2次方和3次方,指令结尾为"\n"。该代码会对输入的指令进行解读,并且进行相应的功能,返回对应的数值。

cpp 复制代码
String str,pre_str,last_str;

String type_str[] = {"1001", "1002", "1003"}; //指令前4位表示不同类型指令,其中1001表示1次方,1002表示2次方,1003表示3次方

int i,j,ans,cnt;

void setup() {
  Serial.begin(115200);// 设置波特率
}

void loop() {
  delay(100);//等待100ms=0.1s
  while (Serial.available() > 0)
  {
    str= Serial.readStringUntil('\n');//读取指令,指令以"\n"结尾,通过"\n"来分割不同的指令
    pre_str = str.substring(0, 4);//截取输入指令前4位
    last_str= str.substring(5, str.length());//截取输入指令4位后的数据
    
    cnt = last_str.toInt();//将字符串last_str转成数字cnt
    ans=cnt;

    // 根据不同指令计算cnt多少次方
    for(i=0;i<3;i++){
      if(pre_str.compareTo(type_str[i])==0){
        for(j=0;j<i;j++){
          ans*=cnt;
        }
      }
    }

    Serial.println(ans);
  }
}

代码串口测试:

相关推荐
网易独家音乐人Mike Zhou3 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
zy张起灵3 小时前
48v72v-100v转12v 10A大功率转换电源方案CSM3100SK
经验分享·嵌入式硬件·硬件工程
lantiandianzi11 小时前
基于单片机的多功能跑步机控制系统
单片机·嵌入式硬件
哔哥哔特商务网11 小时前
高集成的MCU方案已成电机应用趋势?
单片机·嵌入式硬件
跟着杰哥学嵌入式11 小时前
单片机进阶硬件部分_day2_项目实践
单片机·嵌入式硬件
电子科技圈11 小时前
IAR与鸿轩科技共同推进汽车未来
科技·嵌入式硬件·mcu·汽车
东芝、铠侠总代1361006839312 小时前
浅谈TLP184小型平面光耦
单片机·嵌入式硬件·物联网·平面
lantiandianzi12 小时前
基于单片机中医药柜管理系统的设计
单片机·嵌入式硬件
嵌入式知识大讲堂12 小时前
HDMI数据传输三种使用场景
单片机
黑客呀13 小时前
[系统安全]Rootkit基础
stm32·单片机·系统安全