Incoming serial data is stored in a buffer by background interrupt service routines. The Serial.available() function provides the user with access to this buffered data.
However, it seems that the original poster is interested in reading data directly from the UART receiver hardware -- similar to accessing the USART registers (e.g., UDR0) on the Arduino Uno R3, rather than using the Arduino Serial abstraction layer.
ISR(USART_RX_vect) //USART receive complete interrupt
{
rx_data = UDR0; // Read received byte
}
I have asked AI to give code to read data directly from the RX register of ESP32. It has given me the following code most of which are beyond my understandig as they are wrtten in HAL (High Level Abstraction Layer) format.
#include "driver/uart.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include <string.h>
#define UART_NUM UART_NUM_1
#define BUF_SIZE 1024
static QueueHandle_t uart_queue;
void uart_event_task(void *pvParameters)
{
uart_event_t event;
uint8_t data[BUF_SIZE];
while (1)
{
if (xQueueReceive(uart_queue, &event, portMAX_DELAY))
{
if (event.type == UART_DATA)
{
int len = uart_read_bytes(UART_NUM, data, event.size, portMAX_DELAY);
// Process received data
for (int i = 0; i < len; i++)
{
// Example: echo or store
}
}
}
}
}
void app_main(void)
{
uart_config_t uart_config = {
.baud_rate = 9600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_driver_install(UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart_queue, 0);
uart_param_config(UART_NUM, &uart_config);
uart_set_pin(UART_NUM, 17, 16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 10, NULL);
}
workflow of the above code:
- UART hardware receives byte
- RX FIFO gets data
- Hardware interrupt fires
- ESP32 UART ISR (inside driver) runs
- Data moved to ring buffer
- Event (
UART_DATA) sent to queue
- Your task wakes up and reads data