ESP32学习笔记(4)——UART串口使用

发布者:知识的海洋最新更新时间:2025-03-04 来源: jianshu关键字:ESP32  UART  串口使用 手机看文章 扫描二维码
随时随地手机看文章

一、概述

通用异步收发送器(UART)是一种硬件特性,它使用广泛适应的异步串行通信接口(如RS 232、RS 422、RS 485)来处理通信(即时序要求和数据帧)。UART提供了一种广泛采用和廉价的方法来实现不同设备之间的全双工或半双工数据交换。

ESP32芯片有三个UART控制器(UART 0、UART 1和UART 2),它们具有一组相同的寄存器,以便于编程和灵活性。

每个UART控制器都是独立配置的,参数包括波特率、数据比特长度、位序、停止位数、奇偶校验位等。所有控制器都与不同厂商的UART支持设备兼容,还可以支持红外数据关联协议(IRDA)。

ESP-IDF 编程指南——UART

二、API说明

以下 UART 接口位于 driver/include/driver/uart.h。

2.1 uart_param_config

2.2 uart_driver_install

2.3 uart_read_bytes

2.4 uart_write_bytes

2.5 uart_set_pin

ESP32的串口是支持引脚映射的,比如我的开发板串口一默认的是GPIO9和GPIO10,现在将TX、RX映射到GPIO4和GPIO5上。

三、编程流程

3.1 设置通信参数

如设置波特率、数据位、停止位等

在结构体中进行配置:


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;

3.2 设置通信引脚

ESP32的串口是支持引脚映射的,比如我的开发板串口一默认的是GPIO9和GPIO10,现在将TX、RX映射到GPIO4和GPIO5上。


请调用函数uart_set_pin()并指定驱动程序应将Tx,Rx,RTS和CTS信号路由至的GPIO引脚号。


如果要为特定信号保留当前分配的管脚号,请传递宏UART_PIN_NO_CHANGE。


应该为不使用的引脚指定相同的宏。


// Set UART pins(TX: IO17 (UART2 default), RX: IO16 (UART2 default), RTS: IO18, CTS: IO19)ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 18, 19));

3.3 驱动程序安装

设置好通信引脚后,通过调用安装驱动程序uart_driver_install()并指定以下参数:


Tx环形缓冲区的大小


Rx环形缓冲区的大小


事件队列句柄和大小


分配中断的标志


该功能将为UART驱动程序分配所需的内部资源。


// Setup UART buffered IO with event queueconst int uart_buffer_size = (1024 * 2);QueueHandle_t uart_queue;// Install UART driver using an event queue hereESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, uart_buffer_size,

                                        uart_buffer_size, 10, &uart_queue, 0));

3.4 运行UART通信

串行通信由每个UART控制器的有限状态机(FSM)控制。


发送数据的过程涉及以下步骤:


将数据写入Tx FIFO缓冲区


FSM序列化数据


FSM将数据发送出去


接收数据的过程类似,但是步骤相反:


FSM处理传入的串行流并将其并行化


FSM将数据写入Rx FIFO缓冲区


从Rx FIFO缓冲区读取数据


因此,应用程序将被限制为分别使用uart_write_bytes()和从相应的缓冲区写入和读取数据uart_read_bytes(),而FSM将完成其余的工作。


3.4.1 发送

准备好要传输的数据后,调用该函数uart_write_bytes()并将数据缓冲区的地址和数据长度传递给该函数。该函数将数据复制到Tx环形缓冲区(立即或在有足够空间可用之后),然后退出。当Tx FIFO缓冲区中有可用空间时,中断服务程序(ISR)将数据从Tx环形缓冲区移至后台的Tx FIFO缓冲区。下面的代码演示了此功能的用法。


// Write data to UART.char* test_str = 'This is a test string.n';uart_write_bytes(uart_num, (const char*)test_str, strlen(test_str));

该功能uart_write_bytes_with_break()类似于uart_write_bytes()但在传输结束时添加了一个串行中断信号。意味着它会在发送完数据之后,设置TX低电平一段时间(RTOS任务节拍为单位)。


// Write data to UART, end with a break signal.uart_write_bytes_with_break(uart_num, 'test breakn',strlen('test breakn'), 100);

