1Universal Asynchronous Receiver/Transmitter (UART) 2================================================== 3 4{IDF_TARGET_UART_NUM:default = "UART_NUM_1", esp32 = "UART_NUM_2", esp32s3 = "UART_NUM_2"} 5 6Overview 7-------- 8 9A Universal Asynchronous Receiver/Transmitter (UART) is a hardware feature that handles communication (i.e., timing requirements and data framing) using widely-adopted asynchronous serial communication interfaces, such as RS232, RS422, RS485. A UART provides a widely adopted and cheap method to realize full-duplex or half-duplex data exchange among different devices. 10 11.. only:: esp32 or esp32s3 12 13 The {IDF_TARGET_NAME} chip has three UART controllers (UART0, UART1, and UART2), each featuring an identical set of registers to simplify programming and for more flexibility. 14 15.. only:: esp32s2 or esp32c3 16 17 The {IDF_TARGET_NAME} chip has two UART controllers (UART0 and UART1), each featuring an identical set of registers to simplify programming and for more flexibility. 18 19Each UART controller is independently configurable with parameters such as baud rate, data bit length, bit ordering, number of stop bits, parity bit etc. All the controllers are compatible with UART-enabled devices from various manufacturers and can also support Infrared Data Association protocols (IrDA). 20 21Functional Overview 22------------------- 23 24The following overview describes how to establish communication between an {IDF_TARGET_NAME} and other UART devices using the functions and data types of the UART driver. The overview reflects a typical programming workflow and is broken down into the sections provided below: 25 261. :ref:`uart-api-setting-communication-parameters` - Setting baud rate, data bits, stop bits, etc. 272. :ref:`uart-api-setting-communication-pins` - Assigning pins for connection to a device. 283. :ref:`uart-api-driver-installation` - Allocating {IDF_TARGET_NAME}'s resources for the UART driver. 294. :ref:`uart-api-running-uart-communication` - Sending / receiving data 305. :ref:`uart-api-using-interrupts` - Triggering interrupts on specific communication events 316. :ref:`uart-api-deleting-driver` - Freeing allocated resources if a UART communication is no longer required 32 33Steps 1 to 3 comprise the configuration stage. Step 4 is where the UART starts operating. Steps 5 and 6 are optional. 34 35The UART driver's functions identify each of the UART controllers using :cpp:type:`uart_port_t`. This identification is needed for all the following function calls. 36 37 38.. _uart-api-setting-communication-parameters: 39 40Setting Communication Parameters 41^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 42 43UART communication parameters can be configured all in a single step or individually in multiple steps. 44 45 46Single Step 47""""""""""" 48 49Call the function :cpp:func:`uart_param_config` and pass to it a :cpp:type:`uart_config_t` structure. The :cpp:type:`uart_config_t` structure should contain all the required parameters. See the example below. 50 51.. code-block:: c 52 53 const uart_port_t uart_num = {IDF_TARGET_UART_NUM}; 54 uart_config_t uart_config = { 55 .baud_rate = 115200, 56 .data_bits = UART_DATA_8_BITS, 57 .parity = UART_PARITY_DISABLE, 58 .stop_bits = UART_STOP_BITS_1, 59 .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS, 60 .rx_flow_ctrl_thresh = 122, 61 }; 62 // Configure UART parameters 63 ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config)); 64 65 66Multiple Steps 67"""""""""""""" 68 69Configure specific parameters individually by calling a dedicated function from the table given below. These functions are also useful if re-configuring a single parameter. 70 71.. list-table:: Functions for Configuring specific parameters individually 72 :widths: 30 70 73 :header-rows: 1 74 75 * - Parameter to Configure 76 - Function 77 * - Baud rate 78 - :cpp:func:`uart_set_baudrate` 79 * - Number of transmitted bits 80 - :cpp:func:`uart_set_word_length` selected out of :cpp:type:`uart_word_length_t` 81 * - Parity control 82 - :cpp:func:`uart_set_parity` selected out of :cpp:type:`uart_parity_t` 83 * - Number of stop bits 84 - :cpp:func:`uart_set_stop_bits` selected out of :cpp:type:`uart_stop_bits_t` 85 * - Hardware flow control mode 86 - :cpp:func:`uart_set_hw_flow_ctrl` selected out of :cpp:type:`uart_hw_flowcontrol_t` 87 * - Communication mode 88 - :cpp:func:`uart_set_mode` selected out of :cpp:type:`uart_mode_t` 89 90Each of the above functions has a ``_get_`` counterpart to check the currently set value. For example, to check the current baud rate value, call :cpp:func:`uart_get_baudrate`. 91 92 93.. _uart-api-setting-communication-pins: 94 95Setting Communication Pins 96^^^^^^^^^^^^^^^^^^^^^^^^^^ 97 98After setting communication parameters, configure the physical GPIO pins to which the other UART device will be connected. For this, call the function :cpp:func:`uart_set_pin` and specify the GPIO pin numbers to which the driver should route the Tx, Rx, RTS, and CTS signals. If you want to keep a currently allocated pin number for a specific signal, pass the macro :c:macro:`UART_PIN_NO_CHANGE`. 99 100The same macro should be specified for pins that will not be used. 101 102.. code-block:: c 103 104 // Set UART pins(TX: IO4, RX: IO5, RTS: IO18, CTS: IO19) 105 ESP_ERROR_CHECK(uart_set_pin({IDF_TARGET_UART_NUM}, 4, 5, 18, 19)); 106 107.. _uart-api-driver-installation: 108 109Driver Installation 110^^^^^^^^^^^^^^^^^^^ 111 112Once the communication pins are set, install the driver by calling :cpp:func:`uart_driver_install` and specify the following parameters: 113 114- Size of Tx ring buffer 115- Size of Rx ring buffer 116- Event queue handle and size 117- Flags to allocate an interrupt 118 119The function will allocate the required internal resources for the UART driver. 120 121.. code-block:: c 122 123 // Setup UART buffered IO with event queue 124 const int uart_buffer_size = (1024 * 2); 125 QueueHandle_t uart_queue; 126 // Install UART driver using an event queue here 127 ESP_ERROR_CHECK(uart_driver_install({IDF_TARGET_UART_NUM}, uart_buffer_size, \ 128 uart_buffer_size, 10, &uart_queue, 0)); 129 130Once this step is complete, you can connect the external UART device and check the communication. 131 132 133.. _uart-api-running-uart-communication: 134 135Running UART Communication 136^^^^^^^^^^^^^^^^^^^^^^^^^^ 137 138Serial communication is controlled by each UART controller's finite state machine (FSM). 139 140The process of sending data involves the following steps: 141 1421. Write data into Tx FIFO buffer 1432. FSM serializes the data 1443. FSM sends the data out 145 146The process of receiving data is similar, but the steps are reversed: 147 1481. FSM processes an incoming serial stream and parallelizes it 1492. FSM writes the data into Rx FIFO buffer 1503. Read the data from Rx FIFO buffer 151 152Therefore, an application will be limited to writing and reading data from a respective buffer using :cpp:func:`uart_write_bytes` and :cpp:func:`uart_read_bytes` respectively, and the FSM will do the rest. 153 154 155Transmitting 156"""""""""""" 157 158After preparing the data for transmission, call the function :cpp:func:`uart_write_bytes` and pass the data buffer's address and data length to it. The function will copy the data to the Tx ring buffer (either immediately or after enough space is available), and then exit. When there is free space in the Tx FIFO buffer, an interrupt service routine (ISR) moves the data from the Tx ring buffer to the Tx FIFO buffer in the background. The code below demonstrates the use of this function. 159 160.. code-block:: c 161 162 // Write data to UART. 163 char* test_str = "This is a test string.\n"; 164 uart_write_bytes(uart_num, (const char*)test_str, strlen(test_str)); 165 166The function :cpp:func:`uart_write_bytes_with_break` is similar to :cpp:func:`uart_write_bytes` but adds a serial break signal at the end of the transmission. A 'serial break signal' means holding the Tx line low for a period longer than one data frame. 167 168.. code-block:: c 169 170 // Write data to UART, end with a break signal. 171 uart_write_bytes_with_break(uart_num, "test break\n",strlen("test break\n"), 100); 172 173Another function for writing data to the Tx FIFO buffer is :cpp:func:`uart_tx_chars`. Unlike :cpp:func:`uart_write_bytes`, this function will not block until space is available. Instead, it will write all data which can immediately fit into the hardware Tx FIFO, and then return the number of bytes that were written. 174 175There is a 'companion' function :cpp:func:`uart_wait_tx_done` that monitors the status of the Tx FIFO buffer and returns once it is empty. 176 177.. code-block:: c 178 179 // Wait for packet to be sent 180 const uart_port_t uart_num = {IDF_TARGET_UART_NUM}; 181 ESP_ERROR_CHECK(uart_wait_tx_done(uart_num, 100)); // wait timeout is 100 RTOS ticks (TickType_t) 182 183 184Receiving 185""""""""" 186 187Once the data is received by the UART and saved in the Rx FIFO buffer, it needs to be retrieved using the function :cpp:func:`uart_read_bytes`. Before reading data, you can check the number of bytes available in the Rx FIFO buffer by calling :cpp:func:`uart_get_buffered_data_len`. An example of using these functions is given below. 188 189.. code-block:: c 190 191 // Read data from UART. 192 const uart_port_t uart_num = {IDF_TARGET_UART_NUM}; 193 uint8_t data[128]; 194 int length = 0; 195 ESP_ERROR_CHECK(uart_get_buffered_data_len(uart_num, (size_t*)&length)); 196 length = uart_read_bytes(uart_num, data, length, 100); 197 198If the data in the Rx FIFO buffer is no longer needed, you can clear the buffer by calling :cpp:func:`uart_flush`. 199 200 201Software Flow Control 202""""""""""""""""""""" 203 204If the hardware flow control is disabled, you can manually set the RTS and DTR signal levels by using the functions :cpp:func:`uart_set_rts` and :cpp:func:`uart_set_dtr` respectively. 205 206 207Communication Mode Selection 208"""""""""""""""""""""""""""" 209 210The UART controller supports a number of communication modes. A mode can be selected using the function :cpp:func:`uart_set_mode`. Once a specific mode is selected, the UART driver will handle the behavior of a connected UART device accordingly. As an example, it can control the RS485 driver chip using the RTS line to allow half-duplex RS485 communication. 211 212.. code-block:: bash 213 214 // Setup UART in rs485 half duplex mode 215 ESP_ERROR_CHECK(uart_set_mode(uart_num, UART_MODE_RS485_HALF_DUPLEX)); 216 217 218.. _uart-api-using-interrupts: 219 220Using Interrupts 221^^^^^^^^^^^^^^^^ 222 223There are many interrupts that can be generated following specific UART states or detected errors. The full list of available interrupts is provided in *{IDF_TARGET_NAME} Technical Reference Manual* > *UART Controller (UART)* > *UART Interrupts* and *UHCI Interrupts* [`PDF <{IDF_TARGET_TRM_EN_URL}#uart>`__]. You can enable or disable specific interrupts by calling :cpp:func:`uart_enable_intr_mask` or :cpp:func:`uart_disable_intr_mask` respectively. The mask of all interrupts is available as :c:macro:`UART_INTR_MASK`. 224 225By default, the :cpp:func:`uart_driver_install` function installs the driver's internal interrupt handler to manage the Tx and Rx ring buffers and provides high-level API functions like events (see below). It is also possible to register a lower level interrupt handler instead using :cpp:func:`uart_isr_register`, and to free it again using :cpp:func:`uart_isr_free`. Some UART driver functions which use the Tx and Rx ring buffers, events, etc. will not automatically work in this case - it is necessary to handle the interrupts directly in the ISR. Inside the custom handler implementation, clear the interrupt status bits using :cpp:func:`uart_clear_intr_status`. 226 227The API provides a convenient way to handle specific interrupts discussed in this document by wrapping them into dedicated functions: 228 229- **Event detection**: There are several events defined in :cpp:type:`uart_event_type_t` that may be reported to a user application using the FreeRTOS queue functionality. You can enable this functionality when calling :cpp:func:`uart_driver_install` described in :ref:`uart-api-driver-installation`. An example of using Event detection can be found in :example:`peripherals/uart/uart_events`. 230 231- **FIFO space threshold or transmission timeout reached**: The Tx and Rx FIFO buffers can trigger an interrupt when they are filled with a specific number of characters, or on a timeout of sending or receiving data. To use these interrupts, do the following: 232 233 - Configure respective threshold values of the buffer length and timeout by entering them in the structure :cpp:type:`uart_intr_config_t` and calling :cpp:func:`uart_intr_config` 234 - Enable the interrupts using the functions :cpp:func:`uart_enable_tx_intr` and :cpp:func:`uart_enable_rx_intr` 235 - Disable these interrupts using the corresponding functions :cpp:func:`uart_disable_tx_intr` or :cpp:func:`uart_disable_rx_intr` 236 237- **Pattern detection**: An interrupt triggered on detecting a 'pattern' of the same character being received/sent repeatedly for a number of times. This functionality is demonstrated in the example :example:`peripherals/uart/uart_events`. It can be used, e.g., to detect a command string followed by a specific number of identical characters (the 'pattern') added at the end of the command string. The following functions are available: 238 239 - Configure and enable this interrupt using :cpp:func:`uart_enable_pattern_det_intr` 240 - Disable the interrupt using :cpp:func:`uart_disable_pattern_det_intr` 241 242 243Macros 244^^^^^^ 245 246The API also defines several macros. For example, :c:macro:`UART_FIFO_LEN` defines the length of hardware FIFO buffers; :c:macro:`UART_BITRATE_MAX` gives the maximum baud rate supported by the UART controllers, etc. 247 248 249.. _uart-api-deleting-driver: 250 251Deleting a Driver 252^^^^^^^^^^^^^^^^^ 253 254If the communication established with :cpp:func:`uart_driver_install` is no longer required, the driver can be removed to free allocated resources by calling :cpp:func:`uart_driver_delete`. 255 256 257Overview of RS485 specific communication options 258------------------------------------------------ 259 260.. note:: 261 262 The following section will use ``[UART_REGISTER_NAME].[UART_FIELD_BIT]`` to refer to UART register fields/bits. For more information on a specific option bit, see *{IDF_TARGET_NAME} Technical Reference Manual* > *UART Controller (UART)* > *Register Summary* [`PDF <{IDF_TARGET_TRM_EN_URL}#uart-reg-summ>`__]. Use the register name to navigate to the register description and then find the field/bit. 263 264- ``UART_RS485_CONF_REG.UART_RS485_EN``: setting this bit enables RS485 communication mode support. 265- ``UART_RS485_CONF_REG.UART_RS485TX_RX_EN``: if this bit is set, the transmitter's output signal loops back to the receiver's input signal. 266- ``UART_RS485_CONF_REG.UART_RS485RXBY_TX_EN``: if this bit is set, the transmitter will still be sending data if the receiver is busy (remove collisions automatically by hardware). 267 268The {IDF_TARGET_NAME}'s RS485 UART hardware can detect signal collisions during transmission of a datagram and generate the interrupt ``UART_RS485_CLASH_INT`` if this interrupt is enabled. The term collision means that a transmitted datagram is not equal to the one received on the other end. Data collisions are usually associated with the presence of other active devices on the bus or might occur due to bus errors. 269 270The collision detection feature allows handling collisions when their interrupts are activated and triggered. The interrupts ``UART_RS485_FRM_ERR_INT`` and ``UART_RS485_PARITY_ERR_INT`` can be used with the collision detection feature to control frame errors and parity bit errors accordingly in RS485 mode. This functionality is supported in the UART driver and can be used by selecting the :cpp:enumerator:`UART_MODE_RS485_APP_CTRL` mode (see the function :cpp:func:`uart_set_mode`). 271 272The collision detection feature can work with circuit A and circuit C (see Section `Interface Connection Options`_). In the case of using circuit A or B, the RTS pin connected to the DE pin of the bus driver should be controlled by the user application. Use the function :cpp:func:`uart_get_collision_flag` to check if the collision detection flag has been raised. 273 274The {IDF_TARGET_NAME} UART controllers themselves do not support half-duplex communication as they cannot provide automatic control of the RTS pin connected to the ~RE/DE input of RS485 bus driver. However, half-duplex communication can be achieved via software control of the RTS pin by the UART driver. This can be enabled by selecting the :cpp:enumerator:`UART_MODE_RS485_HALF_DUPLEX` mode when calling :cpp:func:`uart_set_mode`. 275 276Once the host starts writing data to the Tx FIFO buffer, the UART driver automatically asserts the RTS pin (logic 1); once the last bit of the data has been transmitted, the driver de-asserts the RTS pin (logic 0). To use this mode, the software would have to disable the hardware flow control function. This mode works with all the used circuits shown below. 277 278 279Interface Connection Options 280^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 281 282This section provides example schematics to demonstrate the basic aspects of {IDF_TARGET_NAME}'s RS485 interface connection. 283 284.. note:: 285 286 - The schematics below do **not** necessarily contain **all required elements**. 287 288 - The **analog devices** ADM483 & ADM2483 are examples of common RS485 transceivers and **can be replaced** with other similar transceivers. 289 290 291Circuit A: Collision Detection Circuit 292"""""""""""""""""""""""""""""""""""""" 293 294.. code-block:: none 295 296 VCC ---------------+ 297 | 298 +-------x-------+ 299 RXD <------| R | 300 | B|----------<> B 301 TXD ------>| D ADM483 | 302 ESP | | RS485 bus side 303 RTS ------>| DE | 304 | A|----------<> A 305 +----| /RE | 306 | +-------x-------+ 307 | | 308 GND GND 309 310This circuit is preferable because it allows for collision detection and is quite simple at the same time. The receiver in the line driver is constantly enabled, which allows the UART to monitor the RS485 bus. Echo suppression is performed by the UART peripheral when the bit ``UART_RS485_CONF_REG.UART_RS485TX_RX_EN`` is enabled. 311 312 313Circuit B: Manual Switching Transmitter/Receiver Without Collision Detection 314"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 315 316 317.. code-block:: none 318 319 VCC ---------------+ 320 | 321 +-------x-------+ 322 RXD <------| R | 323 | B|-----------<> B 324 TXD ------>| D ADM483 | 325 ESP | | RS485 bus side 326 RTS --+--->| DE | 327 | | A|-----------<> A 328 +----| /RE | 329 +-------x-------+ 330 | 331 GND 332 333This circuit does not allow for collision detection. It suppresses the null bytes that the hardware receives when the bit ``UART_RS485_CONF_REG.UART_RS485TX_RX_EN`` is set. The bit ``UART_RS485_CONF_REG.UART_RS485RXBY_TX_EN`` is not applicable in this case. 334 335 336Circuit C: Auto Switching Transmitter/Receiver 337"""""""""""""""""""""""""""""""""""""""""""""" 338 339.. code-block:: none 340 341 VCC1 <-------------------+-----------+ +-------------------+----> VCC2 342 10K ____ | | | | 343 +---|____|--+ +---x-----------x---+ 10K ____ | 344 | | | +---|____|--+ 345 RX <----------+-------------------| RXD | | 346 10K ____ | A|---+---------------<> A (+) 347 +-------|____|------| PV ADM2483 | | ____ 120 348 | ____ | | +---|____|---+ RS485 bus side 349 VCC1 <--+--|____|--+------->| DE | | 350 10K | | B|---+------------+--<> B (-) 351 ---+ +-->| /RE | | ____ 352 10K | | | | +---|____|---+ 353 ____ | /-C +---| TXD | 10K | 354 TX >---|____|--+_B_|/ NPN | | | | 355 |\ | +---x-----------x---+ | 356 | \-E | | | | 357 | | | | | 358 GND1 GND1 GND1 GND2 GND2 359 360This galvanically isolated circuit does not require RTS pin control by a software application or driver because it controls the transceiver direction automatically. However, it requires suppressing null bytes during transmission by setting ``UART_RS485_CONF_REG.UART_RS485RXBY_TX_EN`` to 1 and ``UART_RS485_CONF_REG.UART_RS485TX_RX_EN`` to 0. This setup can work in any RS485 UART mode or even in :cpp:enumerator:`UART_MODE_UART`. 361 362 363Application Examples 364-------------------- 365 366The table below describes the code examples available in the directory :example:`peripherals/uart/`. 367 368.. list-table:: 369 :widths: 35 65 370 :header-rows: 1 371 372 * - Code Example 373 - Description 374 * - :example:`peripherals/uart/uart_echo` 375 - Configuring UART settings, installing the UART driver, and reading/writing over the UART1 interface. 376 * - :example:`peripherals/uart/uart_events` 377 - Reporting various communication events, using pattern detection interrupts. 378 * - :example:`peripherals/uart/uart_async_rxtxtasks` 379 - Transmitting and receiving data in two separate FreeRTOS tasks over the same UART. 380 * - :example:`peripherals/uart/uart_select` 381 - Using synchronous I/O multiplexing for UART file descriptors. 382 * - :example:`peripherals/uart/uart_echo_rs485` 383 - Setting up UART driver to communicate over RS485 interface in half-duplex mode. This example is similar to :example:`peripherals/uart/uart_echo` but allows communication through an RS485 interface chip connected to {IDF_TARGET_NAME} pins. 384 * - :example:`peripherals/uart/nmea0183_parser` 385 - Obtaining GPS information by parsing NMEA0183 statements received from GPS via the UART peripheral. 386 387 388API Reference 389------------- 390 391.. include-build-file:: inc/uart.inc 392.. include-build-file:: inc/uart_types.inc 393 394 395GPIO Lookup Macros 396^^^^^^^^^^^^^^^^^^ 397 398The UART peripherals have dedicated IO_MUX pins to which they are connected directly. However, signals can also be routed to other pins using the less direct GPIO matrix. To use direct routes, you need to know which pin is a dedicated IO_MUX pin for a UART channel. GPIO Lookup Macros simplify the process of finding and assigning IO_MUX pins. You choose a macro based on either the IO_MUX pin number, or a required UART channel name, and the macro will return the matching counterpart for you. See some examples below. 399 400.. note:: 401 402 These macros are useful if you need very high UART baud rates (over 40 MHz), which means you will have to use IO_MUX pins only. In other cases, these macros can be ignored, and you can use the GPIO Matrix as it allows you to configure any GPIO pin for any UART function. 403 4041. :c:macro:`UART_NUM_2_TXD_DIRECT_GPIO_NUM` returns the IO_MUX pin number of UART channel 2 TXD pin (pin 17) 4052. :c:macro:`UART_GPIO19_DIRECT_CHANNEL` returns the UART number of GPIO 19 when connected to the UART peripheral via IO_MUX (this is UART_NUM_0) 4063. :c:macro:`UART_CTS_GPIO19_DIRECT_CHANNEL` returns the UART number of GPIO 19 when used as the UART CTS pin via IO_MUX (this is UART_NUM_0). Similar to the above macro but specifies the pin function which is also part of the IO_MUX assignment. 407 408.. include-build-file:: inc/uart_channel.inc 409 410