Change baud rate: end(); begin(); also needs clear()

Status
Not open for further replies.
Teensy 3.5, Teensyduino 1.48

I need to change the baud rate of a hardware UART on the fly under user control. The obvious sequence is Serial1.end(); Serial1.begin(newbaud);. This does indeed change the baud rate but it apparently leaves the receive FIFO in a weird state. It sorts itself out after a few dozen characters, but until then the characters are scrambled up and mixed with characters that arrived before the baud rate change. This is not timing dependent.

A workaround is to call Serial1.clear() after Serial1.begin(). I believe the active ingredient here is the UART_CFIFO_RXFLUSH command, though I have not tested that. This is not ideal, since clear() is not part of the official documented Arduino API for serial ports.

I suggest the FIFO flush, if not the entire contents of serial_clear(), be added to the code in serial_begin(), so this workaround will not be necessary.

I created a simple demo sketch to reproduce the problem:

Code:
// This is intended to be a minimal demo of a problem in the Teensy3 hardware serial driver.
//
// Symptom: if we call Serial1.end() and then Serial1.begin(), as we might do to change the
//          baud rate, the characters received on Serial1 after the transition are scrambled up.
//          Sometime they include repeats of characters received before the transition, and
//          sometimes the characters are just out of order. This continues for some number of
//          received characters before sorting itself out.
//
// Program description: Passes through received characters from Serial1 to USB Serial.
//                      A received character on USB Serial (e.g., a blank line from
//                      the Send line in the Arduino IDE) triggers Serial1.end()
//                      followed by Serial1.begin().
//
// Procedure: Connect a terminal emulator to Serial1 (pins 0 and 1) and run the
//            program. Open the serial monitor. Type "1234567890" on the terminal,
//            and see it echoed on the serial monitor. Click Send on the serial
//            monitor. Now type "abcdefghij" on the terminal.
//
// Should see:   1234567890abcdefghij
// Actually see: 1234567890xxxxxxxxxx  (where xxx is something wrong)
//

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
}

void loop() {
  if (Serial.available()) {      // If anything comes in Serial (USB),
    Serial.read();    // discard
    Serial1.end();
    Serial1.begin(9600);
//    Serial1.clear();  // this workaround avoids the problem!
  }

  if (Serial1.available()) {     // If anything comes in Serial1 (pins 0 & 1)
    Serial.write(Serial1.read());   // read it and send it out Serial (USB)
  }
}
 
Status
Not open for further replies.
Back
Top