ESP32 一共有三个 UART 通讯接口,设备号从 0~2,即 UART0,UART1,UART2。这三个串口的管脚不 是固定的,是可以重映射到任意的 IO 口的。
ESP32 的 BOOT 程序把 UART0 用于程序下载,LOG 输出,我们的第一个实验 hello world 的 LOG 就是从 UART0 输出的。在 BOOT 程序里,把 UART0 映射到 IO1(RX0)和 IO3(TX0)上,我们板子的硬件上也是 把 IO1 和 IO3 通过拨码开关连接到 CH340G 芯片上的
下图为我们实验里三个串口的 IO 口映射表
ESP32 串口使用的基本步骤:
设置通信参数:包括波特率、数据位、停止位等
IO 口关联:设置 UART 和具体的物理 GPIO 引脚关联
驱动器安装:为 UART 驱动程序分配 ESP 32 的资源
运行 UART 通信:开始发送/接收数据,接收数据一般是写在任务函数里。
(1) 设置通信参数
设置串口参数结构定义如下: 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 = UART_HW_FLOWCTRL_DISABLE,//控制模式
};
设置参数的函数定义如下:
esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config);
参数说明:
uart_port_t uart_num:串口号,支持 UART_NUM_0,UART_NUM_1,UART_NUM_2 const uart_config_t *uart_config:要设置的参数
(2) IO 口关联
设置串口和具体的 IO 引脚关联,通过函数 uart_set_pin 实现,函数定义如下:
esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) 参数说明:
uart_port_t uart_num:串口号,支持 UART_NUM_0,UART_NUM_1,UART_NUM_2 int tx_io_num:串口接收管脚
int rx_io_num:串口发送管脚 int rts_io_num:串口流控脚 int cts_io_num:串口流控脚
如下,表示把串口 1 映射到 IO4 和 IO5 上:
uart_set_pin(UART_NUM_1, GPIO_NUM_5, GPIO_NUM_4, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
(3) 驱动器安装
分配接收发送空间及函数调用参数,使用到函数为 uart_driver_install,这个函数定义如下:
esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int intr_alloc_flags)
参数说明:
uart_port_t uart_num:串口号,支持 UART_NUM_0,UART_NUM_1,UART_NUM_2 int rx_buffer_size:接收缓存大小
int tx_buffer_size:发送缓存大小 int queue_size:队列大小
QueueHandle_t *uart_queue:串口队列指针 int intr_alloc_flags:分配中断标记
(4) UART 通信
串口通信分为两部分:接收和发送。
1 串口数据接收使用函数 uart_read_bytes,一般接收函数是写在任务里,这个函数定义:
int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait) 参数说明:
uart_port_t uart_num:串口号,支持 UART_NUM_0,UART_NUM_1,UART_NUM_2 uint8_t* buf:接收数据缓冲地址
uint32_t length:接收缓冲区长度 TickType_t ticks_to_wait:等待时间
2 串口数据接收使用函数 uart_write_bytes,这个函数定义:
int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size) 参数说明:
uart_port_t uart_num:串口号,支持 UART_NUM_0,UART_NUM_1,UART_NUM_2 const char* src:待发送数据
size_t size:发送数据大小
(5) 任务的创建和删除
第 4 点在讲到 UART 通信的时候,说到串口的接收数据要运行在任务里。关于创建任务是使用函数 xTaskCreate 实现,要使用这个函数,首先要包括头文件:task.h。
删除任务函数:
void vTaskDelete( xTaskHandle pxTask );
(1) 初始化串口
void uart_init(void)
{
//串口配置结构体
uart_config_t uart0_config, uart1_config,uart2_config;
//串口参数配置->uart0
uart0_config.baud_rate = 115200; //波特率 uart0_config.data_bits = UART_DATA_8_BITS; //数据位
uart0_config.parity = UART_PARITY_DISABLE; //校验位
uart0_config.stop_bits = UART_STOP_BITS_1; //停止位 uart0_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; //硬件流控 uart_param_config(UART_NUM_0, &uart0_config); //设置串口
uart_set_pin(UART_NUM_0, TXD0_PIN, RXD0_PIN, UART_PIN_NO_CHANGE, //esp32 三路串口初始化
void uart_init(void)
{
//串口配置结构体
uart_config_t uart0_config, uart1_config,uart2_config;
//串口参数配置->uart0
uart0_config.baud_rate = 115200; //波特率 uart0_config.data_bits = UART_DATA_8_BITS; //数据位
uart0_config.parity = UART_PARITY_DISABLE; //校验位
uart0_config.stop_bits = UART_STOP_BITS_1; //停止位 uart0_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; //硬件流 uart_param_config(UART_NUM_0, &uart0_config); //设置串口uart_set_pin(UART_NUM_0, TXD0_PIN, RXD0_PIN, UART_PIN_NO_CHANGE,
任务接收函数
// 串口 0 接收任务 void uart0_rx_task()
{
uint8_t* data = (uint8_t*) malloc(RX0_BUF_SIZE+1); while (1) {
//获取串口 1 接收的数据
const int rxBytes = uart_read_bytes(UART_NUM_0, data, RX0_BUF_SIZE, 10 / portT
ICK_RATE_MS);
data[rxBytes] = 0;
uart_write_bytes(UART_NUM_0, "uart0 cb\r\n", strlen("uart0 cb\r\n"));
//将接收到的数据发出去
uart_write_bytes(UART_NUM_0, (char *)data, rxBytes);
}
}
free(data);
}
//串口 1 接收任务 void uart1_rx_task()
{
uint8_t* data = (uint8_t*) malloc(RX1_BUF_SIZE+1); while (1) {
//获取串口 1 接收的数据
const int rxBytes = uart_read_bytes(UART_NUM_1, data, RX1_BUF_SIZE, 10 / portT
ICK_RATE_MS);
if (rxBytes > 0) {
data[rxBytes] = 0;
uart_write_bytes(UART_NUM_1, "uart1 cb\r\n", strlen("uart1 cb\r\n"));
//将接收到的数据发出去
uart_write_bytes(UART_NUM_1, (char *)data, rxBytes);
}
}
free(data);
}
//串口 2 接收任务 void uart2_rx_task()
{
uint8_t* data = (uint8_t*) malloc(RX2_BUF_SIZE+1); while (1) {
const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX2_BUF_SIZE, 10 / portT
ICK_RATE_MS);
if (rxBytes > 0) {
data[rxBytes] = 0;
uart_write_bytes(UART_NUM_2, "uart2 cb\r\n", strlen("uart2 cb\r\n"));
//将接收到的数据发出去
uart_write_bytes(UART_NUM_2, (char *)data, rxBytes);
}
}
free(data);
按下开发板的复位键,可以看到串口工具有数据输出,输入到串口工具点发送后,观察串口工具 的输出。
最后推荐一款开发套件,可以手淘扫码查看。