提示:本博客作为学习笔记,有错误的地方希望指正
一、ESP32串口介绍
??UART 是一种以字符为导向的通用数据链,可以实现设备间的通信。异步传输的意思是不需要在发送数据上添加时钟信息。这也要求发送端和接收端的速率、停止位、奇偶校验位等都要相同,通信才能成功。 ??一个典型的 UART 帧开始于一个起始位,紧接着是有效数据,然后是奇偶校验位(可有可无),最后是停止位。 ??ESP32 上的 UART 控制器支持多种字符长度和停止位。另外,控制器还支持软硬件流控和 DMA,可以实现无缝高速的数据传输。开发者可以使用多个 UART 端口,同时又能保证很少的软件开销。 ??ESP32 芯片中有 3 个 UART 控制器可供使用,并且兼容不同的 UART 设备。另外,UART 还可以用作红外数据交换 (IrDA) 或 RS-485 调制解调器。 ? 可编程收发波特率 ? 3 个 UART 的发送 FIFO 以及接收 FIFO 共享 1024 × 8-bit RAM ? 全双工异步通信 ? 支持输入信号波特率自检功能 ? 支持 5/6/7/8 位数据长度 ? 支持 1/1.5/2/3 个停止位 ? 支持奇偶校验位 ? 支持 RS485 协议 ? 支持 IrDA 协议 ? 支持 DMA 高速数据通信 ? 支持 UART 唤醒模式 ? 支持软件流控和硬件流控 ??值得注意的是ESP32的三路串口中串口0不支持引脚的修改默认是RGIO1作为RX,GPIO3作为TX,配置的时候需要注意下,串口0默认使用作为下载程序使用和ESP_LOG的输出。UART1默认引脚是GPIO9用作U1RXD,GPIO10用作U1TXD,但是这两个引脚也是用于外接flash的,因此在使用UART1的时候需要设置其他引脚,UART2默认引脚是GPIO16用作U2RXD,GPIO17用作U2TXD。
二、硬件设计
??这里的硬件设置就是使用的是M5Stack的硬件来实现串口通讯协议实验演示的。
三、实现代码;
??初始化流程 ??其中串口的参数配置的话通过ESP-IDF项目配置菜单来配置串口引脚,配置-1的话默认原来的引脚。串口回声虫的话就是接收到的数据原封不动的发送出去。 ??初始化代码如下
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#define ECHO_TEST_TXD (CONFIG_EXAMPLE_UART_TXD)
#define ECHO_TEST_RXD (CONFIG_EXAMPLE_UART_RXD)
#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE)
#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE)
#define ECHO_UART_PORT_NUM (CONFIG_EXAMPLE_UART_PORT_NUM)
#define ECHO_UART_BAUD_RATE (CONFIG_EXAMPLE_UART_BAUD_RATE)
#define ECHO_TASK_STACK_SIZE (CONFIG_EXAMPLE_TASK_STACK_SIZE)
#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));
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
while (1) {
int len = uart_read_bytes(ECHO_UART_PORT_NUM, data, BUF_SIZE, 20 / portTICK_RATE_MS);
uart_write_bytes(ECHO_UART_PORT_NUM, (const char *) data, len);
}
}
void app_main(void)
{
xTaskCreate(echo_task, "uart_echo_task", ECHO_TASK_STACK_SIZE, NULL, 10, NULL);
}
四、串口实验演示结果
五、ESP32串口函数API
5.1、uart_types.h文件中的内容的API
??uart_types.h文件中的内容基本上实现的是一些串口协议的设置结构体
typedef int uart_port_t;
typedef enum {
UART_MODE_UART = 0x00,
UART_MODE_RS485_HALF_DUPLEX = 0x01,
UART_MODE_IRDA = 0x02,
UART_MODE_RS485_COLLISION_DETECT = 0x03,
uart_mod_rs485_app_ctrl = 0x04,
} uart_mode_t;
typedef enum {
UART_DATA_5_BITS = 0x0,
UART_DATA_6_BITS = 0x1,
UART_DATA_7_BITS = 0x2,
UART_DATA_8_BITS = 0x3,
UART_DATA_BITS_MAX = 0x4,
} uart_word_length_t;
typedef enum {
UART_STOP_BITS_1 = 0x1,
UART_STOP_BITS_1_5 = 0x2,
UART_STOP_BITS_2 = 0x3,
UART_STOP_BITS_MAX = 0x4,
} uart_stop_bits_t;
typedef enum {
UART_PARITY_DISABLE = 0x0,
UART_PARITY_EVEN = 0x2,
UART_PARITY_ODD = 0x3
} uart_parity_t;
typedef enum {
UART_HW_FLOWCTRL_DISABLE = 0x0,
UART_HW_FLOWCTRL_RTS = 0x1,
UART_HW_FLOWCTRL_CTS = 0x2,
UART_HW_FLOWCTRL_CTS_RTS = 0x3,
UART_HW_FLOWCTRL_MAX = 0 x4,
} uart_hw_flowcontrol_t;
typedef enum {
Uart_signal_inv_disable = 0,
UART_SIGNAL_IRDA_TX_INV = (0x1 << 0),
UART_SIGNAL_IRDA_RX_INV = (0x1 << 1),
UART_SIGNAL_RXD_INV = (0x1 << 2),
UART_SIGNAL_CTS_INV = (0x1 << 3),
UART_SIGNAL_DSR_INV = (0x1 << 4),
UART_SIGNAL_TXD_INV = (0x1 << 5),
UART_SIGNAL_RTS_INV = (0x1 << 6),
UART_SIGNAL_DTR_INV = (0x1 << 7),
} uart_signal_inv_t;
typedef enum {
UART_SCLK_APB = 0x0,
#if SOC_UART_SUPPORT_RTC_CLK
UART_SCLK_RTC = 0x1,
# endif
#if SOC_UART_SUPPORT_XTAL_CLK
UART_SCLK_XTAL = 0x2,
# endif
#if SOC_UART_SUPPORT_REF_TICK
UART_SCLK_REF_TICK = 0x3,
# endif
} uart_sclk_t;
typedef struct {
uint8_t cmd_char;
uint8_t char_num;
uint32_t gap_tout;
uint32_t pre_idle;
uint32_t post_idle;
} uart_at_cmd_t;
typedef struct {
uint8_t xon_char;
uint8_t xoff_char;
uint8_t xon_thrd;
uint8_t xoff_thrd;
} uart_sw_flowctrl_t;
typedef struct {
int baud_rate;
uart_word_length_t data_bits;
uart_parity_t parity;
uart_stop_bits_t stop_bits;
uart_hw_flowcontrol_t flow_ctrl;
uint8_t rx_flow_ctrl_thresh;
union{
uart_sclk_t source_clk;
bool use_ref_tick __attribute__((deprecated));
};
} uart_config_t;
5.2、在uart.h文件中的内容的API
??在uart.h文件中的内容就多一些,主要是ESP32串口的配置参数的架构体以及初始化函数和配置函数,还包括了串口事件等参数和函数API。温馨提示:可以给这些API复制到文本编辑器中,例如Vscode中,然后可以快速查找定位即可知道函数功能以及函数参数的含义。
#define UART_NUM_0 (0)
#define UART_NUM_1 (1)
#if SOC_UART_NUM > 2
#define UART_NUM_2 (2)
# endif
#define UART_NUM_MAX (SOC_UART_NUM)
#define UART_PIN_NO_CHANGE (1)
SOC_UART_FIFO_LEN
SOC_UART_BITRATE_MAX
typedef struct {
uint32_t intr_enable_mask;
uint8_t rx_timeout_thresh;
uint8_t txfifo_empty_intr_thresh;
uint8_t rxfifo_full_thresh;
} uart_intr_config_t;
typedef enum {
UART_DATA ,
UART_BREAK ,
UART_BUFFER_FULL ,
UART_FIFO_OVF ,
UART_FRAME_ERR ,
UART_PARITY_ERR ,
UART_DATA_BREAK ,
UART_PATTERN_DET ,
UART_EVENT_MAX ,
} uart_event_type_t;
typedef struct {
uart_event_type_t type;
size_t size;
bool timeout_flag;
} uart_event_t;
typedef intr_handle_t uart_isr_handle_t;
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);
esp_err_t uart_driver_delete (uart_port_t uart_num);
bool uart_is_driver_installed (uart_port_t uart_num);
esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit);
esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit);
esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit);
esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits);
esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bits);
esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode);
esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode);
esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate);
esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate);
esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask);
esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh);
esp_err_t uart_set_sw_flow_ctrl(uart_port_t uart_num, bool enable, uint8_t rx_thresh_xon, uint8_t rx_thresh_xoff);
esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl);
esp_err_t uart_clear_in t_status(uart_port_t uart_num, uint32_t clr_mask);
esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask);
esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask);
esp_err_t uart_enable_rx_intr (uart_port_t uart_num);
esp_err_t uart_disable_rx_intr (uart_port_t uart_num);
esp_err_t uart_disable_tx_intr (uart_port_t uart_num);
esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);
esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void* arg, int intr_alloc_flags, uart_isr_handle_t *handle);
esp_err_t uart_isr_free (uart_port_t uart_num);
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);
esp_err_t uart_set_rts(uart_port_t uart_num, int level);
esp_err_t uart_set_dtr(uart_port_t uart_num, int level);
esp_err_t uart_set_tx_idle_num(uart_port_t uart_num, uint 16_t idle_num);
esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config)
esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf);
esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait);
int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len);
int uart_write_bytes(uart_port_t uart_num, const void* src, size_t size);
int uart_write_bytes_with_break(uart_port_t uart_num, const void* src, size_t size, int brk_len);
int uart_read_bytes(uart_port_t uart_num, void* buf, uint32_t length, TickType_t ticks_to_wait);
esp_err_t uart_flush (uart_port_t uart_num);
esp_err_t uart_flush_input (uart_port_t uart_num);
esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size);
esp_err_t uart_disable_pattern_det_intr (uart_port_t uart_num);
#if CONFIG_IDF_TARGET_ESP32
esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle) __attribute__((deprecated));
# endif
esp_err_t uart_enable_pattern_det_baud_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle);
int uart_pattern_pop_pos (uart_port_t uart_num);
int uart_pattern_get_pos (uart_port_t uart_num);
esp_err_t uart_pattern_queue_reset(uart_port_t uart_num, int queue_length);
esp_err_t uart_set_mode(uart_port_t uart_num, uart_mode_t mode);
esp_err_t uart_set_rx_full_threshold(uart_port_t uart_num, int threshold);
esp_err_t uart_set_tx_empty_threshold(uart_port_t uart_num, int threshold);
esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh);
esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool* collision_flag);
esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold);
esp_err_t uart_get_wakeup_threshold(uart_port_t uart_num, int * out_wakeup_threshold);
esp_err_t uart_wait_tx_idle_polling (uart_port_t uart_num);
esp_err_t uart_set_loop_back(uart_port_t uart_num, bool loop_back_en);
Void uart_set_always_rx_timeout(uart_port_t uart_num, bool always_rx_timeout_en);
|