一、概述
UART是一种通用异步收发送器,在ESP32中有3个UART(UART0、UART1和UART2),但是在ESP32-S2中只有2个UART(UART0和UART1)。
每个UART控制器都需要单独配置数据,参数包括波特率、数据比特长度、停止位等。在ESP32-S2中,由于UART0主要用于烧录程序,所以串口的数据传输最好是使用UART1,避免发生冲突。
ESP32的串口是可以支持引脚映射的,比如ESP32-S2的UART1的引脚默认是GPIO17和GPIO18,当我GPIO18引脚被占用时,可以将TX和RX映射到GPIO17和GPIO16上。
二、使用说明
2.1设置参数(波特率、数据位、停止位等)
一般波特率设置为115200或9600
2.2设置通信引脚
调用uart_set_pin()函数指定Tx、Rx、RTS和CTS的GPIO引脚号,并且指定使用UART0或者UART1。
RTS是模块的输入端,用于MCU通知模块,MCU是否准备好,模块是否可向MCU发送信息,RTS的有效电平为低。
CTS是模块的输出端,用于模块通知MCU,模块是否准备好,MCU是否可向模块发送信息,CTS的有效电平为低。
从文字看,RTS和CTS是独立的,不存在每次单向数据传输的发起者问题。如果主机输出RTS有效,那么模块有数据就会发往主机;如果模块输出CTS有效,那么主机就可以将数据送达模块接收。
硬流控的RTS 、CTS :RTS (Require To Send,发送请求)为输出信号,用于指示本设备准备好可接收;CTS(Clear To Send,发送清除)为输入信号,有效时停止发送。假定A、B两设备通信,A设备的RTS 连接B设备的CTS ;A设备的CTS 连接B设备 的RTS 。 前一路信号控制B设备的发送,后一路信号控制A设备的发送。对B设备的发送(A设备接收)来说,如果A设备接收缓冲快满的时发出RTS 信号(意思 通知B设备停止发送),B设备通过CTS 检测到该信号,停止发送;一段时间后A设备接收缓冲有了空余,发出RTS 信号,指示B设备开始发送数据。A设备发(B设备接收) 类似。
在宏中可以定义引脚号或者不做更改,不使用。
2.3安装驱动程序
设置好参数和引脚后,通过调用安装函数uart_driver_install(uart_num, rx_buffer_size, tx_buffer_size, queue_size, uart_queue, intr_alloc_flags),并设置好以下参数:
uart_num:UART端口号;
rx_buffer_size:UART RX缓存区的大小;
tx_buffer_size:UART TX缓存区的大小;
queue_size: UART事件队列的大小/深度
uart_queue: UART事件队列句柄,如果设置为NULL,驱动程序将不使用事件队列;
intr_alloc_flags:用于分配中断标志。
2.4UART的通信
串行通信是由每个UART控制器的FSM(有限状态机)控制。
发送数据的过程:
- 将数据写入Tx FIFO缓冲区
- FSM序列化数据
- FSM将数据发送出去
发送缓冲区data中的数据,长度为len。
接收数据过程:
- FSM处理传入的串行流将其并行化
- FSM将数据写入Rx FIFO缓冲区
- 从Rx FIFO缓冲区读取数据
读取缓冲区data的数据,长度为BUF_SIZE,也可以先调用函数
uart_get_buffered_data_len()将数据长度读取到length变量中。
三、UART引脚映射
目标:将UART1引脚默认值,改为TX GPIO16,RX GPIO17;
在ESO-IDF命令符窗口:
配置好使用的芯片型号:例如idf.py set-target esp32s2
1、使用idf.py menuconfig进入可视化配置,进入Component config --> Common ESP-related修改
选择Custom UART
修改TX和RX的值
四、循环读写
这里使用的UART1引脚是ESP32S2的默认值。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_log.h"
#define ECHO_TEST_TXD 17
#define ECHO_TEST_RXD 18
#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE)
#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE)
#define ECHO_UART_PORT_NUM UART_NUM_1
#define ECHO_UART_BAUD_RATE 115200//波特率
#define ECHO_TASK_STACK_SIZE 2048
#define BUF_SIZE (1024)
static void echo_task(void *arg)
{
uart_config_t uart_config = {
.baud_rate = ECHO_UART_BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
int intr_alloc_flags = 0;
#if CONFIG_UART_ISR_IN_IRAM
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif
ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS));
// Configure a temporary buffer for the incoming data
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
printf("start uart echo task\r\n");
while (1) {
// Read data from the UART
int len = uart_read_bytes(ECHO_UART_PORT_NUM, data, BUF_SIZE, 20 / portTICK_RATE_MS);//读取数据
// Write data back to the UART
uart_write_bytes(ECHO_UART_PORT_NUM, (const cha+r *) data, len);//发送数据
// memset(data,0,BUF_SIZE);//非必要
}
}
void app_main(void)
{
xTaskCreate(echo_task, "uart_echo_task", ECHO_TASK_STACK_SIZE, NULL, 10, NULL);//设置一个任务(无限循环)
}