嵌入式应用通常要求一个简单的并且占用系统资源少的方法来传输数据。通用异步收发传输器 (UART) 即可以满足这些要求,它能够灵活地与外部设备进行全双工数据交换。ESP32 芯片中有3个UART控制器可供使用,并且兼容不同的UART设备。另外,UART还可以用作红外数据交换 (IrDA) 或 RS-485 调制解调器。
Light-Sleep
状态时,会通过Wakeup_Ctrl
计算rxd_in
的脉冲个数,当Rxd边沿变化次数大于阈值时,传输给RTC模块来唤醒UART控制器;目前仅UART0和UART1具备Light-Sleep
功能,且rxd_in
不能通过GPIO交换矩阵,只能通过IO_MUX输入UART_RX_SIZE
对指定UART的FIFO进行扩展【最大1024Byte】,提高整体的利用率;当UART控制器不使用时,可以通过配置UART_MEM_PD
来使RAM进入低功耗状态注意:UART2 没有 Tx_FIFO 以及 Rx_FIFO 的复位寄存器。UART1 的 UART1_TXFIFO_RST 和 UART1_RXFIFO_RST 会影响 UART2 的工作。因此,只有在 UART2 的 Tx_FIFO 和 Rx_FIFO 中没有数据时,才可以置位这两个寄存器。
STOP
位可以通过UART_STOP_BIT_NUM、UART_DL1_EN 和 UART_DL0_EN
来配置1/1.5/2/3位宽;数据位通过UART_BIT_NUM
可配置5-8位;UART_PARITY
选择奇校验或偶校验;UART_TX_DONE_INT
中断;置位UART_TXD_BRK
寄存器可设置发送完成后可继续发送NULL数据帧;数据帧可通过UART_TX_IDEL_NUM
配置最小间隔UART 控制器有两种数据流控方式:硬件流控和软件流控。硬件流控主要通过输出信号 rtsn_out 以及输入信号dsrn_in 进行数据流控制。软件流控主要通过在发送数据流中插入特殊字符以及在接收数据流中检测特殊字符来实现数据流控功能。
UHCI×_UART_CE
寄存器选择配置。配置寄存器 | 描述 |
---|---|
UART_CONF0_REG | 配置寄存器0,选择配置时钟源 |
UART_CONFIG1_REG | 配置寄存器1,设置接收超时与流控功能 |
UART_CLKDIV_REG | 时钟分频配置寄存器 |
UART_FLOW_CONF_REG | 软件流控配置寄存器 |
UART_SWFC_CONF_REG | 软件流控字符配置 |
UART_SLEEP_CONF_REG | 休眠模式配置,设置RXD延边次数阈值 |
UART_IDEL_CONF_REG | 帧空闲配置寄存器,设置帧间隔与空帧数量 |
UART_RS485_CONF_REG | RS485模式配置寄存器 |
状态寄存器 | 描述 |
---|---|
UART_STATUS_REG | 串口状态寄存器,读取TXRX电平状态与FIFO有效数 |
波特率自检寄存器 | 描述 |
---|---|
UART_AUTOBAUD_REG | 自检波特率寄存器,配置自检使能与滤波门限 |
UART_LOWPULSE_REG | 自检波特率最小低脉冲寄存器,读取最小低电平脉冲宽度 |
UART_HIGHPULSE_MIN_CNT | 自检波特率最小高脉冲寄存器,读取最小高电平脉冲宽度 |
UART_POSPULSE_REG | 自检波特率高脉冲寄存器,检测上升沿次数 |
UART_NEGPULSE_REG | 自检波特率低脉冲寄存器,检测下升沿次数 |
UART_RXD_CNT_REG | 接收边沿计数寄存器,存储边沿变化次数 |
FIFO配置寄存器 | 描述 |
---|---|
UART_FIFO_REG | FIFO数据寄存器,读取RX接收数据 |
UART_MEM_CONF_REG | FIFO阈值设置与RAM空间分配 |
UART_MEM_CNT_STATUS_REG | 收发FIFI有效个数状态寄存器 |
中断寄存器 | 描述 |
---|---|
UART_INT_RAW_REG | 原始中断状态寄存器,获取相关的状态位 |
UART_INT_ST_REG | 隐藏中断状态寄存器 |
UART_INT_ENA_REG | 中断使能寄存器,配置相关中断使能位 |
UART_INT_CLR_REG | 清中断标志寄存器,置位清空相关中断 |
设置通信参数:接口esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config)
ESP_OK
表明配置成功const int uart_num = UART0;
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 parametersESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));
参数也可以单独调用接口配置
接口 | 描述 |
---|---|
uart_set_baudrate | 配置波特率 |
uart_set_word_length | 设置数据位 |
uart_set_parity | 设置校验模式 |
uart_set_stop_bits | 设置停止位 |
uart_set_sw_flow_ctrl | 设置流控 |
uart_set_mode | 设置模式 |
设置通信引脚:接口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_PIN_NO_CHANGE
// 设置串口引脚(TX: IO16 RX: IO17 RTS: IO18(UART2 default), , CTS: IO19(UART2 default), )
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, 16, 17, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
驱动安装:接口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_num
:串口号【0 - 2】rx_buffer_size
:硬件接收缓存大小,串口接收数据会自动缓存到BUFF中tx_buffer_size
:发送缓存大小,设为0时,发送的数据会进入堵塞状态等待发送完成queue_size
:串口事件的队列大小uart_queue
:串口事件的队列句柄,用于串口事件触发时数据同步intr_alloc_flags
:中断分配的标识,默认填0驱动删除:接口esp_err_t uart_driver_delete(uart_port_t uart_num)
通信发送:接口int uart_write_bytes(uart_port_t uart_num, const void *src, size_t size)
tx_buffer_size
大于0,会将数据拷贝到FIFI缓冲器中并立即返回数据接收:接口int uart_read_bytes(uart_port_t uart_num, void *buf, uint32_t length, TickType_t ticks_to_wait)
ticks_to_wait
超时时间内,读取最大长度为length
的数据中断使用:串口状态或检测到错误时,可使能指定中断触发
uart_event_type_t
定义了相关的事件,可通过uart_driver_install
接口分配队列,利用FreeRtos进行数据传递,可参考peripherals/uart/uart_events
代码uart_intr_config
配置,查看数据结构uart_intr_config_t
选择事件绑定uart_enable_pattern_det_intr
进行使能,主要应用AT命令应用中,单硬件检测到连续相同的字符时,触发中断,可参考peripherals/uart/uart_events
代码例程可参考idf目录下的test_uart.c,路径esp-idf\components\driver\test
#define UART_NUM1 (UART_NUM_1)//端口
#define BUF_SIZE (256)//缓存,大于128byte
#define UART1_RX_PIN (17)//关联引脚
#define UART1_TX_PIN (16)
#define UART1_RTS_PIN (UART_PIN_NO_CHANGE)
#define UART1_CTS_PIN (UART_PIN_NO_CHANGE)
static void test_task(void *pvParameters)
{
uint8_t recvbuf[BUF_SIZE];
int len;
uart_config_t uart_config =
{
.baud_rate = 115200,//波特率
.data_bits = UART_DATA_8_BITS,//8位数据
.parity = UART_PARITY_DISABLE,//不校验
.stop_bits = UART_STOP_BITS_1,//1位停止位
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,//禁用流控
.source_clk = UART_SCLK_APB,//apb时钟源
};
uart_driver_install(UART_NUM1, BUF_SIZE, 0, 0, NULL, 0);//驱动安装
uart_param_config(UART_NUM1, &uart_config);//配置参数
uart_set_pin(UART_NUM1, UART1_TX_PIN, UART1_RX_PIN, UART1_RTS_PIN, UART1_CTS_PIN);//配置引脚
while(1)
{
len = uart_read_bytes(UART_NUM1, recvbuf, BUF_SIZE, 100 / portTICK_RATE_MS);//读取数据
if(len)
{
uart_write_bytes(UART_NUM1, (const char *) recvbuf, len);//返回接收数据
}
}
}
当引脚不够时,考虑使用UART0时,只需要在app_mian里面重新配置下UART0即可