1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-11 15:22:13 +03:00

Function added to detect baudrate (#4978)

* Function added to detect baudrate

* Added uart_start_detect_baudrate, detectBaudrate() wrappers for HardwareSerial and an example usage SerialDetectBaudrate.ino

* Some layout changes to pass Travis tests

* Some more nitty-gritty layout changes to pass Travis tests

* Some even more nitty-gritty layout changes to pass Travis tests

* renamed one function to testBaudrate() and updated doc/reference.rst

* Minor updates to doc/reference.rst

* New lines added
This commit is contained in:
Jeroen88
2018-08-01 21:33:25 +02:00
committed by Develo
parent 3ab38d690d
commit e4d9c279ef
6 changed files with 125 additions and 0 deletions

View File

@ -108,6 +108,30 @@ void HardwareSerial::flush()
delayMicroseconds(11000000 / uart_get_baudrate(_uart) + 1); delayMicroseconds(11000000 / uart_get_baudrate(_uart) + 1);
} }
void HardwareSerial::startDetectBaudrate()
{
uart_start_detect_baudrate(_uart_nr);
}
unsigned long HardwareSerial::testBaudrate()
{
return uart_detect_baudrate(_uart_nr);
}
unsigned long HardwareSerial::detectBaudrate(time_t timeoutMillis)
{
time_t startMillis = millis();
unsigned long detectedBaudrate;
while ((time_t) millis() - startMillis < timeoutMillis) {
if ((detectedBaudrate = testBaudrate())) {
break;
}
yield();
delay(100);
}
return detectedBaudrate;
}
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
HardwareSerial Serial(UART0); HardwareSerial Serial(UART0);
#endif #endif

View File

@ -184,6 +184,12 @@ public:
return uart_has_overrun(_uart); return uart_has_overrun(_uart);
} }
void startDetectBaudrate();
unsigned long testBaudrate();
unsigned long detectBaudrate(time_t timeoutMillis);
protected: protected:
int _uart_nr; int _uart_nr;
uart_t* _uart = nullptr; uart_t* _uart = nullptr;

View File

@ -44,6 +44,7 @@
#include "uart.h" #include "uart.h"
#include "esp8266_peri.h" #include "esp8266_peri.h"
#include "user_interface.h" #include "user_interface.h"
#include "uart_register.h"
const char overrun_str [] ICACHE_RODATA_ATTR STORE_ATTR = "uart input full!\r\n"; const char overrun_str [] ICACHE_RODATA_ATTR STORE_ATTR = "uart input full!\r\n";
static int s_uart_debug_nr = UART0; static int s_uart_debug_nr = UART0;
@ -739,3 +740,49 @@ uart_get_debug()
{ {
return s_uart_debug_nr; return s_uart_debug_nr;
} }
/*
To start detection of baud rate with the UART the UART_AUTOBAUD_EN bit needs to be cleared and set. The ROM function uart_baudrate_detect() does this only once, so on a next call the UartDev.rcv_state is not equal to BAUD_RATE_DET. Instead of poking around in the UartDev struct with unknown effect, the UART_AUTOBAUD_EN bit is directly triggered by the function uart_detect_baudrate().
*/
void
uart_start_detect_baudrate(int uart_nr)
{
USA(uart_nr) &= ~(UART_GLITCH_FILT << UART_GLITCH_FILT_S | UART_AUTOBAUD_EN);
USA(uart_nr) = 0x08 << UART_GLITCH_FILT_S | UART_AUTOBAUD_EN;
}
int
uart_detect_baudrate(int uart_nr)
{
static bool doTrigger = true;
if (doTrigger)
{
uart_start_detect_baudrate(uart_nr);
doTrigger = false;
}
int32_t divisor = uart_baudrate_detect(uart_nr, 1);
if (!divisor) {
return 0;
}
doTrigger = true; // Initialize for a next round
int32_t baudrate = UART_CLK_FREQ / divisor;
static const int default_rates[] = {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 256000, 460800, 921600, 1843200, 3686400};
size_t i;
for (i = 1; i < sizeof(default_rates) / sizeof(default_rates[0]) - 1; i++) // find the nearest real baudrate
{
if (baudrate <= default_rates[i])
{
if (baudrate - default_rates[i - 1] < default_rates[i] - baudrate) {
i--;
}
break;
}
}
return default_rates[i];
}

View File

@ -141,6 +141,9 @@ bool uart_has_overrun (uart_t* uart); // returns then clear overrun flag
void uart_set_debug(int uart_nr); void uart_set_debug(int uart_nr);
int uart_get_debug(); int uart_get_debug();
void uart_start_detect_baudrate(int uart_nr);
int uart_detect_baudrate(int uart_nr);
#if defined (__cplusplus) #if defined (__cplusplus)
} // extern "C" } // extern "C"

View File

@ -155,6 +155,17 @@ current speed. For example
| Note that this implementation is **only for ESP8266 based boards**, | Note that this implementation is **only for ESP8266 based boards**,
and will not works with other Arduino boards. and will not works with other Arduino boards.
To detect an unknown baudrate of data coming into Serial use ``Serial.detectBaudrate(time_t timeoutMillis)``. This method tries to detect the baudrate for a maximum of timeoutMillis ms. It returns zero if no baudrate was detected, or the detected baudrate otherwise. The ``detectBaudrate()`` function may be called before ``Serial.begin()`` is called, because it does not need the receive buffer nor the SerialConfig parameters.
The uart can not detect other parameters like number of start- or stopbits, number of data bits or parity.
The detection itself does not change the baudrate, after detection it should be set as usual using ``Serial.begin(detectedBaudrate)``.
Detection is very fast, it takes only a few incoming bytes.
SerialDetectBaudrate.ino is a full example of usage.
Progmem Progmem
------- -------

View File

@ -0,0 +1,34 @@
#define TIMEOUT (10000UL) // Maximum time to wait for serial activity to start
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
// Serial.detectBaudrate() may also be called before Serial.begin()
// There must be activity on the serial port for the baudrate to be detected
unsigned long detectedBaudrate = Serial.detectBaudrate(TIMEOUT);
if (detectedBaudrate) {
Serial.printf("\nDetected baudrate is %lu, switching to that baudrate now...\n", detectedBaudrate);
// Wait for printf to finish
while (Serial.availableForWrite() != UART_TX_FIFO_SIZE) {
yield();
}
// Clear Tx buffer to avoid extra characters being printed
Serial.flush();
// After this, any writing to Serial will print gibberish on the serial monitor if the baudrate doesn't match
Serial.begin(detectedBaudrate);
} else {
Serial.println("\nNothing detected");
}
}
void loop() {
// put your main code here, to run repeatedly:
}