Skip to content

Commit 233d31b

Browse files
Jeroen88me-no-dev
Jeroen88
authored andcommitted
Added baudrate detection to esp32-hal-uart and HardwareSerial (espressif#1961)
* Added baudrate detection to esp32-hal-uart and HardwareSerial * Solved compiler warning for uartResizeRxBuffer() * Add unit to header variable name (timeout_ms) * Reverting accidentally changed files to master * Add small delay after baudrate detection
1 parent 65c861a commit 233d31b

File tree

4 files changed

+105
-4
lines changed

4 files changed

+105
-4
lines changed

cores/esp32/HardwareSerial.cpp

+21-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ HardwareSerial Serial2(2);
3030

3131
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {}
3232

33-
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert)
33+
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms)
3434
{
3535
if(0 > _uart_nr || _uart_nr > 2) {
3636
log_e("Serial number is invalid, please use 0, 1 or 2");
@@ -51,7 +51,26 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
5151
rxPin = RX2;
5252
txPin = TX2;
5353
}
54-
_uart = uartBegin(_uart_nr, baud, config, rxPin, txPin, 256, invert);
54+
55+
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert);
56+
57+
if(!baud) {
58+
time_t startMillis = millis();
59+
unsigned long detectedBaudRate;
60+
while(millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) {
61+
yield();
62+
}
63+
64+
end();
65+
66+
if(detectedBaudRate) {
67+
delay(100); // Give some time...
68+
_uart = uartBegin(_uart_nr, detectedBaudRate, config, rxPin, txPin, 256, invert);
69+
} else {
70+
log_e("Could not detect baudrate. Serial data at the port must be present within the timeout for detection to be possible");
71+
_uart = NULL;
72+
}
73+
}
5574
}
5675

5776
void HardwareSerial::end()

cores/esp32/HardwareSerial.h

+19-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,24 @@
2222
Modified 18 December 2014 by Ivan Grokhotkov (esp8266 platform support)
2323
Modified 31 March 2015 by Markus Sattler (rewrite the code for UART0 + UART1 support in ESP8266)
2424
Modified 25 April 2015 by Thomas Flayols (add configuration different from 8N1 in ESP8266)
25+
Modified 13 October 2018 by Jeroen Döll (add baudrate detection)
26+
Baudrate detection example usage (detection on Serial1):
27+
void setup() {
28+
Serial.begin(115200);
29+
delay(100);
30+
Serial.println();
31+
32+
Serial1.begin(0, SERIAL_8N1, -1, -1, true, 11000UL); // Passing 0 for baudrate to detect it, the last parameter is a timeout in ms
33+
34+
unsigned long detectedBaudRate = Serial1.baudRate();
35+
if(detectedBaudRate) {
36+
Serial.printf("Detected baudrate is %lu\n", detectedBaudRate);
37+
} else {
38+
Serial.println("No baudrate detected, Serial1 will not work!");
39+
}
40+
}
41+
42+
Pay attention: the baudrate returned by baudRate() may be rounded, eg 115200 returns 115201
2543
*/
2644

2745
#ifndef HardwareSerial_h
@@ -37,7 +55,7 @@ class HardwareSerial: public Stream
3755
public:
3856
HardwareSerial(int uart_nr);
3957

40-
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false);
58+
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL);
4159
void end();
4260
int available(void);
4361
int availableForWrite(void);

cores/esp32/esp32-hal-uart.c

+63-1
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ void uartEnd(uart_t* uart)
242242

243243
size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
244244
if(uart == NULL) {
245-
return;
245+
return 0;
246246
}
247247

248248
UART_MUTEX_LOCK();
@@ -455,3 +455,65 @@ int log_printf(const char *format, ...)
455455
}
456456
return len;
457457
}
458+
459+
/*
460+
* if enough pulses are detected return the minimum high pulse duration + minimum low pulse duration divided by two.
461+
* This equals one bit period. If flag is true the function return inmediately, otherwise it waits for enough pulses.
462+
*/
463+
unsigned long uartBaudrateDetect(uart_t *uart, bool flg)
464+
{
465+
while(uart->dev->rxd_cnt.edge_cnt < 30) { // UART_PULSE_NUM(uart_num)
466+
if(flg) return 0;
467+
ets_delay_us(1000);
468+
}
469+
470+
UART_MUTEX_LOCK();
471+
unsigned long ret = ((uart->dev->lowpulse.min_cnt + uart->dev->highpulse.min_cnt) >> 1) + 12;
472+
UART_MUTEX_UNLOCK();
473+
474+
return ret;
475+
}
476+
477+
/*
478+
* To start detection of baud rate with the uart the auto_baud.en bit needs to be cleared and set. The bit period is
479+
* detected calling uartBadrateDetect(). The raw baudrate is computed using the UART_CLK_FREQ. The raw baudrate is
480+
* rounded to the closed real baudrate.
481+
*/
482+
unsigned long
483+
uartDetectBaudrate(uart_t *uart)
484+
{
485+
static bool uartStateDetectingBaudrate = false;
486+
487+
if(!uartStateDetectingBaudrate) {
488+
uart->dev->auto_baud.glitch_filt = 0x08;
489+
uart->dev->auto_baud.en = 0;
490+
uart->dev->auto_baud.en = 1;
491+
uartStateDetectingBaudrate = true;
492+
}
493+
494+
unsigned long divisor = uartBaudrateDetect(uart, true);
495+
if (!divisor) {
496+
return 0;
497+
}
498+
499+
uart->dev->auto_baud.en = 0;
500+
uartStateDetectingBaudrate = false; // Initialize for the next round
501+
502+
unsigned long baudrate = UART_CLK_FREQ / divisor;
503+
504+
static const unsigned long default_rates[] = {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 256000, 460800, 921600, 1843200, 3686400};
505+
506+
size_t i;
507+
for (i = 1; i < sizeof(default_rates) / sizeof(default_rates[0]) - 1; i++) // find the nearest real baudrate
508+
{
509+
if (baudrate <= default_rates[i])
510+
{
511+
if (baudrate - default_rates[i - 1] < default_rates[i] - baudrate) {
512+
i--;
513+
}
514+
break;
515+
}
516+
}
517+
518+
return default_rates[i];
519+
}

cores/esp32/esp32-hal-uart.h

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ size_t uartResizeRxBuffer(uart_t* uart, size_t new_size);
7272
void uartSetDebug(uart_t* uart);
7373
int uartGetDebug();
7474

75+
unsigned long uartDetectBaudrate(uart_t *uart);
76+
7577
#ifdef __cplusplus
7678
}
7779
#endif

0 commit comments

Comments
 (0)