# How does TTL serial work?

I've been trying to find a good description of the TTL serial "standard" without much luck. I understand that serial transmit (TX) and receive (RX) lines idle high (at VCC) and that they drop to ground when a bit is transmitted. As such, they're inverted from the norm, where a "1" is high and "0" is low.

What I don't understand is who's responsible for holding the line high and how a zero is transmitted. Does the sender drive the line to high and low? Or does the receiver hold the line high with the sender pulling the line low (open collector)?

-
Read Joby's answer; apparently everything I thought I knew was inverted. :-) –  blalor Nov 17 '10 at 16:04
Real RS232 is the other way around 0 = 12v, 1 = -12v, that's why it's confusing –  Toby Jaffey Nov 17 '10 at 16:34
Point of terminology: "TTL serial" is a severely over-broad term, "(point-to-point) asynchronous serial (at TTL levels)" seems to be what you're asking about. (Though that's still probably lacking, but at least better) –  Nick T Nov 17 '10 at 18:42
@Nick The kind the OP means is whatever is fed into a MAX232, I'd call that "RS232 at TTL levels" –  Toby Jaffey Nov 17 '10 at 21:56
@Joby - If he uses only Tx and Rx, and you also remove its levels, then there's nothing RS232 anymore about it! Call it UART. –  stevenvh May 11 '12 at 10:40

With TTL serial, there are two unidirectional data lines. Each is driven by the sender, both high and low. A 0 bit is represented by 0V a 1 bit by VCC.

The receiver's pin should be set to an input.

So, for a microcontroller to send a byte (8-N-1 no flow control) it could do something like this:

#define BAUDRATE 9600
#define DELAY (SYS_CLK/BAUDRATE)

#define UART_BITBANG_OFF     UART_BITBANG_PORT |= _BV(UART_BITBANG_PIN)
#define UART_BITBANG_ON      UART_BITBANG_PORT &= ~ _BV(UART_BITBANG_PIN)

#define UART_BITBANG_BIT(bit) {if (bit) UART_BITBANG_ON; else UART_BITBANG_OFF; _delay_us(DELAY);}

void uart_bitbang_init(void)
{
UART_BITBANG_DDR &= ~ _BV(UART_BITBANG_PIN);        // TX output
}

void uart_bitbang_putc(uint8_t c)
{
UART_BITBANG_BIT(1)
UART_BITBANG_BIT((c & 0x1) == 0);
UART_BITBANG_BIT((c & 0x2) == 0);
UART_BITBANG_BIT((c & 0x4) == 0);
UART_BITBANG_BIT((c & 0x8) == 0);
UART_BITBANG_BIT((c & 0x10) == 0);
UART_BITBANG_BIT((c & 0x20) == 0);
UART_BITBANG_BIT((c & 0x40) == 0);
UART_BITBANG_BIT((c & 0x80) == 0);
UART_BITBANG_BIT(0);
}


(This code reads a bit backwards as it was originally meant for inverted TTL serial)

Of course, most MCUs have hardware UARTs which do all this for you.

Here's what you'd see on a scope:

http://www.pololu.com/docs/0J25/4.a

-
Thanks, Joby. So even though the line idles high, a 0 bit is still 0v. Does the receiver typically have an internal pull-up on the RX line, so that it doesn't float? –  blalor Nov 17 '10 at 16:06
@blalor the line won't float, the sender is driving it (assuming both ends are connected) –  Toby Jaffey Nov 17 '10 at 16:21
Arduino's NewSoftSerial enables the AVR's internal pull-up on the RX pin. I assume this is required if there isn't an attached sender. Thanks for the info, and the added Adafruit link. –  blalor Nov 17 '10 at 17:11
Being somewhat pedantic, but doesn't "TTL" just imply levels? You describe a point-to-point serial link, but could it just as well be a multi-master topology with open collector drivers and a pullup (like LIN but with TTL levels)? "TTL serial" seems like an incredibly broad term that's almost useless without some context. –  Nick T Nov 17 '10 at 18:36
It's just the standard serial port interface with the voltage converters removed. –  starblue Nov 17 '10 at 21:47