Logic Levels & Electrical Signals - How Bits Become Voltage
Before any protocol can work, bits must become voltages. Learn about 3.3V vs 5V logic, signal integrity, pull-up resistors, and level shifting.
Logic Levels & Electrical Signals. How Bits Become Voltage
Before UART, SPI, I2C, or any other protocol matters, there's something more fundamental: a wire is either at a high voltage or a low voltage. That's it. Everything else is built on top of that physical reality.
This sounds obvious until you connect a 5V Arduino to a 3.3V ESP32 for the first time. If you're lucky, nothing happens. If you're less lucky, you've just killed an input pin. sometimes the whole chip. So let's get this layer right before moving up.
What a Logic Level Actually Is
A logic level isn't a single voltage. it's a range. A system reads anything in the HIGH range as a 1, anything in the LOW range as a 0, and anything in between as... undefined. That middle zone exists on purpose; it's the noise margin.
| System | Logic LOW | Logic HIGH | Supply |
|---|---|---|---|
| 5V TTL | 0. 0.8 V | 2.0. 5.0 V | 5 V |
| 3.3V CMOS | 0. 0.8 V | 2.0. 3.3 V | 3.3 V |
| 1.8V CMOS | 0. 0.35 V | 1.17. 1.8 V | 1.8 V |
5.0 V β€ βββββββββββββββ HIGH valid zone
2.0 V β€ - - - - - - - - HIGH threshold
β β don't go here
0.8 V β€ - - - - - - - - LOW threshold
0.0 V β€ βββββββββββββββ LOW valid zone
Notice that 3.3V CMOS outputs can drive 5V TTL inputs just fine. 3.3V sits well inside the HIGH valid zone for 5V TTL (which only requires 2.0V minimum). The reverse doesn't work: a 5V output driving a 3.3V input sends it straight past its maximum rated voltage.
Pull-up resistors. and why the value matters more than you'd expect
Some bus lines are open-drain: the chip can only pull the line LOW, never actively drive it HIGH. I2C is the classic example. A pull-up resistor sits between the supply and the line, providing the default HIGH state passively.
Rendering diagram...
The resistor value is not arbitrary. Pick it too small. say 100Ξ©. and you're burning 33mA every time the line is pulled low. Pick it too large. 100kΞ©. and the rise time becomes so sluggish that edges blur into each other at any real speed. For I2C at 100kHz, 4.7kΞ© is the standard. At 400kHz, come down to 2.2kΞ©. At 1MHz, 1kΞ© or lower.
I've seen I2C buses that "almost work" at 100kHz with a 10kΞ© pull-up. it looks fine on the logic analyser until the PCB gets warm and the stray capacitance increases slightly. Then it stops working. The correct pull-up fixes it permanently.
Signal integrity. what happens at speed
Even a 5cm PCB trace has resistance, capacitance, and inductance. At low speeds (UART at 9600 baud) none of this matters. At SPI running at 40MHz, it can mean the difference between a working board and one that fails intermittently.
Ideal edge Real edge on a long trace
1 ββ 1 ββ~~_
β β~~~
0 ββ 0 ββββββ
β ringing. that dip can look like a spurious LOW
Short lines, matched impedance (50Ξ© is typical for PCB traces), and a small series resistor (33β100Ξ©) near the driver output all help. The series resistor damps the ringing without affecting the steady-state voltage.
Mixing 3.3V and 5V devices
The safest approach is to never do it. In practice you usually have no choice. There are three real options:
- Resistor divider: works fine for a unidirectional signal where you're stepping 5V down to 3.3V. Fast, cheap, zero components. But it's passive, so you can't use it on bidirectional lines.
- MOSFET-based shifter (BSS138 circuit). handles bidirectional lines like I2C. Works well up to a few hundred kHz.
- Dedicated level-shift IC (TXS0102, TXB0108). faster and more reliable for SPI and anything above 1MHz. Costs a bit more.
Rendering diagram...
Don't skip this step. The "it works on my desk" phase of a direct 5Vβ3.3V connection sometimes lasts for months before it starts causing bit errors or silently damages the input ESD structure. By then you've forgotten you ever did it.
Getting the physical layer right isn't glamorous, but every debugging session that starts with "SPI randomly drops bytes" or "I2C freezes after a few minutes" is really a symptom of something broken at this level.