Serial Buses and Embedded Protocols
The source includes a buses and protocols chapter covering serial communication classes, RS-232C, RS-423A, RS-422A, RS-485, I2C, Modbus, and IEEE-488. These topics widen the view from one microcontroller board to communication between devices. A microcontroller may send bytes through a UART, share an I2C bus with memory and clock chips, or exchange Modbus frames with an industrial controller.
The common theme is that a bus is more than a wire. It defines electrical levels, direction rules, timing, addressing, framing, acknowledgements, and error checks. Software must follow the protocol's order exactly, while hardware must satisfy voltage, termination, pull-up, and distance requirements.
Definitions
Serial communication transmits data one bit at a time over one or a small number of signal lines. It contrasts with parallel transfer, where multiple bits move simultaneously.
Simplex communication allows data in one direction only. Half-duplex allows both directions but not at the same time. Full-duplex allows simultaneous transmit and receive.
Asynchronous serial communication sends frames without a shared clock. A UART frame commonly contains a start bit, data bits, optional parity, and one or more stop bits.
Synchronous serial communication uses a clock or defined clocking relationship so the receiver samples bits at known times.
RS-232C defines single-ended serial electrical signaling and connector conventions for short point-to-point communication. Logic levels are not ordinary TTL levels, so level conversion is normally required between an 8051 UART and RS-232.
RS-422 and RS-485 use differential signaling. RS-485 is widely used for multidrop half-duplex networks because several devices can share a twisted pair when drivers are controlled correctly.
I2C is a two-wire synchronous bus using serial data SDA and serial clock SCL, open-drain signaling, pull-up resistors, start and stop conditions, 7-bit or 10-bit addressing, and acknowledge bits.
Modbus is a master-slave or client-server style industrial protocol. Modbus RTU frames on serial links include address, function code, data, and CRC.
IEEE-488, also known as GPIB, is a parallel instrument-control bus historically used for test equipment.
Key results
The first key result is that electrical compatibility is not the same as byte compatibility. An 8051 UART can create an asynchronous byte stream, but RS-232 requires level shifting and inversion compared with TTL logic. RS-485 requires differential drivers and direction control.
The second key result is that asynchronous UART timing is open-loop inside each frame. The receiver detects the start bit, then samples based on its own baud-rate clock. If transmitter and receiver baud rates differ too much, sampling drifts and framing errors occur.
The third key result is that I2C devices never drive the bus high. They release the open-drain line, and pull-up resistors bring it high. This allows multiple devices to share the bus and makes acknowledgement possible, but it also limits speed through bus capacitance and pull-up resistance.
The fourth key result is that I2C transfer order is structured: start condition, address plus direction bit, acknowledge, data bytes with acknowledge bits, and stop condition. A repeated start can change direction without releasing the bus.
The fifth key result is that Modbus RTU relies on framing gaps and CRC. A receiver must know where one frame ends and another begins, and it must reject frames whose CRC does not match.
The sixth key result is that multidrop buses require an addressing or arbitration rule. I2C uses device addresses and arbitration on SDA; Modbus uses a slave address field; RS-485 only defines the electrical layer, so the higher-level protocol must prevent two nodes from transmitting at once.
The seventh key result is that bus length and speed are engineering tradeoffs. A short board-level I2C bus can run faster than a long cable with high capacitance. RS-485 can cover much longer distances, but it needs proper termination, biasing, and transceiver direction timing. RS-232 is simple for point-to-point links but is not a multidrop network. Choosing a bus begins with distance, noise, number of nodes, speed, and existing device support.
The eighth key result is that a frame format must define both content and boundaries. UART bytes alone do not say where a message starts. Protocols add start markers, lengths, time gaps, checksums, CRCs, addresses, or fixed byte counts. Modbus RTU uses timing gaps and CRC; I2C uses start/stop conditions and acknowledges; many custom UART protocols use sync bytes and length fields. Without boundaries, a receiver cannot recover cleanly after a lost byte.
The ninth key result is that acknowledgements mean different things at different layers. An I2C ACK means a device pulled SDA low for one bit time; it does not prove that a sensor measurement is complete or that an EEPROM write has finished internally. A Modbus response proves that a slave parsed a request and chose a response; it does not prove that an actuator physically reached a final position. Good software distinguishes link-level success from application-level success.
Visual
| Bus or standard | Signaling | Topology | Software concern | Hardware concern |
|---|---|---|---|---|
| TTL UART | Single-ended logic | Point-to-point | Baud, framing, flags | Logic-level compatibility |
| RS-232C | Single-ended, higher voltage | Point-to-point | UART framing | Level shifter and cable length |
| RS-485 | Differential | Multidrop | Direction and protocol | Termination and biasing |
| I2C | Open-drain two-wire | Multidrop | Address, ACK, bus state | Pull-ups and capacitance |
| Modbus RTU | Usually over RS-485 | Master-slave network | CRC and timing gaps | Transceiver direction |
| IEEE-488 | Parallel instrument bus | Multiple instruments | Talker/listener control | Cable and bus loading |
Worked example 1: Decoding an I2C address byte
Problem: An I2C master sends address byte D0H immediately after a start condition. Determine the 7-bit slave address and transfer direction.
Method:
-
In 7-bit I2C addressing, the transmitted address byte contains the 7-bit address in bits 7 through 1.
-
Bit 0 is the direction bit:
0for write and1for read. -
Convert
D0Hto binary:
D0H = 1101 0000
- Extract bits 7 through 1:
1101000
- Convert
1101000to hexadecimal. Pad on the left for grouping:
0110 1000 = 68H
- The least significant bit of
D0His0, so the direction is write.
Answer: the 7-bit slave address is 68H, and the operation is a write. This is the common address used by DS1307 RTC devices.
Check: The read address byte for the same 7-bit address would be D1H, because only the low direction bit changes.
Worked example 2: Identifying a Modbus RTU frame
Problem: A Modbus RTU request begins with bytes 01 03 00 10 00 02 followed by two CRC bytes. Interpret the fields before the CRC.
Method:
- The first byte is the slave address:
01H -> slave 1
- The second byte is the function code:
03H -> read holding registers
- The next two bytes are the starting register address:
00 10 -> 0010H
- The next two bytes are the quantity of registers:
00 02 -> 2 registers
- The final two bytes, not shown in detail here, are the CRC transmitted low byte first in Modbus RTU.
Answer: the frame asks slave 1 to read two holding registers starting at address 0010H.
Check: The request is not complete without a valid CRC. A receiver should compute the CRC over the address, function, and data fields and compare it with the received CRC bytes.
Code
/* Modbus RTU CRC-16, polynomial 0xA001.
Returns the CRC value whose low byte is transmitted first. */
unsigned int modbus_crc16(const unsigned char *buf, unsigned int len) {
unsigned int crc = 0xFFFF;
unsigned int i;
unsigned char bit;
for (i = 0; i < len; i++) {
crc ^= buf[i];
for (bit = 0; bit < 8; bit++) {
if (crc & 0x0001) {
crc = (crc >> 1) ^ 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
Common pitfalls
- Connecting an 8051 UART directly to RS-232 without a level converter.
- Forgetting RS-485 driver direction control in half-duplex systems, causing two nodes to drive the bus.
- Treating I2C lines as push-pull outputs. I2C requires open-drain behavior and pull-ups.
- Ignoring acknowledge bits. A missing ACK usually means wrong address, absent device, bus fault, or timing issue.
- Confusing 7-bit I2C addresses with the 8-bit address-plus-direction byte shown in some data sheets.
- Transmitting Modbus CRC high byte first. Modbus RTU sends CRC low byte first.
- Assuming a protocol such as Modbus defines the physical layer. Modbus can run over different links; RS-485 is common but separate.