文章目录
-
-
-
-
- 通信类型
- Arduino串口通信
-
- 硬串口
- 软串口
-
-
-
通信类型 通信是用来在不同电子设备之间交换数据用的技术,其实就是要实现不同电子设备之间的“通讯对话”。
文章图片
Arduino串口通信 Arduino采用USART通信模式,可以有硬串口,软串口两种实现方式。
通常将Arduino UNO上自带的串口0(RX)、1(TX)称为硬件串口,可与外围串口设备通信。而使用SoftwareSerial类库模拟成的串口,称为软件模拟串口(简称软串口)。如果要连接更多的串口设备,可以使用软串口。
硬串口 硬串口的操作类为HardwareSerial,定义于HardwareSerial.h源文件中,并对用户公开声明了Serial对象,用户在Arduino程序中直接调用Serial,就可实现串口通讯。
常用函数有:
Serial.begin()
- 描述:开启串口,通常置于setup()函数中。
- 原型:
- Serial.begin(speed)
- Serial.begin(speed, config)
- 参数:
- speed:波特率,一般取值9600,115200等。
- config:设置数据位、校验位和停止位。默认SERIAL_8N1表示8个数据位,无校验位,1个停止位。
- 返回值:无。
- 描述:禁止串口传输。此时串口Rx和Tx可以作为数字IO引脚使用。
- 原型:Serial.end()
- 参数:无。
- 返回值:无。
- 描述:串口输出数据,写入字符数据到串口。
- 原型:
- Serial.print(val)
- Serial.print(val, format)
- 参数:
- val:打印的值,任意数据类型。
- config:输出的数据格式。BIN(二进制)、OCT(八进制)、DEC(十进制)、HEX(十六进制)。对于浮点数,此参数指定要使用的小数位数。
- 示例:
- 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(val)
- Serial.println(val, format)
- 参数:
- val:打印的值,任意数据类型。
- config:输出的数据格式。
- 返回值:返回写入的字节数。
- 描述:判断串口缓冲区的状态,返回从串口缓冲区读取的字节数。
- 原型:Serial.available()
- 参数:无。
- 返回值:可读取的字节数。
- 描述:读取串口数据,一次读一个字符,读完后删除已读数据。
- 原型:Serial.read()
- 参数:无。
- 返回值:返回串口缓存中第一个可读字节,当没有可读数据时返回-1,整数类型。
实验1:
String str="";
void setup() {
Serial.begin(9600);
//set up serial library baud rate to 9600
}void loop() {
str = "";
while (Serial.available() > 0)
{
str += char(Serial.read());
// read是剪切,而不是复制
delay(10);
// 延时
}
if (str.length() > 0)
{
Serial.print(F("命令行发送内容:"));
Serial.println(str);
}
}
实验现象:
文章图片
实验2:
文章图片
/**
* 通过串口改变Arduino 9号针脚接的LED灯的亮度
*/int i,j,val;
//定义i、j、val三个整型变量
char A[10];
//定义一个无符号数组Avoid setup(){
Serial.begin(9600);
pinMode(9,OUTPUT);
}void loop(){
delay(100);
// 等待100msj = Serial.available();
// 读取串口寄存器中的信息的帧数if(j != 0){// 如果串口寄存器中有数据,那么依次读取这些数据,并存放到数组A中
for(i = 0;
i < j;
i++){
A[i] = Serial.read();
}val = strtol(A,NULL,10);
// 将A中的字符转换成十进制数
}
analogWrite(9,val);
// 将转换好的val输出给三号端口,驱动LED灯的亮度
}
实验分析:
在理解Arduino串口通信前需要知道一些先验知识。
计算机和Arduino的串口接线如下:
文章图片
在Arduino的USB接口连接一个串口寄存器,用来暂时存放电脑传过来的信息(之后Arduino会根据开发者的程序,从串口寄存器中提取数据,保存到Arduino内存中),在和电脑通过USB串口通信时,默认分配给Arduino UNO的串口寄存器空间可存放63帧的信息。(一帧信息包括帧头、数据和帧尾。)超出得话后面的信息就会挤兑前面的信息,造成信息丢失。
read函数读取串口寄存器中的信息。但是Arduino的主频有16M,也就是每秒运算160万次;而串口通信的速度(也就是前面讲到的波特率)最高一般用到115200,也就是每秒115200个比特,约为14400个字节。所以Arduino读取的速度比串口发送的速度快得多,在读取之前需要加一定的延时。
现在假设我们从电脑上发送了三个帧的数据给到Arduino,这三个帧的内容分别是’a’,‘b’,‘c’。
文章图片
首先,右侧中步骤1至步骤4这段时间内,信息一帧一帧地进入串口寄存器中,假如我们想要一次性读取所有的信息,那么在步骤1到步骤4的这段时间内我们不能够对信息进行读取,因为这个时候信息还没有完全传送完毕,也就是说所有信息没有全部进入寄存器。假如我们在图6中的步骤2就开始读取寄存器中的信息,那么我们将只能获得’a’这个信息。对于Arduino这个1秒钟运算160万次的芯片来说,串口信息的传送是很慢的,所以我们必须在开头给Arduino设置一个等待时间,这个等待时间一般就设定100ms即可,这就是为什么要加上delay(100)这条命令的原因。
然后,当等待时间结束,这时候我们认为信息已经完全传送完毕。当然,说实话这都是靠猜,我们估计100ms信息传送完毕了,可能信息早在10ms 的时候就传送完毕了,不过没关系,为了保险我们宁可多等待一会儿,反正是毫秒级的时间损失,对于我们来说多等几十毫秒根本感觉不出来,当然你觉得有把握的话也可以把等待时间缩短一些,比如50ms甚至20ms都可以,你可以尝试着用,假如没有出现信息丢失那你完全可以用更短的等待时间。信息完全传送完毕后,我们才开始要把信息从串口寄存器中都读取出来了,也即是步骤5到步骤7的过程。注意,图6中的黑线指向的那个“大箭头”是Arduino内部的一个指针,这个指针时刻监测着串口寄存器,我们随时可以使用命令Serial.available()来调动这个指针,获取传入信息的数量,当然如我们所说,要等信息全部传送完毕后再开始调用,假如我们在步骤2就调用Serial.available()的话,我们只能探测到一个数据。而在图6中的步骤4我们可以看到,总共有三个信息传入了寄存器,所以这个时候调用Serial.available()获得的值是3,然后我们把这个值赋给变量j,于是变量j就代表了寄存器中信息的数量。
最后,还是这个指针,我们可以使用命令Serial.read()来调动这个指针来抓取数据,注意Serial.read()每次可以抓取一帧的信息,每次抓取走信息后,寄存器中原本存放这个信息的空间就空了出来,我的意思是:Serial.read()命令不是复制信息而是剪切信息。好,回过头来说,3个信息每次抓取1个,那么为了抓取寄存器中的所有信息,我们需要抓取3次,于是我们采用了一个 for循环,循环数设定为j,这样就可以自动抓取所有寄存器中的信息了。每次抓取的数据我们将会存储到数组A中,A是我们在程序开头就定义好的一个字符型数组。关于A数组要注意两点:1)必须定义为字符型数组,因为我们讲过电脑串口输入的所有信息都是字符形式传输的,就算是阿拉伯数字也只是一个字符,而不是真的阿拉伯数字;2)A数组的空间大小在定义的时候要给足,假如我们打算每次处理1帧的数据,那么A的空间就要给到1帧或更多;假如我们每次打算处理3帧的数据,那么A的空间就要大于等于3帧。然后我们把“帧”换算成字节来定义A的空间。
软串口 软串口的操作类为SoftwareSerial,定义于SoftwareSerial.h源文件中,但不像硬串口那样,源文件中并没有事先声明软串口对象,Arduino程序中需要手动创建软串口对象。
在使用前需要先声明包含SoftwareSerial.h头文件。
之后调用SoftwareSerial类的构造函数,通过它可指定软串口RX、TX引脚。
SoftwareSerial mySerial= SoftwareSerial(rxPin, txPin)
SoftwareSerial mySerial(rxPin, txPin)
- mySerial:用户自定义软件串口对象
- rxPin:软串口接收引脚
- txPin:软串口发送引脚
测试代码:
#include//定义管脚2/3分别为RX,TX.
SoftwareSerial mySerial(2, 3);
// RX, TX
void setup()
{
mySerial.begin(9600);
}
void loop()
{
mySerial.println("Hello, world?");
//TX输出
delay(1000);
}
运行程序,会发现串口监视器并没有任何字符串输出,这是为什么?
在硬串口的部分提到过,计算机是通过硬串口TX(1)和RX(0)进行Arduino串口通信的,当我们使用软串口的时候,计算机连接的仍然是这两个引脚。所以即使软串口TX(3)在进行输出,仍然是不会被计算机读取显示的。所以将硬串口TX(1)和软串口TX(3)连接即可,这样软串口TX(3)的输出就会进入到硬串口TX(1)中,进而发送给计算机。
文章图片
实验现象:
文章图片
参考:
Arduino菜鸟通俗版解读系列(4)串口通信USART
Arduino菜鸟通俗版解读系列(7)通信类型总结
推荐阅读
- Arduino 连接JDY-08蓝牙模块
- Arduino|第一章 - 新手入门 - 第三课 Arduino 上手实战呼吸灯
- Arduino|Arduino TFT_eSPI库来驱动SPI接口的LCD显示文字详解
- ESP32|基于arduino的ESP32 学习笔记(二) TFT_eSPI和LVGL库使用笔记
- esp32|Arduino应用开发——spi flash(以esp32和w25qxx为例)
- esp32|ESP32-S2应用开发——USB通信(虚拟串口)
- esp32|ESP32烧录Arduino生成的bin文件
- 技术实践类|BMP280使用指南
- arduino|【毕业设计】基于arduino的蓝牙扫地机器人