#ESP32 #Python
在本章节中,我们将深入探讨ESP32的串口通信功能,并教授读者如何有效利用ESP32的串口来实现数据的发送与接收。具体目标在于,实现ESP32与上位机之间的串口对话机制,确保ESP32在接收到上位机发送的字符串后,能够准确无误地将其回传至上位机,从而实现双向的数据交换功能。
本节课目标:
实现ESP32与上位机之间的串口对话机制,确保ESP32在接收到上位机发送的字符串后,能够准确无误地将其回传至上位机,从而实现双向的数据交换功能。
本节课内容:
- 串口简介
- machine.UART类
- 硬件设计
- 软件设计
- 下载验证
一、串口简介
串行接口(Serial Interface),简称串口,又称串行通信接口或串行通讯接口(通常指代 COM 接口)。该接口采用串行通信方式,数据以位为单位依次顺序传送。其显著特点是通信线路结构简洁,仅需一对传输线即可实现双向通信(可直接利用电话线作为传输媒介),从而大幅度降低了成本,尤其适用于远距离通信场景。然而,这一方式的传送速度相对较慢。
UART四要素:
- 数据位的位数。数据位的位数由通信双方共同约定,一般可以是 5~8 位。
- 奇偶校验位。通信双方共同约定是否具备奇偶校验位。
- 停止位。停止时间长度。
- 波特率。波特率其实就是通信传输数据的速度,即每秒传输多少位。通信双方需在同一个波特率通信,否则会出现数据丢失、数据溢出和乱码等情况。
详细的串口资料可以上网查阅。
二、machine.UART类
machine.UART
类是 machine
模块中的一个核心硬件分类,其旨在实现对 UART(即通用异步收发器,Universal Asynchronous Receiver/Transmitter)设备的精确配置与高效操作。UART 作为一种广泛应用的串行通信协议,促进了两个设备间双向通信的实现。在物理结构层面,UART 依赖于两根数据线以维持其功能:一条用于接收数据(RX),另一条则负责发送数据(TX)。
通信的基本单元为一个字符,其位宽可灵活设定为 8 位或 9 位,这一设计特性赋予了 UART 在多种应用场景中的广泛适应性,包括但不限于数据采集、远程监控及设备间的通信需求。通过采用 machine.UART
类,用户能够简便地配置 UART 设备参数、实现数据的收发功能,并有效管理通信流程中的各类事件,从而确保通信过程的顺畅与高效。
下面是MicroPython库的machine.UART类链接。
类 UART – 双工串行通信总线 — MicroPython latest 文档
1. machine.UART类的构造对象
构造对象方法如下:
class machine.UART(id, ...)
使用示例:uart = UART(2)
构造函数的参数描述如下:
参数 | 描述 |
id | 串口号 |
返回值:UART
类对象
2. machine.UART类的方法(部分主要用到的)
(1)对象初始化
方法原型如下:
UART.init(
baudrate=9600, bits=8, parity=None, stop=1, tx=Pin(17), rx=Pin(16)*, ...
)
方法的参数描述如下(包括可能支持的其他仅限关键字的参数):
参数 | 描述 |
baudrate | baudrate 是 clock rate,波特率 |
bits | bits 是每个字符的位数,7、8 或 9 |
parity | parity 是奇偶校验,、0(偶数)或 1(奇数) |
stop | stop 是 stop 位数,1 或 2 |
tx | 指定要使用的 TX 引脚 |
rx | 指定要使用的 RX pin |
rts | 指定用于硬件接收流控制的 RTS(输出)引脚 |
cts | 指定用于硬件传输流量控制的 CTS(输入)引脚 |
txbuf | 指定 TX 缓冲区的长度(以字符为单位) |
rxbuf | 指定 RX 缓冲区的长度(以字符为单位) |
timeout | 指定等待第一个字符的时间(以毫秒为单位) |
timeout_char | 指定字符之间等待的时间(以毫秒为单位) |
invert | 指定要反转的信号
|
flow | 指定要使用的硬件流控制信号。 |
(2)关闭UART
方法原型如下:
UART.deinit()
关闭 UART 总线。
(3)读取字符
读取字符时,如果指定了最大字节数,则最多读取该数量的字节;若未指定,则尽可能多地读取数据。如果达到设定的超时时间,读取操作可能会提前结束。超时时间可以在构造函数中进行配置。
方法原型如下:
uart.read(nbytes[ ])
方法的参数描述如下:
参数 | 描述 |
nbytes | 读取 n 个字节数据 |
返回值:一个包含读取字节的字节对象。如果超时则返回 None。
(4)读取字符到buf中
如果指定读 n 个字节,那么最多读取 n 个字节,否则就读取尽可能多的数据。另外读取数据的长度不超过 buf 的长度。
方法原型如下:
uart.readinto(buf, nbytes[ ])
方法的参数描述如下:
参数 | 描述 |
buf | buf 存储区 |
nbytes | 读取 n 个字节数据 |
返回值:读取和存储到 buf 中的字节数。如果超时则返回 None。
(5)读一行数据,以换行符结尾
如果指定读 n 个字节,那么最多读取 n 个字节,否则就读取尽可能多的数据。另外读取数据的长度不超过 buf 的长度。
方法原型如下:
uart.readline()
返回值:读入的行数,如果超时则返回 None。
(6)将buf中的数据写入总线
方法原型如下:
uart.write(buf)
方法的参数描述如下:
参数 | 描述 |
buf | buf 存储区 |
返回值:写入的字节数,如果超时则返回 None。
(7)检查是否有可读的数据
方法原型如下:
uart.any()
返回值:可读数据长度。
三、硬件设计
1. 例程功能
实现ESP32与上位机之间的串口对话机制,确保ESP32在接收到上位机发送的字符串后,能够准确无误地将其回传至上位机,从而实现双向的数据交换功能。
2. 硬件资源
- USART2 :IO16 IO17 连接串口工具 RX、TX引脚。
3. 原理图
四、软件设计
1. 程序流程图
2. 程序
from machine import UART, Pin, Timer
# 计数器,用于统计多久没有接收到串口数据
times_num = 0
# Timer实例化
timer = Timer(1)
# UART实例化
uart = UART(2)
# 初始化uart
uart.init(115200, 8, tx=Pin(17), rx=Pin(16))
def UART_TIMEX_INT_IRQHandler(timer):
"""
定时器中断处理函数
:param timer: 定时器
"""
global times_num
# 判断UART有无收到信息
if uart.any():
text = uart.read(128) # 接收 128 个以内的字符
uart.write(b"Received UART data:" + text + b"\r\n") # 串口打印接收到的数据
print(b"Received UART data:" + text + b"\r\n") # REPL也打印,方便调试
times_num = 0 # 计数器清 0
else:
# 没有接收到信息,计数器加1
times_num += 1
# 判断计数器是否超时,如果超过5秒,提醒输入数据
if times_num == 500:
uart.write(b"Please input datas...\r\n") # 提示
times_num = 0 # 计数器清 0
# 初始化定时器, 10ms进入一次中断
timer.init(mode=timer.PERIODIC, period=10, callback=UART_TIMEX_INT_IRQHandler)
五、下载验证
实现了ESP32与上位机之间的串口对话机制,确保ESP32在接收到上位机发送的字符串后,能够准确无误地将其回传至上位机,同时也能在REPL上打印数据。