Skip to content
Home » Embedded Systems » Communication Protocols » Interfacing Sensors with Microcontrollers: ADC, I2C, SPI, and 1-Wire

Interfacing Sensors with Microcontrollers: ADC, I2C, SPI, and 1-Wire

Sensors for Embedded Systems
Part 18 of 18View Full Path →

KEY TAKEAWAYS

  • ADC converts analog sensor voltages to digital values — configure reference voltage, resolution, and sample rate.
  • I2C uses 2 wires for up to 128 devices; SPI uses 4+ wires but is faster and full-duplex.
  • 1-Wire (DS18B20) uses a single data pin for multiple sensors with unique addresses.
  • Always add bypass capacitors near sensor power pins and keep analog traces short and away from digital signals.

Part of the Complete Guide to Sensors for Embedded Systems series.

Getting data from a sensor into your microcontroller is a fundamental embedded skill. Different sensors use different interfaces — analog voltage, I2C, SPI, 1-Wire, or custom protocols. This guide covers each interface with practical wiring and code guidance.

Analog Interface (ADC)

Analog sensors like LM35, thermistors, and LDRs output a voltage that varies with the measured quantity. The microcontroller’s ADC converts this voltage to a digital value.

Configure the ADC with the correct reference voltage. Most MCUs use VCC (3.3V or 5V) as the default reference. Some have internal precision references (1.1V on ATmega, 1.25V on MSP430). The reference voltage determines the measurement range and resolution.

Resolution = Vref / 2^n, where n is the ADC bit width. For a 10-bit ADC with 3.3V reference: resolution = 3.3V / 1024 = 3.22mV per step. To convert an LM35 reading (10mV/°C): temperature = (adc_value × 3.3 / 1024) / 0.01 = adc_value × 0.322.

Best practices: add a 100nF capacitor between the analog input and ground to filter high-frequency noise. Use the ADC averaging feature if available, or average multiple samples in software. Allow the sample-and-hold capacitor to charge by not switching channels too rapidly.

I2C (Inter-Integrated Circuit)

I2C is a 2-wire bus using SDA (data) and SCL (clock), with 4.7kΩ pull-up resistors on each line. Each device has a unique 7-bit address. The master (your MCU) initiates communication; slaves (sensors) respond.

To read from an I2C sensor: send a START condition, transmit the slave address with write bit, send the register address you want to read, send a REPEATED START, transmit the slave address with read bit, read the data bytes, send STOP.

Most sensors have readable data registers and writable configuration registers. For example, BME280: write 0xF4 to set measurement mode, then read 0xF7-0xFE for raw temperature, pressure, and humidity data.

Common issues: wrong address (use an I2C scanner to detect devices), missing pull-ups (signals don’t reach logic high), bus contention (two devices with the same address), and clock stretching (some sensors hold SCL low during conversion, causing timeouts on some MCUs).

I2C speed: standard mode (100kHz), fast mode (400kHz), and fast-mode plus (1MHz). Most sensors support 400kHz. Use standard mode for longer wires or noisy environments.

SPI (Serial Peripheral Interface)

SPI is a 4-wire bus: MOSI (master out), MISO (master in), SCK (clock), and CS (chip select — one per device). Full-duplex (send and receive simultaneously) and much faster than I2C (up to 10MHz+).

SPI has no addressing — each device has its own CS pin. To communicate with a specific sensor, pull its CS low, clock data in/out, then release CS. This means SPI needs more GPIO pins (one CS per device) but avoids address conflicts.

SPI communication: set the correct mode (clock polarity and phase — modes 0-3), pull CS low, send the register address (MSB often indicates read/write), clock out data bytes while reading response bytes, release CS.

Sensors using SPI: BMP280 (also supports I2C), ADXL345, MAX31855 (thermocouple), ADS1115 (precision ADC), and many others. SPI is preferred when speed matters (high sample rates) or when I2C bus is already crowded.

1-Wire Interface

The 1-Wire protocol, developed by Dallas Semiconductor (now Maxim), uses a single data wire plus ground. The DS18B20 temperature sensor is the most popular 1-Wire device.

Each 1-Wire device has a unique 64-bit ROM code burned in at the factory. Multiple DS18B20 sensors can share a single GPIO pin — you address them individually using their ROM codes. This makes it trivial to add or remove sensors without changing wiring.

The protocol is timing-critical: the master generates precise microsecond-level pulses. A “1” bit is a short low pulse (1-15µs) followed by high. A “0” bit is a long low pulse (60-120µs). Libraries handle these timing details, but interrupts must be disabled during bit I/O to maintain timing accuracy.

DS18B20 read sequence: send RESET pulse, send SKIP ROM (address all devices) or MATCH ROM (specific device), send CONVERT T (starts temperature conversion), wait 750ms (at 12-bit resolution), send RESET + SKIP ROM + READ SCRATCHPAD, read 9 bytes including temperature and CRC.

Parasitic power mode: DS18B20 can be powered entirely through the data line, requiring only 2 wires (data + ground). A strong pull-up (MOSFET to VCC) is needed during temperature conversion. Useful for remote sensors with minimal wiring.

📖 Related: SPI Protocol Deep Dive: Clock Polarity, Phase, and Multi-Slave DesignLM35 Temperature Sensor: Working, Circuit, and Arduino Code

Going further: For a deeper dive on ADC specifically — resolution, sample rate, reference voltage, and read patterns (polling, interrupt, DMA) — see our ADC in Microcontrollers guide.

Going further: Once you have the raw readings, see Filtering Noisy ADC Readings for the software cleanup techniques: moving average, median, EMA, oversampling, and hysteresis.

Leave a Reply

Your email address will not be published. Required fields are marked *