ESP32串口通信详解:UART介绍与应用

简介

通用异步接收器/发送器 (UART) 属于一种硬件功能,通过使用 RS232、RS422、RS485 等常见异步串行通信接口来处理通信时序要求和数据帧。UART 是实现不同设备之间全双工或半双工数据交换的一种常用且经济的方式。

ESP32 芯片有三个 UART 控制器(也称为端口),每个控制器都有一组相同的寄存器以简化编程并提高灵活性。

每个 UART 控制器可以独立配置波特率、数据位长度、位顺序、停止位位数、奇偶校验位等参数。所有控制器都与不同制造商的 UART 设备兼容,并且支持红外数据协会 (IrDA) 定义的标准协议。

功能概述

下文介绍了如何使用 UART 驱动程序的函数和数据类型在 ESP32 和其他 UART 设备之间建立通信。基本编程流程分为以下几个步骤:

设置通信参数 — 设置波特率、数据位、停止位等
设置通信管脚 — 分配连接设备的管脚
安装驱动程序 — 为 UART 驱动程序分配 ESP32 资源
运行 UART 通信 — 发送/接收数据
使用中断 — 触发特定通信事件的中断
删除驱动程序 — 如无需 UART 通信,则释放已分配的资源

步骤 1 到 3 为配置阶段,步骤 4 为 UART 运行阶段,步骤 5 和 6 为可选步骤。

UART 驱动程序函数通过 uart_port_t 识别不同的 UART 控制器。调用以下所有函数均需此标识。

设置通用参数

UART 通信参数可以在一个步骤中完成全部配置,也可以在多个步骤中单独配置。

一次性配置所有参数

调用函数 uart_param_config() 并向其传递 uart_config_t 结构体,uart_config_t 结构体应包含所有必要的参数。请参考以下示例。

const uart_port_t uart_num = UART_NUM_2;
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
.rx_flow_ctrl_thresh = 122,
};
// Configure UART parameters
ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));

了解配置硬件流控模式的更多信息,请参考 peripherals/uart/uart_echo

分步依次配置每个参数

调用下表中的专用函数,能够单独配置特定参数。如需重新配置某个参数,也可使用这些函数。

表中每个函数都可使用 get 对应项来查看当前设置值。例如,查看当前波特率值,请调用 uart_get_baudrate()。

设置通信管脚

通信参数设置完成后,可以配置其他 UART 设备连接的 GPIO 管脚。调用函数 uart_set_pin(),指定配置 Tx、Rx、RTS 和 CTS 信号的 GPIO 管脚编号。如要为特定信号保留当前分配的管脚编号,可传递宏 UART_PIN_NO_CHANGE。

请为不使用的管脚都指定为宏 UART_PIN_NO_CHANGE。

// Set UART pins(TX: IO4, RX: IO5, RTS: IO18, CTS: IO19)
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, 4, 5, 18, 19));

安装驱动程序

通信管脚设置完成后,请调用 uart_driver_install() 安装驱动程序并指定以下参数:
1、Tx 环形缓冲区的大小
2、Rx 环形缓冲区的大小
3、事件队列句柄和大小
4、分配中断的标志
该函数将为 UART 驱动程序分配所需的内部资源。

// Setup UART buffered IO with event queue
const int uart_buffer_size = (1024 * 2);
QueueHandle_t uart_queue;
// Install UART driver using an event queue here
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, uart_buffer_size, \
                                    uart_buffer_size, 10, &uart_queue, 0));

此步骤完成后,可连接外部 UART 设备检查通信。

运行 UART 通信

串行通信由每个 UART 控制器的有限状态机 (FSM) 控制。
发送数据的过程分为以下步骤:

1、将数据写入 Tx FIFO 缓冲区
2、FSM 序列化数据
3、FSM 发送数据

接收数据的过程类似,只是步骤相反:

1、FSM 处理且并行化传入的串行流
2、FSM 将数据写入 Rx FIFO 缓冲区
3、从 Rx FIFO 缓冲区读取数据

因此,应用程序仅会通过 uart_write_bytes() 和 uart_read_bytes() 从特定缓冲区写入或读取数据,其余工作由 FSM 完成。

发送数据

发送数据准备好后,调用函数 uart_write_bytes(),并向其传递数据缓冲区的地址和数据长度。该函数会立即或在有足够可用空间时将数据复制到 Tx 环形缓冲区,随后退出。当 Tx FIFO 缓冲区中有可用空间时,中断服务例程 (ISR) 会在后台将数据从 Tx 环形缓冲区移动到 Tx FIFO 缓冲区。调用函数请参考以下代码。

// Write data to UART.
char* test_str = "This is a test string.\n";
uart_write_bytes(uart_num, (const char*)test_str, strlen(test_str));

