3.3.7
This commit is contained in:
+265
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
Hardware Flow Control Demo for ESP32
|
||||
|
||||
This sketch demonstrates UART hardware flow control using RTS (Request To Send)
|
||||
and CTS (Clear To Send) signals with UART1 (HardwareSerial Serial1).
|
||||
|
||||
CONFIGURATION:
|
||||
==============
|
||||
|
||||
Set USE_INTERNAL_MATRIX_PIN_LOOPBACK to 1 for internal GPIO matrix connections
|
||||
(no external wires needed). Set to 0 to use external wire connections.
|
||||
|
||||
PIN CONNECTIONS (when USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0):
|
||||
============================================================
|
||||
|
||||
For basic loopback with hardware flow control:
|
||||
- Connect GPIO2 (RTS1) to GPIO4 (CTS1) - Flow control loopback
|
||||
- Connect TX1 pin to RX1 pin - Data loopback
|
||||
|
||||
For GPIO-controlled flow control demonstration:
|
||||
- Connect TX1 pin to RX1 pin - Data loopback
|
||||
- Connect GPIO2 (RTS1) to GPIO5 (GPIO_RTS_MONITOR) - Monitor RTS state
|
||||
- Connect GPIO4 (CTS1) to GPIO13 (GPIO_CTS_CTRL) - Control CTS signal
|
||||
- Use GPIO13 to manually control CTS signal (LOW = allow, HIGH = block)
|
||||
|
||||
HARDWARE FLOW CONTROL EXPLANATION:
|
||||
===================================
|
||||
|
||||
RTS (Request To Send):
|
||||
- Output signal from UART (GPIO2 in this example)
|
||||
- Asserted LOW when UART is ready to receive data (RX buffer has space)
|
||||
- De-asserted HIGH when RX buffer is getting full (threshold reached)
|
||||
|
||||
CTS (Clear To Send):
|
||||
- Input signal to UART (GPIO4 in this example)
|
||||
- UART will only transmit when CTS is LOW (asserted)
|
||||
- UART will pause transmission when CTS is HIGH (de-asserted)
|
||||
|
||||
OPERATION:
|
||||
==========
|
||||
|
||||
The sketch demonstrates:
|
||||
- Periodic transmission of messages every second
|
||||
- Automatic flow control when USE_GPIO_CONTROL = false
|
||||
- Manual CTS control when USE_GPIO_CONTROL = true
|
||||
- Loopback reception of transmitted data
|
||||
- Status monitoring of RTS/CTS pin states
|
||||
|
||||
NOTE: When USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1, no external connections
|
||||
are needed as the ESP32 GPIO matrix handles the loopback internally.
|
||||
*/
|
||||
|
||||
// setting it to 1 will allow internal matrix pin connection for RX1<->TX1 and RTS1<->CTS1
|
||||
// otherwise it needs a wire for cross connecting the pins
|
||||
#define USE_INTERNAL_MATRIX_PIN_LOOPBACK 1
|
||||
|
||||
// Pin definitions for UART1
|
||||
#define UART1_RX_PIN RX1 // Default GPIO - UART1 RX pin
|
||||
#define UART1_TX_PIN TX1 // Default GPIO - UART1 TX pin
|
||||
#define UART1_RTS_PIN 2 // GPIO2 - UART1 RTS pin (output from UART)
|
||||
#define UART1_CTS_PIN 4 // GPIO4 - UART1 CTS pin (input to UART)
|
||||
|
||||
// Optional: GPIO pins for manual flow control demonstration
|
||||
// If using GPIO-controlled flow control, connect:
|
||||
// - RTS1 to GPIO_RTS_MONITOR (to monitor RTS state)
|
||||
// - CTS1 to GPIO_CTS_CTRL (to control CTS signal)
|
||||
#define GPIO_RTS_MONITOR 5 // GPIO5 - Monitor RTS signal (connect RTS1 to this)
|
||||
#define GPIO_CTS_CTRL 13 // GPIO13 - Control CTS signal (connect CTS1 to this)
|
||||
|
||||
// Set to true to use GPIO-controlled flow control, false for simple loopback
|
||||
// Note: this control will be overridden by USE_INTERNAL_MATRIX_PIN_LOOPBACK when it is 1
|
||||
#define USE_GPIO_CONTROL false
|
||||
|
||||
// Variables for demonstration
|
||||
unsigned long lastSendTime = 0;
|
||||
unsigned long lastStatusTime = 0;
|
||||
const unsigned long sendInterval = 1000; // Send data every 1 second
|
||||
const unsigned long statusInterval = 2000; // Print status every 2 seconds
|
||||
int sendCounter = 0;
|
||||
|
||||
void printPinStatus() {
|
||||
Serial.println("\n=== UART1 Pin Status ===");
|
||||
Serial.printf("RX Pin (GPIO%d): Receiving data\n", UART1_RX_PIN);
|
||||
Serial.printf("TX Pin (GPIO%d): Transmitting data\n", UART1_TX_PIN);
|
||||
|
||||
if (USE_GPIO_CONTROL) {
|
||||
// Read RTS state from monitor GPIO (connected to RTS1)
|
||||
bool rtsState = digitalRead(GPIO_RTS_MONITOR);
|
||||
Serial.printf("RTS Pin (GPIO%d): %s (LOW = ready to receive)\n", UART1_RTS_PIN, rtsState == LOW ? "LOW (Ready)" : "HIGH (Busy)");
|
||||
|
||||
// Read CTS state from control GPIO (connected to CTS1)
|
||||
bool ctsState = digitalRead(GPIO_CTS_CTRL);
|
||||
Serial.printf("CTS Pin (GPIO%d): %s (LOW = can transmit)\n", UART1_CTS_PIN, ctsState == LOW ? "LOW (Clear)" : "HIGH (Blocked)");
|
||||
} else {
|
||||
Serial.printf("RTS Pin (GPIO%d): Hardware controlled (LOW = ready to receive)\n", UART1_RTS_PIN);
|
||||
Serial.printf("CTS Pin (GPIO%d): Hardware controlled (LOW = can transmit)\n", UART1_CTS_PIN);
|
||||
Serial.println("Note: RTS/CTS pins are hardware-controlled. Connect RTS1 to CTS1 for loopback.");
|
||||
}
|
||||
|
||||
Serial.printf("Available for write: %d bytes\n", Serial1.availableForWrite());
|
||||
Serial.printf("Available to read: %d bytes\n", Serial1.available());
|
||||
Serial.println("========================\n");
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// Initialize Serial (USB) for debugging
|
||||
Serial.begin(115200);
|
||||
delay(1000);
|
||||
|
||||
Serial.println("\n\n========================================");
|
||||
Serial.println("ESP32 Hardware Flow Control Demo");
|
||||
Serial.println("========================================\n");
|
||||
|
||||
// Configure GPIOs for flow control (only if using GPIO-controlled mode)
|
||||
if (USE_GPIO_CONTROL) {
|
||||
// Configure CTS control GPIO - this will control the CTS signal
|
||||
pinMode(GPIO_CTS_CTRL, OUTPUT);
|
||||
digitalWrite(GPIO_CTS_CTRL, LOW); // Start with CTS LOW (clear to send)
|
||||
|
||||
// Configure RTS monitor GPIO - this will monitor the RTS signal
|
||||
pinMode(GPIO_RTS_MONITOR, INPUT);
|
||||
Serial.println("Using GPIO-controlled flow control mode");
|
||||
} else {
|
||||
Serial.println("Using hardware-controlled flow control (simple loopback)");
|
||||
}
|
||||
|
||||
// Initialize UART1 with hardware flow control
|
||||
Serial.println("Initializing UART1...");
|
||||
|
||||
// Begin UART1 with 115200 baud, 8N1 configuration
|
||||
Serial1.begin(115200);
|
||||
|
||||
// Set all pins for UART1
|
||||
if (!Serial1.setPins(UART1_RX_PIN, UART1_TX_PIN, UART1_CTS_PIN, UART1_RTS_PIN)) {
|
||||
Serial.println("ERROR: Failed to set CTS and RTS UART1 pins!");
|
||||
while (1) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println("Enabling hardware flow control...");
|
||||
if (!Serial1.setHwFlowCtrlMode(UART_HW_FLOWCTRL_CTS_RTS, 64)) {
|
||||
Serial.println("ERROR: Failed to enable hardware flow control!");
|
||||
while (1) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_INTERNAL_MATRIX_PIN_LOOPBACK
|
||||
uart_internal_loopback(1, UART1_RX_PIN);
|
||||
uart_internal_hw_flow_ctrl_loopback(1, UART1_CTS_PIN);
|
||||
#endif
|
||||
|
||||
// Diagnostic: Check initial state after enabling flow control
|
||||
Serial.println("\nPost-initialization diagnostics:");
|
||||
Serial.printf(" Serial1.available(): %d bytes\n", Serial1.available());
|
||||
Serial.printf(" Serial1.availableForWrite(): %d bytes\n", Serial1.availableForWrite());
|
||||
if (USE_GPIO_CONTROL) {
|
||||
Serial.printf(" GPIO%d (CTS control): %s\n", GPIO_CTS_CTRL, digitalRead(GPIO_CTS_CTRL) == LOW ? "LOW" : "HIGH");
|
||||
Serial.printf(" GPIO%d (RTS monitor): %s\n", GPIO_RTS_MONITOR, digitalRead(GPIO_RTS_MONITOR) == LOW ? "LOW" : "HIGH");
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Serial.println("UART1 initialized successfully!");
|
||||
Serial.println("Hardware flow control: ENABLED (RTS + CTS)");
|
||||
Serial.printf("RX Pin: GPIO%d\n", UART1_RX_PIN);
|
||||
Serial.printf("TX Pin: GPIO%d\n", UART1_TX_PIN);
|
||||
Serial.printf("RTS Pin: GPIO%d (output from UART)\n", UART1_RTS_PIN);
|
||||
Serial.printf("CTS Pin: GPIO%d (input to UART)\n", UART1_CTS_PIN);
|
||||
|
||||
#if USE_INTERNAL_MATRIX_PIN_LOOPBACK
|
||||
Serial.println("\nNO EXTERNAL PIN CONNECTIONS ARE REQUIRED:");
|
||||
Serial.println("-------------------------");
|
||||
Serial.println("Internal GPIO Matrix connection with flow control mode:");
|
||||
Serial.printf(" 1. Automatic Internal Connection of GPIO%d (TX1) to GPIO%d (RX1) - Loopback\n", UART1_TX_PIN, UART1_RX_PIN);
|
||||
Serial.printf(" 2. Automatic Internal Connection of GPIO%d (RTS1) to GPIO%d (CTS1) - Flow control loopback\n", UART1_RTS_PIN, UART1_CTS_PIN);
|
||||
Serial.println("\n Note: In this mode, RTS/CTS are automatically controlled by hardware.");
|
||||
Serial.println(" RTS goes LOW when ready to receive, HIGH when buffer is full.");
|
||||
Serial.println(" CTS must be LOW for transmission to proceed.");
|
||||
#else
|
||||
Serial.println("\nPIN CONNECTIONS REQUIRED:");
|
||||
Serial.println("-------------------------");
|
||||
if (USE_GPIO_CONTROL) {
|
||||
Serial.println("GPIO-controlled flow control mode:");
|
||||
Serial.printf(" 1. Connect GPIO%d (TX1) to GPIO%d (RX1) - Loopback\n", UART1_TX_PIN, UART1_RX_PIN);
|
||||
Serial.printf(" 2. Connect GPIO%d (RTS1) to GPIO%d - Monitor RTS state\n", UART1_RTS_PIN, GPIO_RTS_MONITOR);
|
||||
Serial.printf(" 3. Connect GPIO%d (CTS1) to GPIO%d - Control CTS signal\n", UART1_CTS_PIN, GPIO_CTS_CTRL);
|
||||
} else {
|
||||
Serial.println("Hardware-controlled flow control (simple loopback):");
|
||||
Serial.printf(" 1. Connect GPIO%d (TX1) to GPIO%d (RX1) - Loopback\n", UART1_TX_PIN, UART1_RX_PIN);
|
||||
Serial.printf(" 2. Connect GPIO%d (RTS1) to GPIO%d (CTS1) - Flow control loopback\n", UART1_RTS_PIN, UART1_CTS_PIN);
|
||||
Serial.println("\n Note: In this mode, RTS/CTS are automatically controlled by hardware.");
|
||||
Serial.println(" RTS goes LOW when ready to receive, HIGH when buffer is full.");
|
||||
Serial.println(" CTS must be LOW for transmission to proceed.");
|
||||
}
|
||||
#endif
|
||||
Serial.println("\nStarting demonstration in 2 seconds...\n");
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
// Print status periodically
|
||||
if (currentTime - lastStatusTime >= statusInterval) {
|
||||
lastStatusTime = currentTime;
|
||||
printPinStatus();
|
||||
|
||||
// Demonstrate flow control by toggling CTS (only in GPIO-controlled mode)
|
||||
if (USE_GPIO_CONTROL) {
|
||||
static bool ctsState = false;
|
||||
ctsState = !ctsState;
|
||||
|
||||
if (ctsState) {
|
||||
Serial.println(">>> Blocking transmission (CTS HIGH)...");
|
||||
digitalWrite(GPIO_CTS_CTRL, HIGH); // Block transmission
|
||||
} else {
|
||||
Serial.println(">>> Allowing transmission (CTS LOW)...");
|
||||
digitalWrite(GPIO_CTS_CTRL, LOW); // Allow transmission
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send data periodically
|
||||
if (currentTime - lastSendTime >= sendInterval) {
|
||||
lastSendTime = currentTime;
|
||||
sendCounter++;
|
||||
|
||||
// Check if we can transmit (CTS must be LOW)
|
||||
// In GPIO-controlled mode, check the control GPIO; otherwise hardware handles it
|
||||
bool canTransmit = true;
|
||||
if (USE_GPIO_CONTROL) {
|
||||
canTransmit = (digitalRead(GPIO_CTS_CTRL) == LOW);
|
||||
}
|
||||
|
||||
if (canTransmit) {
|
||||
char message[64];
|
||||
snprintf(message, sizeof(message), "Message #%d: Hello from UART1! Time: %lu ms\r\n", sendCounter, currentTime);
|
||||
|
||||
Serial.print("Sending: ");
|
||||
Serial.print(message);
|
||||
|
||||
size_t bytesWritten = Serial1.write((const uint8_t *)message, strlen(message));
|
||||
Serial.printf(" -> Written: %d bytes\n", bytesWritten);
|
||||
|
||||
// Flush to ensure data is sent
|
||||
Serial1.flush();
|
||||
} else {
|
||||
Serial.println("!!! Transmission blocked - CTS is HIGH !!!");
|
||||
}
|
||||
}
|
||||
|
||||
// Read and echo received data
|
||||
if (Serial1.available()) {
|
||||
Serial.print("Received: ");
|
||||
while (Serial1.available()) {
|
||||
char c = Serial1.read();
|
||||
Serial.write(c);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Small delay to prevent tight loop
|
||||
delay(10);
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
# Hardware Flow Control Demo
|
||||
|
||||
This example demonstrates UART hardware flow control using RTS (Request To Send) and CTS (Clear To Send) signals with ESP32's HardwareSerial (UART1).
|
||||
|
||||
## Overview
|
||||
|
||||
Hardware flow control is a mechanism that prevents data loss by controlling when data can be transmitted and received. It uses two additional signals:
|
||||
|
||||
- **RTS (Request To Send)**: Output signal from the UART indicating it's ready to receive data
|
||||
- **CTS (Clear To Send)**: Input signal to the UART that controls when transmission is allowed
|
||||
|
||||
## Configuration Options
|
||||
|
||||
The sketch supports two configuration options:
|
||||
|
||||
### USE_INTERNAL_MATRIX_PIN_LOOPBACK
|
||||
|
||||
**Location in code:** Line 55 in `HardwareFlowControl_Demo.ino`
|
||||
```cpp
|
||||
#define USE_INTERNAL_MATRIX_PIN_LOOPBACK 1 // Set to 1 for internal loopback, 0 for external wires
|
||||
```
|
||||
|
||||
- **`USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`** (Default): Uses ESP32's internal GPIO matrix to create loopback connections. **No external wires needed!**
|
||||
- **`USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`**: Requires external wire connections (see Pin Connections section below)
|
||||
|
||||
### USE_GPIO_CONTROL
|
||||
|
||||
**Location in code:** Line 72 in `HardwareFlowControl_Demo.ino`
|
||||
```cpp
|
||||
#define USE_GPIO_CONTROL false // Set to true or false
|
||||
```
|
||||
|
||||
**Note:** When `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`, the `USE_GPIO_CONTROL` setting is overridden and hardware-controlled mode is used.
|
||||
|
||||
## Pin Connections
|
||||
|
||||
**Important:** Pin connections are only needed when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`.
|
||||
|
||||
### Default Pin Assignments
|
||||
|
||||
- **RX1**: Uses board default (`RX1` constant - typically GPIO26 for ESP32, varies by board)
|
||||
- **TX1**: Uses board default (`TX1` constant - typically GPIO27 for ESP32, varies by board)
|
||||
- **RTS1**: GPIO2 (configurable via `UART1_RTS_PIN`)
|
||||
- **CTS1**: GPIO4 (configurable via `UART1_CTS_PIN`)
|
||||
- **GPIO_RTS_MONITOR**: GPIO5 (for GPIO-controlled mode, configurable via `GPIO_RTS_MONITOR`)
|
||||
- **GPIO_CTS_CTRL**: GPIO13 (for GPIO-controlled mode, configurable via `GPIO_CTS_CTRL`)
|
||||
|
||||
**Note:** RX1 and TX1 pin numbers are board-specific. Check your board's pin definitions or use the serial output to see the actual GPIO numbers being used.
|
||||
|
||||
### Option 1: Simple Loopback (`USE_GPIO_CONTROL = false`)
|
||||
|
||||
For a basic loopback test with automatic flow control:
|
||||
|
||||
```
|
||||
ESP32 Pin Connections:
|
||||
- TX1 ────┐
|
||||
├──> RX1 (Data loopback)
|
||||
|
||||
- GPIO2 (RTS1) ────┐
|
||||
├──> GPIO4 (CTS1) (Flow control loopback)
|
||||
```
|
||||
|
||||
**Physical Connections (when USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0):**
|
||||
1. Connect TX1 pin to RX1 pin with a jumper wire - read the console serial output to know which pins are the default ones
|
||||
2. Connect GPIO2 (RTS1) to GPIO4 (CTS1) with a jumper wire
|
||||
|
||||
### Option 2: GPIO-Controlled Flow Control (`USE_GPIO_CONTROL = true`)
|
||||
|
||||
For manual control of flow control signals:
|
||||
|
||||
```
|
||||
ESP32 Pin Connections:
|
||||
- TX1 ────> RX1 (Data loopback)
|
||||
- GPIO2 (RTS1) ────> GPIO5 (RTS Monitor) (Monitor RTS state)
|
||||
- GPIO4 (CTS1) <─── GPIO13 (CTS Control) (Control CTS signal)
|
||||
```
|
||||
|
||||
**Physical Connections (when USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0):**
|
||||
1. Connect TX1 pin to RX1 pin with a jumper wire
|
||||
2. Connect GPIO2 (RTS1) to GPIO5 with a jumper wire
|
||||
3. Connect GPIO4 (CTS1) to GPIO13 with a jumper wire
|
||||
|
||||
## How Hardware Flow Control Works
|
||||
|
||||
### RTS (Request To Send)
|
||||
- **Output signal** from the UART
|
||||
- **LOW (0 V)**: UART is ready to receive data (RX buffer has space)
|
||||
- **HIGH (3.3 V)**: UART RX buffer is getting full, cannot receive more data
|
||||
|
||||
### CTS (Clear To Send)
|
||||
- **Input signal** to the UART
|
||||
- **LOW (0 V)**: UART is allowed to transmit data
|
||||
- **HIGH (3.3 V)**: UART must pause transmission (transmission is blocked)
|
||||
|
||||
### Flow Control Behavior
|
||||
|
||||
1. **Receiving Data (RTS)**:
|
||||
- When UART1's RX buffer has space, RTS1 is driven LOW
|
||||
- When RX buffer fills up (threshold reached), RTS1 is driven HIGH
|
||||
- This signals the sender to stop transmitting
|
||||
|
||||
2. **Transmitting Data (CTS)**:
|
||||
- UART1 checks CTS1 before transmitting
|
||||
- If CTS1 is LOW, transmission proceeds normally
|
||||
- If CTS1 is HIGH, UART1 pauses transmission until CTS1 goes LOW again
|
||||
|
||||
### Understanding the Two Modes
|
||||
|
||||
**`USE_GPIO_CONTROL = false` (Default - Simple Loopback)**
|
||||
- Use this mode when you connect RTS1 directly to CTS1 (hardware loopback)
|
||||
- Flow control operates automatically - no software intervention needed
|
||||
- RTS/CTS signals are controlled entirely by the UART hardware
|
||||
- Best for: Basic testing and understanding automatic flow control behavior
|
||||
- **Wiring (when USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0):** Connect GPIO2 (RTS1) → GPIO4 (CTS1)
|
||||
|
||||
**`USE_GPIO_CONTROL = true` (GPIO-Controlled Mode)**
|
||||
- Use this mode when you want to manually control or monitor flow control signals
|
||||
- Software can read RTS state and control CTS signal via GPIO pins
|
||||
- Demonstrates explicit flow control blocking behavior
|
||||
- Best for: Testing flow control behavior, interfacing with external logic, or learning how external devices control UART transmission
|
||||
- **Wiring (when USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0):**
|
||||
- Connect GPIO2 (RTS1) → GPIO5 (to monitor RTS)
|
||||
- Connect GPIO4 (CTS1) → GPIO13 (to control CTS)
|
||||
- **Note:** This mode is overridden when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`
|
||||
|
||||
### How to Configure
|
||||
|
||||
1. Open `HardwareFlowControl_Demo.ino` in Arduino IDE
|
||||
2. **For internal loopback (no wires):** Set `USE_INTERNAL_MATRIX_PIN_LOOPBACK` to `1` (default)
|
||||
3. **For external wires:** Set `USE_INTERNAL_MATRIX_PIN_LOOPBACK` to `0` and configure `USE_GPIO_CONTROL`:
|
||||
- `false` for hardware-controlled mode
|
||||
- `true` for GPIO-controlled mode
|
||||
4. Make sure your physical wiring matches the selected mode (only if `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`)
|
||||
5. Upload the sketch
|
||||
|
||||
**Important:**
|
||||
- When `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`, no external connections are needed
|
||||
- When `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`, the wiring configuration must match the `USE_GPIO_CONTROL` setting
|
||||
|
||||
## Code Explanation
|
||||
|
||||
### Key Functions Used
|
||||
|
||||
1. **`begin(baudrate)`**
|
||||
- Initializes the UART with the specified baud rate
|
||||
- Must be called before setting pins and enabling hardware flow control
|
||||
|
||||
2. **`setPins(rxPin, txPin, ctsPin, rtsPin)`**
|
||||
- Configures the UART pins
|
||||
- Note: The order `begin()` then `setPins()` is important for proper initialization
|
||||
|
||||
3. **`uart_internal_loopback(uartNum, rxPin)`** (when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`)
|
||||
- Creates internal GPIO matrix connection for TX→RX loopback
|
||||
- No external wires needed
|
||||
|
||||
4. **`uart_internal_hw_flow_ctrl_loopback(uartNum, ctsPin)`** (when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`)
|
||||
- Creates internal GPIO matrix connection for RTS→CTS flow control loopback
|
||||
- No external wires needed
|
||||
|
||||
5. **`setHwFlowCtrlMode(mode, threshold)`**
|
||||
- Enables hardware flow control
|
||||
- Modes:
|
||||
- `UART_HW_FLOWCTRL_DISABLE`: Disable flow control
|
||||
- `UART_HW_FLOWCTRL_RTS`: Enable RX flow control only
|
||||
- `UART_HW_FLOWCTRL_CTS`: Enable TX flow control only
|
||||
- `UART_HW_FLOWCTRL_CTS_RTS`: Enable full flow control (default)
|
||||
- Threshold: Number of bytes in RX FIFO before RTS is asserted (default: 64)
|
||||
|
||||
### Example Behavior
|
||||
|
||||
The sketch demonstrates:
|
||||
- Periodic transmission of messages
|
||||
- Flow control blocking when CTS is HIGH
|
||||
- Monitoring of RTS/CTS pin states
|
||||
- Loopback reception of transmitted data
|
||||
|
||||
## Expected Output and Behavior
|
||||
|
||||
The sketch behavior differs depending on the `USE_GPIO_CONTROL` setting (see Configuration section above for details).
|
||||
|
||||
### Mode 1: Hardware-Controlled Flow Control (`USE_GPIO_CONTROL = false`)
|
||||
|
||||
**Behavior:**
|
||||
- RTS and CTS signals are automatically controlled by the UART hardware
|
||||
- RTS1 is directly connected to CTS1 (hardware loopback)
|
||||
- Flow control operates automatically without software intervention
|
||||
- RTS goes LOW when ready to receive, HIGH when buffer is full
|
||||
- CTS must be LOW for transmission to proceed (automatically controlled by RTS)
|
||||
|
||||
**Expected Output:**
|
||||
|
||||
```
|
||||
========================================
|
||||
ESP32 Hardware Flow Control Demo
|
||||
========================================
|
||||
|
||||
Initializing UART1...
|
||||
Using hardware-controlled flow control (simple loopback)
|
||||
UART1 initialized successfully!
|
||||
Hardware flow control: ENABLED (RTS + CTS)
|
||||
RX Pin: GPIO26 (for the ESP32 RX1 or board-specific RX1 default)
|
||||
TX Pin: GPIO27 (for the ESP32 TX1 or board-specific TX1 default)
|
||||
RTS Pin: GPIO2 (output from UART)
|
||||
CTS Pin: GPIO4 (input to UART)
|
||||
|
||||
NO EXTERNAL PIN CONNECTIONS ARE REQUIRED:
|
||||
-------------------------
|
||||
Internal GPIO Matrix connection with flow control mode:
|
||||
1. Automatic Internal Connection of TX1 to RX1 - Loopback (via GPIO matrix)
|
||||
2. Automatic Internal Connection of GPIO2 (RTS1) to GPIO4 (CTS1) - Flow control loopback
|
||||
|
||||
Note: In this mode, RTS/CTS are automatically controlled by hardware.
|
||||
RTS goes LOW when ready to receive, HIGH when buffer is full.
|
||||
CTS must be LOW for transmission to proceed.
|
||||
|
||||
Starting demonstration in 2 seconds...
|
||||
|
||||
=== UART1 Pin Status ===
|
||||
RX Pin (GPIO26): ESP32 Receiving data (or board-specific RX1)
|
||||
TX Pin (GPIO27): ESP32 Transmitting data (or board-specific TX1)
|
||||
RTS Pin (GPIO2): Hardware controlled (LOW = ready to receive)
|
||||
CTS Pin (GPIO4): Hardware controlled (LOW = can transmit)
|
||||
Note: RTS/CTS pins are hardware-controlled. Connect RTS1 to CTS1 for loopback.
|
||||
Available for write: 128 bytes
|
||||
Available to read: 0 bytes
|
||||
========================
|
||||
|
||||
Sending: Message #1: Hello from UART1! Time: 1000 ms
|
||||
-> Written: 45 bytes
|
||||
Received: Message #1: Hello from UART1! Time: 1000 ms
|
||||
|
||||
=== UART1 Pin Status ===
|
||||
RX Pin (GPIO26): ESP32 Receiving data (or board-specific RX1)
|
||||
TX Pin (GPIO27): ESP32 Transmitting data (or board-specific TX1)
|
||||
RTS Pin (GPIO2): Hardware controlled (LOW = ready to receive)
|
||||
CTS Pin (GPIO4): Hardware controlled (LOW = can transmit)
|
||||
Note: RTS/CTS pins are hardware-controlled. Connect RTS1 to CTS1 for loopback.
|
||||
Available for write: 128 bytes
|
||||
Available to read: 45 bytes
|
||||
========================
|
||||
|
||||
Sending: Message #2: Hello from UART1! Time: 2000 ms
|
||||
-> Written: 45 bytes
|
||||
Received: Message #2: Hello from UART1! Time: 2000 ms
|
||||
```
|
||||
|
||||
**Key Characteristics:**
|
||||
- No manual CTS toggling messages
|
||||
- Flow control happens automatically based on RX buffer state
|
||||
- RTS/CTS states are not directly readable (hardware-controlled)
|
||||
- Transmission is always allowed (CTS follows RTS automatically)
|
||||
|
||||
### Mode 2: GPIO-Controlled Flow Control (`USE_GPIO_CONTROL = true`)
|
||||
|
||||
**Behavior:**
|
||||
- RTS signal is monitored via GPIO5 (connected to RTS1)
|
||||
- CTS signal is controlled via GPIO13 (connected to CTS1)
|
||||
- Software can manually block/allow transmission by controlling GPIO13
|
||||
- Demonstrates explicit flow control blocking behavior
|
||||
- Shows how external devices can control UART transmission
|
||||
- **Note:** This mode only works when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`
|
||||
|
||||
**Expected Output:**
|
||||
|
||||
```
|
||||
========================================
|
||||
ESP32 Hardware Flow Control Demo
|
||||
========================================
|
||||
|
||||
Initializing UART1...
|
||||
Using GPIO-controlled flow control mode
|
||||
UART1 initialized successfully!
|
||||
Hardware flow control: ENABLED (RTS + CTS)
|
||||
RX Pin: GPIO26 (or board-specific RX1 default)
|
||||
TX Pin: GPIO27 (or board-specific TX1 default)
|
||||
RTS Pin: GPIO2 (output from UART)
|
||||
CTS Pin: GPIO4 (input to UART)
|
||||
|
||||
PIN CONNECTIONS REQUIRED:
|
||||
-------------------------
|
||||
GPIO-controlled flow control mode:
|
||||
1. Connect TX1 to RX1 - Loopback (board-specific pins)
|
||||
2. Connect GPIO2 (RTS1) to GPIO5 - Monitor RTS state
|
||||
3. Connect GPIO4 (CTS1) to GPIO13 - Control CTS signal
|
||||
|
||||
Starting demonstration in 2 seconds...
|
||||
|
||||
=== UART1 Pin Status ===
|
||||
RX Pin (GPIO26): Receiving data (or board-specific RX1)
|
||||
TX Pin (GPIO27): Transmitting data (or board-specific TX1)
|
||||
RTS Pin (GPIO2): LOW (Ready) (LOW = ready to receive)
|
||||
CTS Pin (GPIO4): LOW (Clear) (LOW = can transmit)
|
||||
Available for write: 128 bytes
|
||||
Available to read: 0 bytes
|
||||
========================
|
||||
|
||||
Sending: Message #1: Hello from UART1! Time: 1000 ms
|
||||
-> Written: 45 bytes
|
||||
Received: Message #1: Hello from UART1! Time: 1000 ms
|
||||
|
||||
=== UART1 Pin Status ===
|
||||
RX Pin (GPIO26): Receiving data (or board-specific RX1)
|
||||
TX Pin (GPIO27): Transmitting data (or board-specific TX1)
|
||||
RTS Pin (GPIO2): LOW (Ready) (LOW = ready to receive)
|
||||
CTS Pin (GPIO4): LOW (Clear) (LOW = can transmit)
|
||||
Available for write: 128 bytes
|
||||
Available to read: 45 bytes
|
||||
========================
|
||||
|
||||
>>> Allowing transmission (CTS LOW)...
|
||||
Sending: Message #2: Hello from UART1! Time: 2000 ms
|
||||
-> Written: 45 bytes
|
||||
Received: Message #2: Hello from UART1! Time: 2000 ms
|
||||
|
||||
=== UART1 Pin Status ===
|
||||
RX Pin (GPIO26): Receiving data (or board-specific RX1)
|
||||
TX Pin (GPIO27): Transmitting data (or board-specific TX1)
|
||||
RTS Pin (GPIO2): LOW (Ready) (LOW = ready to receive)
|
||||
CTS Pin (GPIO4): HIGH (Blocked) (LOW = can transmit)
|
||||
Available for write: 128 bytes
|
||||
Available to read: 45 bytes
|
||||
========================
|
||||
|
||||
>>> Blocking transmission (CTS HIGH)...
|
||||
!!! Transmission blocked - CTS is HIGH !!!
|
||||
|
||||
=== UART1 Pin Status ===
|
||||
RX Pin (GPIO26): Receiving data (or board-specific RX1)
|
||||
TX Pin (GPIO27): Transmitting data (or board-specific TX1)
|
||||
RTS Pin (GPIO2): LOW (Ready) (LOW = ready to receive)
|
||||
CTS Pin (GPIO4): HIGH (Blocked) (LOW = can transmit)
|
||||
Available for write: 128 bytes
|
||||
Available to read: 45 bytes
|
||||
========================
|
||||
|
||||
>>> Allowing transmission (CTS LOW)...
|
||||
Sending: Message #3: Hello from UART1! Time: 3000 ms
|
||||
-> Written: 45 bytes
|
||||
Received: Message #3: Hello from UART1! Time: 3000 ms
|
||||
```
|
||||
|
||||
**Key Characteristics:**
|
||||
- Explicit messages showing CTS state changes ("Allowing transmission" / "Blocking transmission")
|
||||
- Transmission blocking messages when CTS is HIGH
|
||||
- RTS/CTS pin states are readable via GPIO5 and GPIO13
|
||||
- Demonstrates manual flow control
|
||||
- Useful for testing flow control behavior or interfacing with external flow control logic
|
||||
- Only works when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. **No data received**:
|
||||
- If `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`: Check that the internal loopback functions are being called
|
||||
- If `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`: Check that TX1 is connected to RX1
|
||||
2. **Transmission always blocked**: Verify CTS pin connection and state (only applies when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`)
|
||||
3. **RTS always HIGH**: RX buffer may be full, try reading data
|
||||
4. **Compilation errors**: Ensure you're using ESP32 Arduino Core 2.0.0 or later
|
||||
5. **GPIO-controlled mode not working**: Make sure `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0` (internal loopback overrides GPIO control)
|
||||
|
||||
## Notes
|
||||
|
||||
- **Internal Loopback Mode** (`USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`): No external connections needed! The ESP32 GPIO matrix handles all connections internally. This is the easiest way to test hardware flow control.
|
||||
- **External Wire Mode** (`USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`): Requires physical connections between RTS and CTS pins (and TX/RX for data loopback)
|
||||
- The threshold parameter controls when RTS is asserted (default: 64 bytes = half of 128-byte FIFO)
|
||||
- Flow control is most useful when communicating with devices that support it (modems, some sensors, etc.)
|
||||
- For simple point-to-point communication without flow control support, you can disable it
|
||||
Reference in New Issue
Block a user