|
| 1 | +/* |
| 2 | + * This is C++ example that demonstrates the usage of a std::function as OnReceive Callback function to all the UARTs |
| 3 | + * It basically defines a general onReceive function that receives an extra parameter, the Serial pointer that is |
| 4 | + * executing the callback. |
| 5 | + * |
| 6 | + * For each HardwareSerial object (Serial, Serial1, Serial2), it is necessary to set the callback with |
| 7 | + * the repective Serial pointer. It is done using lambda expression as a std::function. |
| 8 | + * Example: |
| 9 | + * Serial1.onReceive([]() { processOnReceiving(&Serial1); }); |
| 10 | + * |
| 11 | + */ |
| 12 | + |
| 13 | +// soc/soc_caps.h has information about each SoC target |
| 14 | +// in this example, we use SOC_UART_NUM that goes from 1 to 3, |
| 15 | +// depending on the number of available UARTs in the ESP32xx |
| 16 | +// This makes the code transparent to what SoC is used. |
| 17 | +#include "soc/soc_caps.h" |
| 18 | + |
| 19 | +// In case that the target has USB CDC and it has being selected to be enable on boot, |
| 20 | +// the console output will into USB (Serial). |
| 21 | +// Otherwise the output will be sent to UART0 (Serial) and we have to redefine Serial0 |
| 22 | +#ifndef ARDUINO_USB_CDC_ON_BOOT |
| 23 | +#define ARDUINO_USB_CDC_ON_BOOT 0 |
| 24 | +#endif |
| 25 | +#if ARDUINO_USB_CDC_ON_BOOT == 0 // No USB CDC |
| 26 | +#define Serial0 Serial // redefine the symbol Serial0 to the default Arduino |
| 27 | +#endif |
| 28 | + |
| 29 | +// This example shall use UART1 or UART2 for testing and UART0 for console messages |
| 30 | +// If UART0 is used for testing, it is necessary to manually send data to it, using the Serial Monitor/Terminal |
| 31 | +// In case that USB CDC is available, it may be used as console for messages. |
| 32 | +#define TEST_UART 1 // Serial# (0, 1 or 2) will be used for the loopback |
| 33 | +#define RXPIN 4 // GPIO 4 => RX for Serial1 or Serial2 |
| 34 | +#define TXPIN 5 // GPIO 5 => TX for Serial1 or Serial2 |
| 35 | + |
| 36 | +// declare testingSerial (as reference) related to TEST_UART number defined above (only for Serial1 and Serial2) |
| 37 | +#if SOC_UART_NUM > 1 && TEST_UART == 1 |
| 38 | + HardwareSerial &testingSerial = Serial1; |
| 39 | +#elif SOC_UART_NUM > 2 && TEST_UART == 2 |
| 40 | + HardwareSerial &testingSerial = Serial2; |
| 41 | +#endif |
| 42 | + |
| 43 | +// General callback function for any UART -- used with a lambda std::function within HardwareSerial::onReceive() |
| 44 | +void processOnReceiving(HardwareSerial &mySerial) { |
| 45 | + // detects which Serial# is being used here |
| 46 | + int8_t uart_num = -1; |
| 47 | + if (&mySerial == &Serial0) { |
| 48 | + uart_num = 0; |
| 49 | +#if SOC_UART_NUM > 1 |
| 50 | + } else if (&mySerial == &Serial1) { |
| 51 | + uart_num = 1; |
| 52 | +#endif |
| 53 | +#if SOC_UART_NUM > 2 |
| 54 | + } else if (&mySerial == &Serial2) { |
| 55 | + uart_num = 2; |
| 56 | +#endif |
| 57 | + } |
| 58 | + |
| 59 | + //Prints some information on the current Serial (UART0 or USB CDC) |
| 60 | + if (uart_num == -1) { |
| 61 | + Serial.println("This is not a know Arduino Serial# object..."); |
| 62 | + return; |
| 63 | + } |
| 64 | + Serial.printf("\nOnReceive Callback --> Received Data from UART%d\n", uart_num); |
| 65 | + Serial.printf("Received %d bytes\n", mySerial.available()); |
| 66 | + Serial.printf("First byte is '%c' [0x%02x]\n", mySerial.peek(), mySerial.peek()); |
| 67 | + uint8_t charPerLine = 0; |
| 68 | + while(mySerial.available()) { |
| 69 | + char c = mySerial.read(); |
| 70 | + Serial.printf("'%c' [0x%02x] ", c, c); |
| 71 | + if (++charPerLine == 10) { |
| 72 | + charPerLine = 0; |
| 73 | + Serial.println(); |
| 74 | + } |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +void setup() { |
| 79 | + // Serial can be the USB or UART0, depending on the settings and which SoC is used |
| 80 | + Serial.begin(115200); |
| 81 | + |
| 82 | + // when data is received from UART0, it will call the general function |
| 83 | + // passing Serial0 as parameter for processing |
| 84 | +#if TEST_UART == 0 |
| 85 | + Serial0.begin(115200); // keeps default GPIOs |
| 86 | + Serial0.onReceive([]() { |
| 87 | + processOnReceiving(Serial0); |
| 88 | + }); |
| 89 | +#else |
| 90 | + // and so on for the other UARTs (Serial1 and Serial2) |
| 91 | + // Rx = 4, Tx = 5 will work for ESP32, S2, S3, C3, C6 and H2 |
| 92 | + testingSerial.begin(115200, SERIAL_8N1, RXPIN, TXPIN); |
| 93 | + testingSerial.onReceive([]() { |
| 94 | + processOnReceiving(testingSerial); |
| 95 | + }); |
| 96 | +#endif |
| 97 | + |
| 98 | + // this helper function will connect TX pin (from TEST_UART number) to its RX pin |
| 99 | + // creating a loopback that will allow to write to TEST_UART number |
| 100 | + // and send it to RX with no need to physically connect both pins |
| 101 | +#if TEST_UART > 0 |
| 102 | + uart_internal_loopback(TEST_UART, RXPIN); |
| 103 | +#else |
| 104 | + // when UART0 is used for testing, it is necessary to send data using the Serial Monitor/Terminal |
| 105 | + // Data must be sent by the CP2102, manually using the Serial Monitor/Terminal |
| 106 | +#endif |
| 107 | + |
| 108 | + delay(500); |
| 109 | + Serial.printf("\nSend bytes to UART%d in order to\n", TEST_UART); |
| 110 | + Serial.println("see a single processing fuction display information about"); |
| 111 | + Serial.println("the received data.\n"); |
| 112 | + |
| 113 | +} |
| 114 | + |
| 115 | +void loop() { |
| 116 | + // All done by the UART callback functions |
| 117 | + // just write a random number of bytes into the testing UART |
| 118 | + char serial_data[24]; |
| 119 | + size_t len = random(sizeof(serial_data) - 1) + 1; // at least 1 byte will be sent |
| 120 | + for (uint8_t i = 0; i < len; i++) serial_data[i] = 'A' + i; |
| 121 | + |
| 122 | +#if TEST_UART > 0 |
| 123 | + Serial.println("\n\n=================================="); |
| 124 | + Serial.printf("Sending %d bytes to UART%d...\n", len, TEST_UART); |
| 125 | + testingSerial.write(serial_data, len); |
| 126 | +#else |
| 127 | + // when UART0 is used for testing, it is necessary to send data using the Serial Monitor/Terminal |
| 128 | + Serial.println("Use the Serial Monitor/Terminal to send data to UART0"); |
| 129 | +#endif |
| 130 | + Serial.println("pausing for 15 seconds."); |
| 131 | + delay(15000); |
| 132 | +} |
| 133 | + |
0 commit comments