将数据写入Tx FIFO缓冲区的另一个功能是uart_tx_chars()。不像uart_write_bytes(),此功能在可用空间之前不会阻塞。相反,它将写入可立即放入硬件Tx FIFO中的所有数据,然后返回已写入的字节数。


有一个“陪伴”功能uart_wait_tx_done(),可监视Tx FIFO缓冲区的状态并在其为空时返回。


// Wait for packet to be sentconst int uart_num = UART_NUM_2;ESP_ERROR_CHECK(uart_wait_tx_done(uart_num, 100)); // wait timeout is 100 RTOS ticks (TickType_t)

3.4.2 接收

UART接收到数据并将其保存在Rx FIFO缓冲区后,需要使用函数进行读出uart_read_bytes()。,这个函数会阻塞待在那里,直到读满需要的字节,或是超时。


在读取数据之前,您可以调用来检查Rx FIFO缓冲区中可用的字节数uart_get_buffered_data_len(),然后再读取相应的内容,这样就不会造成不必要的阻塞。下面给出了使用这些功能的示例。


// Read data from UART.const int uart_num = UART_NUM_2;uint8_t data[128];int length = 0;ESP_ERROR_CHECK(uart_get_buffered_data_len(uart_num, (size_t*)&length));length = uart_read_bytes(uart_num, data, length, 100);

如果不再需要Rx FIFO缓冲区中的数据,则可以通过调用清除缓冲区uart_flush()。


四、串口回环输出

这里我将GPIO4、GPIO5改成了GPIO23、GPIO18


#include #include 'freertos/FreeRTOS.h'#include 'freertos/task.h'#include 'driver/uart.h'#include 'driver/gpio.h'/**

 * This is an example which echos any data it receives on UART1 back to the sender,

 * with hardware flow control turned off. It does not use UART driver event queue.

 *

 * - Port: UART1

 * - Receive (Rx) buffer: on

 * - Transmit (Tx) buffer: off

 * - Flow control: off

 * - Event queue: off

 * - Pin assignment: see defines below

 */#define ECHO_TEST_TXD  (GPIO_NUM_23)#define ECHO_TEST_RXD  (GPIO_NUM_18)#define ECHO_TEST_RTS  (UART_PIN_NO_CHANGE)#define ECHO_TEST_CTS  (UART_PIN_NO_CHANGE)#define BUF_SIZE (1024)static void echo_task(void *arg){

    /* Configure parameters of an UART driver,

     * communication pins and install the driver */

    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_NUM_1, BUF_SIZE * 2, 0, 0, NULL, 0);

    uart_param_config(UART_NUM_1, &uart_config);

    uart_set_pin(UART_NUM_1, 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);


    while (1) {

        // Read data from the UART

        int len = uart_read_bytes(UART_NUM_1, data, BUF_SIZE, 20 / portTICK_RATE_MS);

        // Write data back to the UART

        uart_write_bytes(UART_NUM_1, (const char *) data, len);

    }}void app_main(void){

    xTaskCreate(echo_task, 'uart_echo_task', 1024, NULL, 10, NULL);}

五、串口队列接收

