Communication module
A microcontroller on its own is good for very little: almost always it has to talk to a sensor, a display, another micro or a computer. All of that is solved with two or three wires and a peripheral that is configured in five lines.
01Why serial and not parallel
Sending a byte over eight wires at once seems faster, and it is over short distances. But as soon as you have to leave the circuit board, serial communication wins by a landslide.
| Parallel | Serial | |
|---|---|---|
| Wires | 8, 16 or more, plus ground | 1 to 4 |
| Connector and cable cost | High | Low |
| Micro pins | A whole port | Two or three |
| Distance | Centimeters | Meters, or kilometers with RS485 |
| Its own problem | Skew: the bits don’t all arrive together | Both ends have to agree on the speed |
- Synchronous: there is a clock wire. The sender says, besides the data, when to read it. That is SPI, that is I²C, and that is the USART in synchronous mode. Fast and free of speed errors, at the cost of one more wire.
- Asynchronous: there is no clock. Both ends have to be configured at the same speed beforehand, and the frame carries start and end marks to synchronize on every byte. It is the good old serial port.
02The asynchronous USART: the frame
The idle line is high. To send a byte, the line is pulled to zero for one bit time —the start bit—, and that tells the receiver to start counting. Then come the eight data bits, least significant first, optionally a parity bit, and at least one stop bit at high.
| Item | What it is |
|---|---|
| Baud rate | Bits per second on the line. The classic values: 9600, 19200, 38400, 57600, 115200. |
| 8N1 | The usual configuration: 8 data bits, No parity, 1 stop bit. Both ends have to match on all three. |
| Parity | A bit that makes the number of ones even or odd. It detects a one-bit error, doesn’t correct it, and misses double errors. Today it is hardly used: a checksum over the whole message is preferred. |
| Stop bits | One or two. They guarantee that the line returns to idle so the next start can be detected. |
In 8N1, each byte actually takes up 10 bits: start + 8 data + stop.
- At 9600 baud: 1/9600 = 104 µs per bit → 1.04 ms per byte → about 960 bytes per second.
- At 115,200: 8.68 µs per bit → 86.8 µs per byte → about 11,500 bytes per second.
- Sending a 20 × 4 character screen (80 bytes) at 9600 takes 83 ms: it is noticeable to the naked eye. That calculation often decides the speed of the project.
03Setting the baud rate: the calculation you need to know
The module generates its bit time by dividing the system clock. An integer is loaded into a register (SPBRG on PIC, UBRR on AVR) and the actual speed comes out of that, which is almost never exactly the one requested.
A case that works. 16 MHz crystal, 9600 baud:
- UBRR = 16,000,000 / (16 × 9600) − 1 = 104.17 − 1 = 103.17 → load 103
- Actual speed = 16,000,000 / (16 × 104) = 9615 baud
- Error = (9615 − 9600)/9600 = +0.16%. Perfect.
A case that doesn’t work. 8 MHz crystal, 115,200 baud:
- UBRR = 8,000,000 / (16 × 115,200) − 1 = 4.34 − 1 = 3.34 → load 3
- Actual speed = 8,000,000 / (16 × 4) = 125,000 baud
- Error = +8.5%. Reception fails: you get wrong characters or garbage.
The rule of thumb: the total error between the two ends must not exceed 2%. That is why oddly specific crystals exist —7.3728 MHz, 11.0592 MHz, 14.7456 MHz—: they are exact multiples of the standard baud rates. With 7.3728 MHz and 9600 baud, UBRR = 47 and the error is zero.
Internal RC oscillators have a tolerance of 1 to 10% depending on the chip and the temperature, uncalibrated. Added to the division error, the error budget is used up. For reliable serial communication: an external crystal, or self-calibration of the internal oscillator against a reference. It is exactly what was covered in oscillators regarding stability.
- TXIF / UDRE: the transmitter is free. You have to wait for it before loading the next byte.
- RCIF / RXC: a byte has arrived. It is read from the receive register and the flag clears itself.
- OERR / DOR — overrun: a new byte arrived before the previous one was read. It is the typical failure of a program that does something else while receiving. On PIC you have to clear it by hand by turning the receiver off and on, or the module stays mute.
- FERR / FE — framing error: the stop bit didn’t appear where it should have. It is almost always a wrong baud rate or noise.
// Minimal transmit and receive, no libraries (AVR)
void serie_init(uint16_t ubrr) {
UBRR0H = (uint8_t)(ubrr >> 8);
UBRR0L = (uint8_t) ubrr;
UCSR0B = (1 << TXEN0) | (1 << RXEN0); // enable Tx and Rx
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 data bits
}
void serie_enviar(uint8_t dato) {
while (!(UCSR0A & (1 << UDRE0))); // wait for the buffer to become free
UDR0 = dato;
}
uint8_t serie_recibir(void) {
while (!(UCSR0A & (1 << RXC0))); // wait for something to arrive
return UDR0;
}
The two while loops are blocking: the program does nothing else
while it waits. As soon as the project has to attend to something else, this is replaced by
interrupts and a circular buffer, which is a Year 7 topic.
04SPI: the fast synchronous bus
Four wires, one master and as many slaves as needed. The master generates the clock and there is always an exchange: for every bit that goes out on MOSI, one comes in on MISO.
- SCK — clock, generated by the master.
- MOSI — master to slave.
- MISO — slave to master.
- SS̄ / CS̄ — select, active low. One per slave: that is the cost of adding devices.
Two bits are combined: CPOL (whether the clock idles high or low) and CPHA (whether the data is sampled on the first edge or the second). That gives modes 0 to 3.
Each chip specifies its own in the datasheet. If it doesn’t match, you read garbage or the data appears shifted by one bit: it is the first thing to check when an SPI device “doesn’t respond.”
Serial Flash and EEPROM memories, SD cards, graphic and OLED displays, external multi-bit A/D converters, fast sensors, radio modules (nRF24, LoRa), 74HC595 shift registers for expanding outputs. When you need speed —tens of megahertz— SPI is the answer.
05I²C: two wires for everyone
Two lines —SDA (data) and SCL (clock)— shared by all devices, each with its own address. The outputs are open-collector: any device can pull the line to zero, and it is the pull-up resistors that bring it back to one.
| Detail | Value | Why it matters |
|---|---|---|
| Pull-ups | 4.7 kΩ typical (1.5 to 10 k) | Without them the bus doesn’t work. They go once on the whole bus, not one per device. |
| Speed | 100 kHz standard · 400 kHz fast · 1 MHz | Much slower than SPI, and enough for sensors. |
| Addresses | 7 bits → 112 usable | Two devices with the same address collide. Many modules come with jumpers to change it. |
| ACK | One bit per byte | The receiver acknowledges. If nobody answers, the master knows the address doesn’t exist: it is the basis of the “I²C scanner.” |
| Bus capacitance | 400 pF maximum | Limits the length to a few tens of centimeters. For more distance there are repeaters, or you change buses. |
A twenty-line program that goes through all 112 addresses and notes which ones respond with ACK. Before struggling with a sensor that “doesn’t work,” the scanner tells you in two seconds whether the device is alive, whether its address is the one the manual says, and whether the wiring is good. If nothing shows up, 90% of the time the pull-up resistors are missing or SDA and SCL are swapped.
| UART | SPI | I²C | |
|---|---|---|---|
| Wires | 2 (+ ground) | 3 + 1 per slave | 2 (+ ground) |
| Clock | No | Yes | Yes |
| Typical speed | 9.6 to 115.2 kbps | 1 to 50 Mbps | 100 to 400 kbps |
| How many devices | 2 (or a network with RS485) | Many, with one select line each | Up to 112, no extra wires |
| Acknowledges reception | No | No | Yes (ACK) |
| Used for | PC, GPS, modules, debugging | Displays, memories, SD, radio | Sensors, RTC, EEPROM, expanders |
06Electrical levels: what you can’t see in the program
A 3.3 V micro connected to a 5 V output receives a voltage above its maximum and gets damaged, sometimes slowly. The usual solutions: a resistive divider if the signal is slow and one-way, a MOSFET level shifter for I²C (which is bidirectional), or a translator IC. Always check the operating voltage of each module before wiring.
The micro’s serial port works with 0 and 5 V (or 3.3). A PC RS232 port uses inverted ±12 V. Between the two goes a MAX232 or a USB-serial cable, never a direct connection: the micro’s pin gets destroyed.
Two devices communicating serially need to share the ground. It is the most frequent oversight when each one has its own power supply, and it produces intermittent communication that looks like a software problem. If the grounds can’t be joined, you have to isolate with optocouplers or move to RS485.
07In the lab
Configure the USART at 9600 8N1 and send a text once per second to the computer with a USB-serial adapter. Verify on the oscilloscope that the bit time is 104 µs and read the frame by eye: identify the start bit, the eight bits —least significant first— and the stop bit. Compare the byte read on screen with the character sent.
With the transmitter at 9600 and the receiver at 19,200, observe what arrives. Then try small differences: 9600 against 9800 (2%) and against 10,400 (8%). Note at what error it starts to fail. It is the experimental check of the 2% rule.
Drive eight LEDs with a shift register using hardware SPI. With a two-channel oscilloscope measure SCK and MOSI, and verify on which edge the data changes. Then change the micro’s SPI mode and check that it stops working: it is the best way to understand CPOL and CPHA.
With a sensor or an RTC module on the bus, run the scanner and write down the address found. Then remove the pull-up resistors and run it again: nothing shows up. See on the oscilloscope the difference between a line with a pull-up and a floating one.
Connect TX of one to RX of the other and vice versa, with the grounds joined, and set up a minimal protocol: one command byte and one response byte. Then disconnect the common ground and observe the result. Finally, add a checksum and cause errors by touching the wire.
08Common mistakes
| Symptom | Usual cause |
|---|---|
| Strange but consistent characters arrive | Different baud rate at the two ends, or a division error greater than 2%. |
| The first byte arrives and then nothing | Overrun: the receive register wasn’t read in time. On PIC you have to clear OERR by hand. |
| Works with a short cable and fails with a long one | TTL levels over too great a distance. Move to RS485 or lower the speed. |
| Intermittent communication between two devices | The common ground is missing, or there is a potential difference between grounds. |
| The SPI device doesn’t respond | Wrong mode (CPOL/CPHA), SS̄ that doesn’t go low, or MISO and MOSI swapped. |
| The I²C bus is always at zero | Pull-ups are missing, or a device got stuck holding SDA. It is freed by pulsing the clock by hand nine times. |
| Two I²C devices and only one shows up | They share an address. Change it with the module’s jumpers or use two buses. |
| A 3.3 V module stopped working | It was connected to 5 V signals. A level translator is needed. |
| Bytes are lost when the program does other things | Polled reception. Switch to interrupt-driven with a circular buffer. |
09Self-assessment
How many bits does a byte really take in 8N1, and how long does it take at 19,200 baud?
10 bits: start, eight data and stop. At 19,200, each bit lasts 52.1 µs → 521 µs per byte, about 1920 bytes per second.
16 MHz crystal and 19,200 baud: what value goes in UBRR and what error is left?
UBRR = 16,000,000/(16 × 19,200) − 1 = 52.08 − 1 = 51.08 → load 51. Actual speed = 16,000,000/(16 × 52) = 19,231 baud: error +0.16%.
Why do 7.3728 MHz crystals exist?
Because they are exact multiples of the standard baud rates: 7,372,800/(16 × 9600) = exactly 48, so the baud rate error is zero. With “round” crystals there is always a remainder.
What is an overrun and how is it avoided?
A new byte arrived before the program read the previous one, and it was lost. It is avoided by handling reception by interrupt and storing the data in a circular buffer, instead of waiting by polling.
In SPI, what happens on MISO while the master sends on MOSI?
The exchange is simultaneous: for every clock pulse one bit goes out on MOSI and one comes in on MISO. After eight pulses, the two shift registers have swapped their contents.
What are CPOL and CPHA for?
They define the SPI mode: at what level the clock idles (CPOL) and on which of the two edges the data is sampled (CPHA). If the master’s mode doesn’t match the slave’s, the data comes out shifted or simply meaningless.
Why does I²C need pull-up resistors?
Because the outputs are open-collector: they can only pull the line to zero. The logic one is produced by the resistor. Without pull-ups, the lines float and the bus doesn’t work.
How many devices fit on an I²C bus and what limits them?
Up to 112 because of the 7-bit addresses, but in practice the total bus capacitance rules: 400 pF at most, which limits the number of modules and the wiring length to a few tens of centimeters.
When is SPI better and when is I²C?
SPI when speed matters —displays, memories, SD cards— and pins are to spare. I²C when there are many slow devices and wires need to be saved: sensors, real-time clock, port expanders.
Two devices connected by TX/RX can’t understand each other even though the baud rate matches. What should you check first?
The common ground and the crossing of the lines: TX of one must go to RX of the other. Then, the levels: if one is TTL and the other RS232, an adapter is needed.