I know you’ve heard of both synchronous and asynchronous communications. But do you really know the differences between the two?
Serial communication was used long before computers existed. A predecessor is the telegraph system using Morse Code, one of the first digital modes of communication. Another predecessor is the teletype, which set standards that are still used today in your Arduino or Raspberry Pi.
All you need is two wires for serial communications, which makes it simple and relatively robust. One wire is ground and the other the signal. By interrupting the power with predefined patterns, information can be transferred over both short and long distances. The challenge is receiving the patterns correctly and quickly enough to be useful.
I was a bit surprised to find out the serial port on the Arduino Uno’s ATmega328P microcontroller is a Universal Synchronous Asynchronous Transmitter Receiver (USART). I’d assumed it was only a UART (same name, just leave out synchronous) probably because my first work with serial communications was with the venerable Intel 8251 “Programmable Communication Interface”, a UART, and I didn’t expect the microcontroller to be more advanced. Silly me. Later I worked with the Zilog 8530 Serial Controller Chip, a USART, the term I’ll use for both device types.
All these devices function in the same way. You send a byte by loading it into a register and it is shifted out one bit at a time on the transmit (TX) line as pulses. The receiver accepts the pulses on a receive (RX) input and shifts them into a register, which is then read by the system. The transmitter’s job is pretty easy it just shifts out the bits at a known clock rate. The receiver’s task is more complex because it needs to know when to sample the incoming signal. How it does this is the difference between asynchronous and synchronous communications.
Synchronous communication makes the receiver’s job easier by adding a third clock line to the ground and signal lines. This is the clock the transmitter uses to shift out the bits. The receiver uses the clock to determine when to sample the value of the received bit.
There are other devices in addition to the USART on the Arduino, or other microprocessor chips, that use synchronous communications. Both I2C (Inter-Integrated Circuit) and SPI (Standard Peripheral Interface) are synchronous. I2C uses two lines for Serial Data Line (SDA) and Serial Clock Line (SCL). Each device on a bus is assigned an address and responds when the master sends that address over the SDA. Devices respond back on the SDA making this a half-duplex system.
SPI requires at least four lines: Serial Clock (SCK), Master Out / Slave In (MOSI), Master In / Slave Out (MISO), and Ground. This bus can also use a Slave Select (SS) line for each device. This adds complexity but allows SCK/MOSI/MISO to be attached to multiple slave devices — each will only “listen” when its SS line is active. The master activates the SS, transmits, and waits for the response.
In both I2C and SPI the master always generates the clock. It synchronizes the slave devices with the master. This is synchronous communication.
One issue with a synchronous system is the receiver expects to be receiving data if the clock is active. If the transmitting system needs to pause during a message, it needs to send idle characters, which the receiver discards, to hold the line active.
Asynchronous communication does not provide the clock signal. The transmitter’s job is the same, to shift the bits onto the wire at the agreed clock rate, but it needs to do more. With no clock, the receiver needs to know when to begin sampling for incoming bits. The transmitter helps by sending synchronization bits: a start bit and then one, one and a half, or two stop bits. There is also an optional parity bit to allow for error checking. For more on this, check out the serial troubleshooting techniques [Elliot Williams] wrote about earlier this week.
Since the transmit and receive clock rates are running independently they are not going to be in phase. Due to this the receiver might not sample the start bit until it is almost completed, throwing off the sampling for the remainder of the bits in the character. To avoid this the receive clock runs faster, sometimes 16 times faster, than the transmit clock to allow it to more accurately detect the falling edge of the start bit.
In a perfect world a USART’s receiver could determine the time for the middle of an input bit, read the signal level, and that would be the received bit. In the real world, it’s not so simple. The transmitter sends a nice square wave but as the signal propagates it decays. The nice sharp rise time becomes a slope, as does the falling edge. There also may be noise on the signal line lowering or raising the signal level. Here again, the receive clock is faster to take multiple readings and average them to determine the input bit.
Heritage: Break and Signal Levels
The telegraph and teletype systems influence serial communications even today. Today we consider a digital signal line’s default, or idle, condition if there is no voltage on it, implying its value is 0. The telegraph system considers an idle line to be high. With the signal line held high operators could detect physical breaks in the line because the signal dropped to zero. To send a message a telegraph operator moved a slide on the key to “break” the line. The slider was put back when the message was completed.
Teletype (TTY) systems continued both practices. A TTY keyboard has a break key that literally interrupts the high signal on the line and any messages being sent. The break key on your computer keypad is a legacy from broken lines on the telegraph systems. Since TTYs were used with early computers the break key was adopted as a means of interrupting runaway processes. A USART can be configured to set an error flag and generate an interrupt if it detects a break, i.e. a low signal for a character period.
The high idle signal level is the other legacy practice. An idle serial line is held high in contrast to most digital signals, which are held low. In legacy terms, a high signal line is a mark signal and a low signal line is a space. A 1 bit is sent as a mark and a 0 bit is sent as a space. This explains why the asynchronous start bit is a space to indicate the end of an idle line and why the stop bits are marks, returning the line to the high idle state.
A final legacy is ability to specify multiple stop bits. TTY mechanisms were not always fast enough to capture a character, print it, and prepare for the next character in the time provided by a single stop bit. The multiple stop bits provided a built in delay time for these mechanical devices to recover.
Errors and Flags
Errors always occur during serial communications due to noise, bad connections, and the whims of Murphy. The USART reports errors and its operating status in an appropriately named status register. It can also be configured to generate interrupts for errors and most status indicators.
One error is the framing error, often caused by transmit and receive clocks running at different speeds. Severe noise disrupting the start or stop bits can also cause this since it is triggered by a character not ending when expected. With the clocks being on two different systems they simply cannot be running at the same speed. If the transmit clock is sufficiently slower than the receive clock the stop bit will occur after that receiver expects. A faster transmit clock means the stop bit is there before the receiver expects which means the receiver sees the next start bit before it is ready. Clocks must be within 3.3%, based on Determining Clock Accuracy Requirements for UART Communications from Maxim Integrated.
Another error is the overrun. This occurs when the USART receives a new character before its system reads the previous character. To avoid this a modern USART will provide a character buffer to clear the way for the next character to be received by the input register. This double buffering provides time for the system to read the buffered character. Transmitters do the same, holding one in the buffer while another is transmitted. Some USARTs provide larger buffers. The 16550 USART available from multiple vendors and used in many PCs, provides a 16 byte buffer for both transmit and receive.
A few more errors and indicators are possible. There is the parity check error when the received character’s parity doesn’t match that calculated by the USART. The transmitter underrun status indicates the buffer and output register are empty. Also, both the transmitter and receiver provide a ready status when their buffers can accept or provide, respectively, a character.
[Elliot’s] article What Could Go Wrong: Asynchronous Serial Edition digs into the details on connecting two Arduino’s using asynchronous communications. Who will be the first with a project on Hackaday.io that connects a couple of Arduinos using synchronous communications?