Serial Communication

Serial communication sends data one bit at a time over a single wire — the most efficient way to connect computers to terminals, printers, modems, and other computers over medium distances.

Why This Matters

Parallel communication (sending 8 bits simultaneously over 8 wires) is fast but expensive and error-prone over long distances. Serial communication sacrifices bandwidth for simplicity: only two wires (transmit, receive) carry all data. This makes serial interfaces practical for any interconnection scenario from a few centimeters to kilometers.

Serial communication is the foundation of nearly all inter-device communication: RS-232 connected early computers to terminals and modems; UART interfaces still connect embedded systems to terminals; SPI and I²C connect microcontrollers to sensors and peripherals. Understanding serial protocols allows building communicating systems without complex parallel bus infrastructure.

For a hand-built computer, a UART serial interface is the most practical way to add keyboard input and display output simultaneously, using an existing terminal or a modern PC as the I/O device.

Asynchronous Serial: UART Protocol

UART (Universal Asynchronous Receiver/Transmitter) is the most common simple serial protocol. No shared clock signal is needed — sender and receiver operate from independent clocks synchronized by start and stop bits.

UART frame format for transmitting one byte:

  1. Idle state: line stays high (marking)
  2. Start bit: line goes low for one bit period
  3. Data bits: 8 data bits (LSB first), each lasting one bit period
  4. Parity bit (optional): for error detection
  5. Stop bit(s): line high for 1 or 2 bit periods

The bit period = 1 / baud_rate. Common baud rates: 9600, 19200, 38400, 115200 bits per second.

At 9600 baud: bit period = 1/9600 ≈ 104 µs. One 8N1 (8 data, no parity, 1 stop) byte transmission takes 10 bit periods = 1.04 ms → maximum ~960 bytes/second.

At 115200 baud: bit period ≈ 8.7 µs → ~11,520 bytes/second (about 11 KB/s).

Receiver synchronization: on detecting the start bit (falling edge), the receiver waits 1.5 bit periods before sampling the first data bit (to sample near the center of each bit). Then samples at 1-bit intervals for all subsequent bits. Both sides must agree on baud rate in advance.

Hardware Implementation

Using a UART IC (16550 or 8250): the most practical approach. The CPU writes data to the IC’s transmit holding register; the IC handles serialization, timing, and signaling autonomously. The CPU polls a status flag or receives an interrupt when transmission is complete or a byte has been received.

Interface connections:

  • Data bus: 8-bit bidirectional
  • Address bus: 3-bit (selects which register: data, interrupt enable, line control, etc.)
  • CS (chip select), RD, WR: bus control
  • TX: serial output (connect to remote device’s RX)
  • RX: serial input (connect to remote device’s TX)
  • GND: common ground

The 16550 contains a 16-byte FIFO, reducing interrupt overhead. The 8250 (original PC UART) has no FIFO. Both are straightforward to interface to a homemade CPU.

Bit-banging UART (software implementation): the CPU directly manipulates an I/O bit at the correct times to generate the UART waveform. For transmitting:

TX_BYTE:
    ; R0 contains byte to send
    ; assume 9600 baud, 1 MHz CPU clock
    ; bit period = 104 µs = 104 cycles at 1 MHz
 
    SEND_BIT 0   ; start bit: drive TX low
    DELAY 104    ; wait one bit period
 
    ; send 8 data bits LSB first
    REPEAT 8 times:
        shift R0 right through carry
        if carry=1: drive TX high
        if carry=0: drive TX low
        DELAY 104
 
    DRIVE TX high  ; stop bit
    DELAY 208      ; wait 2 stop bits for margin
    RET

Bit-banging works but consumes the CPU entirely during transmission (can’t do anything else while counting bit periods). Use a hardware UART for multi-tasking systems.

RS-232 Voltage Levels

Logic TTL/CMOS levels (0/5V) are not the same as RS-232 voltage levels. RS-232 uses:

  • Logic 1 (marking): −3V to −15V
  • Logic 0 (spacing): +3V to +15V

Note the inversion compared to TTL logic. Connecting TTL directly to RS-232 inputs risks damage and produces incorrect logic levels.

Level conversion IC: MAX232 (or equivalent). Powered from a single 5V supply, it generates ±10V internally using charge pump capacitors. Converts TTL TX to RS-232 TX, and RS-232 RX to TTL RX. Four external 1µF capacitors required.

Connection: UART IC TX → MAX232 T1IN → MAX232 T1OUT → RS-232 cable TX pin. RS-232 cable RX pin → MAX232 R1IN → MAX232 R1OUT → UART IC RX. Three-wire connection: TX, RX, GND.

For terminal connection within a room (< 5 meters), omit RS-232 and connect TTL levels directly with appropriate pull-up resistors. Many modern terminal emulators on laptops accept TTL serial via a USB-TTL adapter, eliminating the need for RS-232 conversion entirely.

Practical Terminal Setup

A hand-built computer with a UART port communicates with a terminal emulator (PuTTY, minicom, screen) running on any modern computer. Settings: baud rate, 8N1 (8 data bits, no parity, 1 stop bit), no hardware flow control.

Initial test: connect TX to RX (loopback). Any byte transmitted should be immediately received back. If the received byte matches the transmitted byte, the UART and clock are working correctly.

Once bidirectional communication is confirmed, connect to a real terminal or computer and send ASCII text. The first “Hello” appearing on the terminal screen confirms that the hand-built computer can communicate with the outside world — a milestone moment in any computer construction project.