在之前的教程,我们学习了如何将DHT-11传感器与Arduino连接。DHT-11是一个集成了8位微控制器的数字传感器。该集成微控制器以40位数字数据包的形式输出湿度和温度值。
在上一篇教程中,我们通过轮询Arduino的一个数字I/O引脚来读取数据包,并通过测量数字信号的脉冲宽度来检测数据位。然而,这并不是数字传感器输出数据的典型方式。大多数数字传感器使用标准的数据通信协议,如UART、SPI或I2C与控制器/计算机进行数据通信。
通用异步接收/发送器(UART)协议是几乎所有嵌入式设备上都可用的最常见的数据通信协议。大多数嵌入式设备使用UART用于交换控制台数据.或者,它们也可以使用I2C来达到同样的目的。这只取决于设备是要成为计算机系统的对等设备还是从属设备。
数字传感器也不例外。几乎所有与控制器/嵌入式计算机作为对等设备的接口的数字传感器都使用UART。这对于那些涉及与计算机系统进行双向数据通信的传感器和设备来说尤其如此。然而,大多数传感器被设计成只将数据作为从端传输到控制器/计算机系统,并且可能使用串行协议,如I2C或SPI来通信传感器数据。(学习串行通信基础知识从这个树莓派教程。)
所有Arduino板都有一个或多个UART端口。Arduino还提供串行功能,这是数字I/O引脚上UART协议的软件实现。但是softwareSerial对于硬件UART是无能的。那么,让我们来讨论一下Arduino的UART功能。
什么是UART?
通用异步收发器(UART)是一种通过UART协议与点对点数据(半双工或全双工)通信的电路。该电路可作为一个独立的集成电路,通常集成在微控制器和嵌入式计算机的外围。
UART协议
您可以了解UART协议在这里.
UART / USART Arduino (s)
串口用于与计算机或其他设备进行数据通信。所有Arduino板都有一个或多个串行端口,可以是UART或USART。
下表列出了不同Arduino板上的UART端口:
Arduino的UART的TTL电压水平可以是5或3.3V,取决于各自的董事会.当连接两个设备的串口时,UART电压必须兼容。如果一个具有较高的UART电压水平(TTL)的串口连接到一个较低的UART电压水平(TTL)的串口,则较高的TTL仍然能够接收串口数据。但是,当它传输串行数据到较低UART电压端口的Rxd引脚时,它就会被损坏。
因此,当连接两个不同TTL电压水平的UART端口时,必须使用合适的TTL电平移位器。
当两个兼容的UART端口直接连接时,一个设备的Txd和Rxd连接到另一个设备的Rxd和Txd -同时共享同一地。如果两个UART端口通过一个TTL逻辑移位器连接,那么连接将依赖于TTL逻辑移位器的引脚配置。
如果UART端口连接到不同的接口,如USB或RS-232,则必须使用合适的串行转换器(例如,RS-232接口使用RS-232串行板,USB接口使用USB串行板)。
这对于RS-232接口尤其重要,因为它们通过UART协议通信数据。这些接口很容易被黑客攻击,从而暴露Rxd和Txd引脚。这些引脚使用正电压和负电压,逻辑位从-15V到15V不等。如果RS-232端口的Rxd和Txd引脚直接连接到TTL UART端口,则TTL端口将被破坏。
在Uno、Nano、Mini和Mega板上,串口引脚0和1被USB用来与计算机通信。如果这些引脚被占用,它可能会干扰通过USB的串行通信。例如,如果有什么东西连接到这些引脚,它可能不可能从计算机上传一个草图到板。
当连接到其他串行端口时(如果像Mega和Due板上可用的话),这些端口只能通过usb串行板连接到计算机。其他串口没有连接到Arduino的USB。
UART通过GPIO引脚
Arduino内置的UART连接到GPIO引脚。串口有两个通道:
- Txd用于传输串行数据
- Rxd接收串行数据,根据UART协议
通过UART通信的两个设备应该具有相同的波特率和数据编码。如果配置为不同的波特率或编码,它们将无法交换数据或交换的数据将是胡言乱语。
通过Arduino USB实现UART
Arduino还可以通过USB进行串行数据通信。然而,USB接口不通过UART协议交换数据。相反,USB有一个不同的数据通信标准,要求一个设备配置为主机,另一个设备配置为从设备。
数据在USB标准中以包的形式通信,UART以字符的形式通信。在USB通信中没有类似的波特率。
如果你还记得,Arduino有两个控制器.一个控制器负责处理USB通信。Arduino的USB接口可以通过计算机对其进行编程。当使用Arduino的USB端口串行通信数据时,这个额外的控制器充当内置的USB串行转换器。
Arduino的UART/USART也连接到这个附加的控制器,它将UART数据转换为USB。当Arduino通过USB线连接到计算机上时,它通过USB起到CDC/ACM设备的作用。这类似于与PC机的串行通信。在一些Arduino板中,USB通信不由附加的控制器处理,而是由板载的主控制器管理。有了这些板,Arduino将自己定位为USB CDC奴隶。
当Arduino连接到Mac时,它使用一个设备名,例如/dev/ ty.Wchusbserial *,其中星号(' * ')可以是任何数字。在Linux系统上,它可能以设备名称出现,例如/dev/ ttyacm *。星号是任意数字。在Windows上,它可能以端口名称出现,例如COM*,其中星号是任何数字。
串行图书馆
Arduino平台支持串行库进行UART通信。这个库有以下方法:
Serial.begin () -用于配置通过串口进行串口通信。用于设置波特率和UART配置。这个方法的语法如下:
Serial.begin(速度)
或
系列。开始(速度、配置)
波特率可以是任意标准波特率,最大值为115200bps。默认的UART配置是8N1。
配置可以设置为以下参数:
SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1(默认),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_7O2, SERIAL_8O2, SERIAL_8O2。
在识别为USB CDC奴隶的Arduino板中,例如Leonardo, Serial.begin()是不相关的。这些单板可以使用UART的任何配置和波特率。该方法的源代码可在Arduino/hardware/ Arduino/ avr/cores/ Arduino/ HardwareSerial.cpp中找到。
Serial.begin()方法的源代码如下:
if(Serial)或if(SerialUSB) -这些if语句可以用来确定串口是否准备就绪。对于非usb CDC端口,请选择(Serial)。对于USB-CDC端口,如果(SerialUSB)是测试条件。如果端口已经准备好,条件将返回True。如果端口不存在——比如某个特定的Arduino板没有USB CDC端口,或者有,但还没有准备好——条件将返回False。
Serial.availableForWrite () -返回可在不阻塞写操作的情况下在串行缓冲区中写入的字节数(字符)。它有这样的语法:
Serial.availableForWrite ()
对于有多个串口的Arduino板,该函数将串口对象作为参数。
该方法有以下源代码:
Serial.write ()- - - - - -用于向串口发送二进制数据。数据以一个字节或一系列字节的形式发送。这个方法的语法如下:
Serial.write (val)
或
Serial.write (str)
或
系列。莱恩写(buf)
该方法需要一个值(单字节)或字符串(一系列字节)作为参数。如果数组作为参数(buf)传递,则数组的长度(len)也应该作为参数传递。
对于有多个串口的Arduino板,该函数将串口对象作为参数。函数将返回写入端口的字节数,但是,读取这个数字是可选的。
该方法有以下源代码:
并同时)用于将ASCII字符发送到串口。这个函数需要一个值或字符串作为参数。它还接受BIN、OCT、DEC或HEX作为可选参数,以指定字符的基本格式(二进制、八进制、十进制或十六进制)。如果传递的值是浮点数,则可以将小数点位数作为参数传递。这个函数的语法如下:
并同时(val)
或
系列。打印(val,格式)
对于有多个串口的Arduino板,该函数将串口对象作为参数。这个函数返回写入端口的字节数,但是读取这个数字是可选的。
以()- - - - - -这个方法与print()方法相同,除了发送的ASCII字符,但后面跟着一个回车符(' \r ')和换行符(' \n ')。它有这样的语法:
以(val)
或
系列。println (val,格式)
Serial.available () -检查是否可以从串口读取串行数据。这是已经到达并存储在64字节串行接收缓冲区中的数据。此方法继承自Stream实用程序类。它有这样的语法:
Serial.available ()
函数返回可从接收串行缓冲区读取的字节数。
该方法有以下源代码:
Serial.read () -用于从串口读取传入的数据。它有这样的语法:
Serial.read ()
它返回传入的可用串行数据的第一个字节,如果没有可用数据则返回-1。
这个函数有以下源代码:
Serial.peek ()- - - - - -此方法返回传入串行数据的下一个字节(字符),而不将其从内部串行缓冲区中删除。它有这样的语法:
Serial.peek ()
该方法有以下源代码:
Serial.readBytes ()- - - - - -从串口读取字符到缓冲区。如果已读取确定的长度或存在超时,则终止。它有这样的语法:
系列。readBytes(缓冲区,长度)
Serial.readBytesUntil ()- - - - - -将字符从串行缓冲区读入数组。如果已经读取了确定的长度、出现超时或检测到终止符,则终止。在缓冲区中不返回终止符本身。这个方法的语法如下:
系列。readBytesUntil(终止符,缓冲区,长度)
Serial.readString ()- - - - - -从串行缓冲区读取字符到字符串。如果超时,则终止。它有这样的语法:
Serial.readString ()
Serial.readStringUntil ()- - - - - -从串行缓冲区读取字符到字符串。如果出现超时或检测到终止符字符,则终止。它有这样的语法:
Serial.readStringUntil(终结者)
Serial.setTimeout ()- - - - - -设置等待串行数据的最大毫秒数。缺省超时时间为1000毫秒。以下方法使用它:Serial.find(), Serial.findUntil(), Serial.parseInt(), Serial.parseFloat(), Serial.readBytes(), Serial.readBytesUntil(), Serial.readString(), Serial.readStringUntil()。它有这样的语法:
Serial.setTimeout(时间)
Serial.find () -从串行缓冲区读取数据,直到找到目标字符串。如果找到目标字符串,则返回true,如果超时则返回false。它有这样的语法:
Serial.find(目标)
或
系列。找到(目标,长度)
Serial.findUntil ()- - - - - -从串行缓冲区读取数据,直到找到给定长度的目标字符串或终止符字符串。如果找到目标字符串,则返回true,如果超时则返回false。它有这样的语法:
系列。findUntil(要搜索的目标字符串,终止符字符串)
Serial.flush ()- - - - - -使串口等待传出的串行数据传输完成。它有这样的语法:
Serial.flush ()
该方法有以下源代码:
Serial.readBytes ()- - - - - -从串口读取字符到缓冲区。如果已读取确定的长度或存在超时,则终止。它有这样的语法:
系列。readBytes(缓冲区,长度)
Serial.readBytesUntil ()- - - - - -将字符从串行缓冲区读入数组。如果已经读取了确定的长度、出现超时或检测到终止符,则终止。在缓冲区中不返回终止符本身。这个方法的语法如下:
系列。readBytesUntil(终止符,缓冲区,长度)
Serial.readString ()- - - - - -从串行缓冲区读取字符到字符串。如果超时,则终止。它有这样的语法:
Serial.readString ()
Serial.readStringUntil ()- - - - - -从串行缓冲区读取字符到字符串。如果出现超时或检测到终止符字符,则终止。它有这样的语法:
Serial.readStringUntil(终结者)
Serial.setTimeout ()- - - - - -设置等待串行数据的最大毫秒数。缺省超时时间为1000毫秒。以下方法使用它:Serial.find(), Serial.findUntil(), Serial.parseInt(), Serial.parseFloat(), Serial.readBytes(), Serial.readBytesUntil(), Serial.readString(), Serial.readStringUntil()。它有这样的语法:
Serial.setTimeout(时间)
Serial.find () -从串行缓冲区读取数据,直到找到目标字符串。如果找到目标字符串,则返回true,如果超时则返回false。它有这样的语法:
Serial.find(目标)
Serial.parseFloat ()- - - - - -返回Serial缓冲区中的第一个有效浮点数。此函数在检测到第一个不是浮点数的字符或超时后终止。它有这样的语法:
Serial.parseFloat ()
或
Serial.parseFloat(超前)
或
系列。parseFloat(超前,忽略)
参数' lookahead '设置用于在浮点数流中向前查找的模式。该参数可以取SKIP_ALL、SKIP_NONE和SKIP_WHITESPACE的值。参数' ignore '用于跳过搜索中指定的字符。
Serial.parseInt ()- - - - - -这个方法类似于Serial.parseFloat()。它从串行缓冲区返回第一个有效整数。如果超时,它也会终止。它有这样的语法:
Serial.parseInt ()
或
Serial.parseInt(超前)
或
系列。方法(超前,忽略)
Serial.end ()- - - - - -禁用串行通信,允许RX和TX引脚用于一般的输入和输出。只有在调用serial .begin()时,才启用串行通信的引脚。它有这样的语法:
Serial.end ()
它有这样的源代码:
Arduino与计算机的接口
将Arduino与计算机连接的最简单方法是使用usb - usb连接线。如果使用其他串口与计算机连接,则必须使用usb转串口板。
连续监测
Arduino IDE有一个集成的串行监视器,可以通过桌面计算机的USB端口接收和发送串行数据。通过导航到“Tools-> serial monitor”可以打开串口监视器。
还可以通过单击IDE右上角的Serial Monitor图标来访问它。
启动Serial Monitor时,将打开一个窗口,在该窗口中可以向连接的串行设备发送、接收和查看串行数据。波特率和编码也可以在窗口内设置。
向计算机传输数据
结果
从计算机接收数据
结果
从计算机接收数据字符串
结果
系列绘图仪
Arduino IDE有一个集成的串行绘图仪,可以用来可视化接收的数据图形化。它可以通过导航到工具->Serial Plotter打开。
在串行绘图器上绘制单个变量
要绘制单个变量,Arduino草图必须将单个变量打印到loop()函数中的串行端口。
看看下面的草图,它在串行绘图仪上绘制了一个正弦波:
结果
在串行绘图仪上绘制多个变量
为了在Serial Plotter上同时绘制多个变量或波形,应该在两个打印函数之间打印一个“空格”。
检查下面的草图,在串行绘图仪上绘制正弦和余弦波。
结果
在下一篇教程中,我们将学习Arduino中的softwareSerial。
了下:Arduino