一、概述
ESP32 有三个 UART 控制器(UART0、UART1 和 UART2,且都可以独立配置波特率,数据位长度,停止位数,奇偶校验位等参数。
通过ESP32 手册发现几乎所有的GPIO 都可以设置为串口接收发送引脚
UART 配置:
-
设置通信参数- 设置波特率、数据位、停止位等
-
设置通信引脚- 分配用于连接到设备的引脚。
-
驱动程序安装- 为 UART 驱动程序分配 ESP32 的资源。
-
运行 UART 通信- 发送/接收数据
-
使用中断- 在特定通信事件上触发中断
二、 串口操作 API
参数配置结构:
/**
* @brief UART configuration parameters for uart_param_config function
*/
typedef struct {
int baud_rate; /*!< UART baud rate*/
uart_word_length_t data_bits; /*!< UART byte size*/
uart_parity_t parity; /*!< UART parity mode*/
uart_stop_bits_t stop_bits; /*!< UART stop bits*/
uart_hw_flowcontrol_t flow_ctrl; /*!< UART HW flow control mode (cts/rts)*/
uint8_t rx_flow_ctrl_thresh; /*!< UART HW RTS threshold*/
union {
uart_sclk_t source_clk; /*!< UART source clock selection */
bool use_ref_tick __attribute__((deprecated)); /*!< Deprecated method to select ref tick clock source, set source_clk field instead */
};
} uart_config_t;
序号 | API | 作用 |
---|---|---|
1 | uart_driver_install() | 安装UART 驱动 |
2 | uart_param_config() | 是配置参数生效 |
3 | uart_set_pin() | 设置UART 管脚 |
4 | uart_pattern_queue_reset() | 给对列分配内存,将检测到的模式位置记录保存在 rx 缓冲区中 |
demo
#define UART_NUMx (UART_NUM_0)
/*使用默认GPIO */
#define TXD_PIN (UART_PIN_NO_CHANGE)
#define RXD_PIN (UART_PIN_NO_CHANGE)
static const char *TAG = "uart_events";
int RX_BUF_SIZE = 1024;
static QueueHandle_t uart0_queue;
/**
* @brief 串口事件
*
* @return
* - None
*/
static void uart_event_task(void *pvParameters)
{
uart_event_t event;
size_t buffered_size;
uint8_t* recv_buffer = (uint8_t*) malloc(RX_BUF_SIZE);
for(;;) {
if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
memset(recv_buffer,0,sizeof(RX_BUF_SIZE));
switch(event.type) {
case UART_DATA: //UART 数据事件
/*将接收的数据写入 recv_buffer*/
uart_read_bytes(UART_NUMx, recv_buffer, event.size, portMAX_DELAY);
/*串口打印出来*/
uart_write_bytes(UART_NUMx, (const char*) recv_buffer, event.size);
break;
case UART_FIFO_OVF: //UART FIFO 溢出事件
ESP_LOGI(TAG, "hw fifo overflow");
uart_flush_input(UART_NUMx);
xQueueReset(uart0_queue);
break;
case UART_BUFFER_FULL://UART RX 缓冲区已满事件
ESP_LOGI(TAG, "ring buffer full");
uart_flush_input(UART_NUMx);
xQueueReset(uart0_queue);
break;
case UART_BREAK://UART RX 中断 事件
ESP_LOGI(TAG, "uart rx break");
break;
case UART_PARITY_ERR: //UART RX 奇偶校验事件
ESP_LOGI(TAG, "uart parity error");
break;
case UART_FRAME_ERR://UART RX 帧错误事件
ESP_LOGI(TAG, "uart frame error");
break;
case UART_PATTERN_DET:// UART 输入类型检测
break;
//Others
default:
ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
}
}
free(recv_buffer);
recv_buffer = NULL;
vTaskDelete(NULL);
}
/**
* @brief init uart
*
* @return
* - ESP_OK: Success
* - Others: Fail
*/
esp_err_t dev_uart_init(void)
{
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_DISABLE,
.source_clk = UART_SCLK_APB,
};
uart_driver_install(UART_NUMx, RX_BUF_SIZE * 2,RX_BUF_SIZE * 2,20, &uart0_queue, 0);
uart_param_config(UART_NUMx, &uart_config);
uart_set_pin(UART_NUMx, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
//使能模式检测功能
//uart_enable_pattern_det_baud_intr(UART_NUMx, '+', 3, 9, 0, 0);
//分配具有给定长度的新内存,以将检测到的模式位置记录保存在 rx 缓冲区中。
uart_pattern_queue_reset(UART_NUMx, 20);
//Create a task to handler UART event from ISR
xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 12, NULL);
return ESP_OK;
}
void app_main(void)
{
dev_uart_init();
}
demo 现象
三、总结
通过参考官方的demo 和文档学习ESP32 外设,其实还是比较简单的。ESP32 实在是太强了,居然每个GPIO 都可以配置成串口引脚,不得不说 666!