I happened to be looking through the HardwareSerial.cpp file that contains the functions used for Serial communication for Arduino. While looking through the HardwareSerial::begin(baud, config) function, I noticed that the ucsra register has its U2X0 bit set. When I looked through the datasheet, it says that the U2X0 bit is set to start Double Speed Operation. From what I'm reading, this means that the baud rate is doubled.
I've been using this Arduino on this computer for a while now with no complaints for the baud rate being at an incorrect speed. What is Double Speed Operation? Why does it seem to be set in the code by default? I attached the code and section in the manual below.

void HardwareSerial::begin(unsigned long baud, byte config)
  // Try u2x mode first
  uint16_t baud_setting = (F_CPU / 4 / baud - 1) / 2;
  *_ucsra = 1 << U2X0;

  // hardcoded exception for 57600 for compatibility with the bootloader
  // shipped with the Duemilanove and previous boards and the firmware
  // on the 8U2 on the Uno and Mega 2560. Also, The baud_setting cannot
  // be > 4095, so switch back to non-u2x mode if the baud rate is too
  // low.
  if (((F_CPU == 16000000UL) && (baud == 57600)) || (baud_setting >4095))
    *_ucsra = 0;
    baud_setting = (F_CPU / 8 / baud - 1) / 2;

  // assign the baud_setting, a.k.a. ubrr (USART Baud Rate Register)
  *_ubrrh = baud_setting >> 8;
  *_ubrrl = baud_setting;

  _written = false;

  //set the data bits, parity, and stop bits
  #if defined(__AVR_ATmega8__)
    config |= 0x80; // select UCSRC register (shared with UBRRH)
  *_ucsrc = config;

  sbi(*_ucsrb, RXEN0);
  sbi(*_ucsrb, TXEN0);
  sbi(*_ucsrb, RXCIE0);
  cbi(*_ucsrb, UDRIE0);

enter image description here


When in double-speed mode, as noted in the manual, fewer samples are used. In Asynchronous serial communication, there is no clock signal, so the clock that keeps the two devices in sync is extrapolated from the data signal. Each end of the communication has it's own clock source (crystal oscillator, ceramic resonator, R-C oscillator, etc.), and you'll rarely find two that are calibrated identically.

The receiver samples the signal at a higher rate than the actual baud rate so that it can better determine where, relative to it's own clock, the data-signal edges go up or down and continually adjusts its offset to compensate for clock drift.

By operating in double-speed mode, the receiver has fewer samples to work with, and so if your transmitter has a clock source that is different enough than the receiver, or is not stable, or you have long or noisy wires or fluctuating temperatures (etc.) then you may experience less stable communication.

If your particular use-case works fine, then stick with it. But if you start to notice errors in communication, the first troubleshooting step would be to disable this mode, since the clock recover is less robust in this mode.


As explained in jose can u c’s answer, in double speed mode the UART has fewer samples for doing clock and data recovery. But this doesn't help answering the second question:

Why does it seem to be set in the code by default?

Double speed mode has also an advantage: it enables higher resolution in setting the baud rate. In normal mode, the bit duration is constrained to be a multiple of 16 CPU clock cycles, whereas in double speed mode it is only constrained to a multiple of 8 cycles.

As an example, let's say you want 57600 bps on a 16 MHz Arduino. Then,

F_CPU ÷ desired_baud_rate = 277.78 = 8 × 34.72 = 16 × 17.36

In single speed mode, this would be rounded to 16 × 17, and the rounding error would make the baud rate 2.1% too fast. In double speed mode, it is rounded to 8 × 35, and the baud rate is only 0.8% too slow. Thus you get better baud rate accuracy in double speed mode. Note that for some baud rates, like 9600 bps, single speed and double speed yield the exact same rate.

This is presumably the reason the Arduino core uses double speed mode, except for a documented compatibility exception and for extremely low baud rates (double speed cannot work below 488 bps).

It should be noted that this is not the only possible strategy. The avr-libc, for example, provides some helper macros for baud rate calculations. These macros give preference to single speed mode and revert to double speed only if the rounding error exceeds a specified tolerance, which defaults to 2%.

  • Thank you very much! That makes a lot more sense now. I had no idea how running Double Speed Operation all the time worked for the Arduino. – delta8 Jun 27 '18 at 14:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.