函数 uart_write_bytes_with_break() 与 uart_write_bytes() 类似,但在传输结束时会添加串行中断信号。“串行中断信号”意味着 Tx 线保持低电平的时间长于一个数据帧。

// Write data to UART, end with a break signal.
uart_write_bytes_with_break(uart_num, "test break\n",strlen("test break\n"), 100);

能够将数据写入 Tx FIFO 缓冲区的另一函数是 uart_tx_chars()。 与 uart_write_bytes() 不同,此函数在没有可用空间之前不会阻塞。相反,它将写入所有可以立即放入硬件 Tx FIFO 的数据,然后返回写入的字节数。

“配套”函数 uart_wait_tx_done() 用于监听 Tx FIFO 缓冲区的状态,并在缓冲区为空时返回。

// Wait for packet to be sent
const uart_port_t uart_num = UART_NUM_2;
ESP_ERROR_CHECK(uart_wait_tx_done(uart_num, 100)); // wait timeout is 100 RTOS ticks (TickType_t)

接受数据

一旦数据被 UART 接收并保存在 Rx FIFO 缓冲区中,就需要使用函数 uart_read_bytes() 检索数据。读取数据之前,调用 uart_get_buffered_data_len() 能够查看 Rx FIFO 缓冲区中可用的字节数。请参考以下示例。

// Read data from UART.
const uart_port_t uart_num = UART_NUM_2;
uint8_t data[128];
int length = 0;
ESP_ERROR_CHECK(uart_get_buffered_data_len(uart_num, (size_t*)&length));
length = uart_read_bytes(uart_num, data, length, 100);

如果不再需要 Rx FIFO 缓冲区中的数据,可以调用 uart_flush() 清空缓冲区。

软件流控

如果硬件流控被禁用,您可使用函数 uart_set_rts() 和 uart_set_dtr() 分别手动设置 RTS 和 DTR 信号电平。

通信方式选择

UART 控制器支持多种通信模式,使用函数 uart_set_mode() 可以选择模式。选择特定模式后,UART 驱动程序将处理已连接 UART 设备的相应行为。例如,使用 RTS 线控制 RS485 驱动芯片,能够实现半双工 RS485 通信。

// Setup UART in rs485 half duplex mode
	ESP_ERROR_CHECK(uart_set_mode(uart_num,UART_MODE_RS485_HALF_DUPLEX));

使用中断

根据特定的 UART 状态或检测到的错误,可以生成许多不同的中断。ESP32 技术参考手册 > UART 控制器 (UART) > UART 中断 和 UHCI 中断 [PDF] 中提供了可用中断的完整列表。调用 uart_enable_intr_mask() 或 uart_disable_intr_mask() 能够分别启用或禁用特定中断。

调用 uart_driver_install() 函数可以安装驱动程序的内部中断处理程序,用以管理 Tx 和 Rx 环形缓冲区,并提供事件等高级 API 函数(见下文)。

API 提供了一种便利的方法来处理本文所讨论的特定中断,即用专用函数包装中断:

事件检测:uart_event_type_t 定义了多个事件,使用 FreeRTOS 队列功能能够将其报告给用户应用程序。您可调用 安装驱动程序 中的 uart_driver_install() 函数启用此功能,请参考 peripherals/uart/uart_events 中使用事件检测的示例。

达到 FIFO 空间阈值或传输超时:Tx 和 Rx FIFO 缓冲区在填充特定数量的字符和在发送或接收数据超时的情况下将会触发中断。如要使用此类中断,请执行以下操作:

配置缓冲区长度和超时阈值:在结构体 uart_intr_config_t 中输入相应阈值并调用 uart_intr_config()

启用中断:调用函数 uart_enable_tx_intr() 和 uart_enable_rx_intr()

禁用中断:调用函数 uart_disable_tx_intr() 或 uart_disable_rx_intr()

模式检测:在检测到重复接收/发送同一字符的“模式”时触发中断,请参考示例 peripherals/uart/uart_events。例如,模式检测可用于检测命令字符串末尾是否存在特定数量的相同字符(“模式”)。可以调用以下函数:

配置并启用此中断:调用 uart_enable_pattern_det_intr()

禁用中断:调用 uart_disable_pattern_det_intr()

宏指令

API 还定义了一些宏指令。例如,UART_FIFO_LEN 定义了硬件 FIFO 缓冲区的长度,UART_BITRATE_MAX 定义了 UART 控制器支持的最大波特率。

删除驱动程序

如果不再需要与 uart_driver_install() 建立通信,则可调用 uart_driver_delete() 删除驱动程序,释放已分配的资源。

物联沃分享整理
物联沃-IOTWORD物联网 » ESP32串口通信详解:UART介绍与应用

发表评论