/*********************************************************************

 * INCLUDES

 */#include #include #include #include 'freertos/FreeRTOS.h'#include 'freertos/task.h'#include 'freertos/queue.h'#include 'driver/uart.h'#include 'esp_log.h'#define BUF_SIZE (1024)#define UART_MAX_NUM_RX_BYTES (1024)static void uartEventTask(void *pvParameters);/*********************************************************************

 * LOCAL VARIABLES

 */static QueueHandle_t s_uart0Queue;static const char *TAG = 'board_uart';/*********************************************************************

 * PUBLIC FUNCTIONS

 *//**

 @brief 串口驱动初始化

 @param 无

 @return 无

*/void UART_Init(void){

    // Configure parameters of an UART driver,

    // communication pins and install the driver

    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    };


    uart_param_config(UART_NUM_0, &uart_config);                                            // 配置串口0参数

    uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);// 配置串口0引脚

    // Install UART driver, and get the queue.

    uart_driver_install(UART_NUM_0, BUF_SIZE * 2, BUF_SIZE * 2, 100, &s_uart0Queue, 0);     // 安装UART驱动程序


    // Create a task to handler UART event from ISR

    xTaskCreate(uartEventTask, 'uartEventTask', 2048, NULL, 12, NULL);  }/*********************************************************************

 * LOCAL FUNCTIONS

 */static void uartEventTask(void *pvParameters){

    uart_event_t event;

    uint8_t *pTempBuf = (uint8_t *)malloc(UART_MAX_NUM_RX_BYTES);


    for(;;)

    {

        // Waiting for UART event.

        if(xQueueReceive(s_uart0Queue, (void *)&event, (portTickType)portMAX_DELAY))

        {

            bzero(pTempBuf, UART_MAX_NUM_RX_BYTES);


            switch(event.type)

            {

                // Event of UART receving data

                // We'd better handler data event fast, there would be much more data events than

                // other types of events. If we take too much time on data event, the queue might be full.

                case UART_DATA:

                    // ESP_LOGI(TAG, '[UART DATA]: %d', event.size);

                    uart_read_bytes(UART_NUM_0, pTempBuf, event.size, portMAX_DELAY);

                    uart_write_bytes(UART_NUM_0, (const char *)pTempBuf, event.size);

                    break;


                // Event of HW FIFO overflow detected

                case UART_FIFO_OVF:

                    ESP_LOGI(TAG, 'hw fifo overflow');

                    // If fifo overflow happened, you should consider adding flow control for your application.

[1] [2]
关键字:ESP32  UART  串口使用 引用地址:ESP32学习笔记(4)——UART串口使用

上一篇:ESP32学习笔记(5)——WiFi接口使用(STA和AP模式)
下一篇:ESP32学习笔记(3)——高分辨率定时器接口使用

推荐阅读最新更新时间:2026-03-25 13:28

STM32模拟串口(UART)使用
1、添加头文件 首先我们先添加相应的头文件。既然我们要进行对串口的模拟,因此我们要先了解uart相关的通信协议。由于UART的通信方式是由1个起始位,8个数据位,包含一个奇偶校验位,和结束位构成因此我们将使用单片机中的两个普通的IO口电平的高低进行对相应时序的模拟。 #include stm32f10x.h #include vuart2.h 2、宏定义 使用到的io口为 #defineOI2_TXDPDout(6) #defineOI2_RXDPDin(7) #defineBuadRate2_9600104 #defineRecive2_Byte19//接收缓冲器的个数 u8len2=0;//接收计数 u
[单片机]
STM32模拟<font color='red'>串口</font>(<font color='red'>UART</font>)<font color='red'>使用</font>
第011课 Jz2400串口(UART)的使用
第001节硬件知识_UART硬件介绍 1.串口的硬件介绍 UART的全称是Universal Asynchronous Receiver and Transmitter,即异步发送和接收。 串口在嵌入式中用途非常的广泛,主要的用途有: 打印调试信息; 外接各种模块:GPS、蓝牙; 串口因为结构简单、稳定可靠,广受欢迎。 通过三根线即可,发送、接收、地线。 通过TxD- RxD把ARM开发板要发送的信息发送给PC机。 通过RxD- TxD线把PC机要发送的信息发送给ARM开发板。 最下面的地线统一参考地。 2.串口的参数 波特率:一般选波特率都会有9600,19200,115200等选项。其实意思就是每
[单片机]
第011课 Jz2400<font color='red'>串口</font>(<font color='red'>UART</font>)的<font color='red'>使用</font>
LPC2000 UART串口使用心得
1、LPC2000 系列芯片的串口的接收模块包括接收缓冲寄存器和移位寄存器。接收的数据进入移位寄存器后经移位处理并行传入缓冲寄存器,事实上,UART的FIFO是一个硬件环形的缓冲队列,物理上不可寻址,不可见,仅U0RBR这个FIFO出口可见。U0RBR就是接收FIFO的第一位。FIFO的长度是可设的,也叫触发点,低于这个长度的字符串不会引起中断,但在实际应用中,不可能串口读入的数据长度总为触发点值的整数倍,为此,引入了CTI即字符接收超时中断,当有不足触发点值规定的字符串读入时,将引起中断,其与串口的RDA中断具有相同的优先级,并会同时被使能。 那么,LPC2000的UART机制是如何判断串口读入数据的一次性容量呢?如果接收FI
[单片机]
stm8s开发(三) UART使用串口通信!
串口通信是单片机学习的一个最基本、最重要的功能之一。串口通信可以间接的当做调试接口使用,实现单片机与电脑之间的通信。当然可以与一些模块(比如蓝牙、wifi)通信,也可以作为和其他单片机通信的工具。 STM8S的通用异步收发器(UART)主要特性: ● 全双工的,异步通信 ● 可编程数据字长度(8位或9位) ● 可配置的停止位-支持1或2个停止位 一般的,我们使用串口通信主要是关心几点参数:波特率、停止位、奇偶校验位。 其次就是如何发送、如何接收数据,这里介绍的使用阻塞式发送数据、中断方式接收数据。 以下代码是初始化串口,参数为:115200 1停止位 无校验位 void Init_UART1(void)
[单片机]
stm8s开发(三) <font color='red'>UART</font>的<font color='red'>使用</font>:<font color='red'>串口</font>通信!
HT46RU232 UART串口通信的使用
HT46RU232拥有1个全双工的异步串行通信口。下面就简单介绍一下232串口的使用。 其操作时序如下: (1).设置串口工作波特率、时钟、以及数据位数,起始位、停止位、错误检测等。 (2).准备等待发送/接收响应。 (3).当检测到发送/接收标志的时候,进行发送/接收数据。 程序范例:(中断法接收数据) #pragma vector Uart_ISR @0x10 //串口中断入口申明 void Uart_init() { _ucr1=0x80; //设置BNO,PRT,PREN,STOP位 _ucr2=0xe4; //使能TXEN、RXEN _brg
[单片机]
STM32与ESP8266结合使用MQTT协议实现数据发送至oneNET云平台串口通信详解
前言:这是基于STM32和ESP8266 WIFI模块的实战应用,全程干货满满,筑波已经踩玩了全部的坑,可放心食用。接下来我仔细介绍一下我的开发历程,希望对大家的学习有所帮助,也欢迎各位大佬来详细指出错误!!! 前提是自己已经烧录好了固件!!!!! 可以去安信可里寻找适合自己的固件,在乐鑫网站找烧录软件,这里不再解释。 AT固件汇总 | 安信可科技 https://www.espressif.com.cn/en/support/download/other-tools 准备材料:ESP8266模块,STM32开发板,oneNET云平台账号,CH340,ST-Link V2,串口i烧录助手(筑波用的是XCOM) 首先先给大
[单片机]
STM32与ESP8266结合<font color='red'>使用</font>MQTT协议实现数据发送至oneNET云平台<font color='red'>串口</font>通信详解
stm32串口应用及使用注意事项小白必备
串口是我们常用的一个数据传输接口,STM32F103系列单片机共有5个串口。 其中1-3是通用同步/异步串行接口USART(Universal Synchronous/Asynchronous Receiver/Transmitter)。 4,、5是通用异步串行接口UART(Universal Asynchronous Receiver/Transmitter)。 看完文章总结可以看下边的资料了解详细情况 (stm32 USART串口应用) http://www.makeru.com.cn/live/1392_1164.html?s=45051 通过Z-stack协议栈实现串口透传 http://www.makeru.com
[单片机]
基于GD32F310使用串口的空闲中断完成不定长数据的接收
我们在单片机开发中,经常会用到串口,这时候我可以通过使用DMA,减少CPU的占用。使用串口的空闲中断可以完成不定长数据的接受。所以本次我们从基础的外设移植开始完成此款板子的体验。 首先看下板子吧。 板子整体还是GD一贯风格,还是白色板子,这次由于芯片的管脚较小,目前所以引出方式变了。把可以用的IO都引出了。 本次我们使用串口0进行测试,此测试完成后我们也可以非常方便的移植到串口1上。 我在其基础上移植了新的开发模板,主要导入我们的外设库和CMSIS库即可。例程上我使用了一个闪烁LED灯的例子。 主循环中我们就两个任务,一个是点灯,一个是完成串口接收和发送。 在串口初始话的时候需要主要下,我们使能了串口的中断后,还需要打
[单片机]
基于GD32F310<font color='red'>使用</font><font color='red'>串口</font>的空闲中断完成不定长数据的接收
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved