Lesson 100: Using shiftIn()
Learn how shiftIn() reads serial bits from external chips like shift registers, including bit order and practical wiring flow.
Progress indicator
Lesson 100 of 100
Learning Objectives
- Understand what shiftIn() does and how serial bit reading works.
- Learn shiftIn() syntax with data pin, clock pin, and bit order.
- Understand MSBFIRST vs LSBFIRST and when each is required.
- Use shiftIn() with shift registers to read multiple digital inputs efficiently.
- Decode returned bytes into individual pin/button states using bit masks.
- Avoid common wiring and timing mistakes in serial bit capture.
Concept Explanation
What is shiftIn()
shiftIn() reads a byte (8 bits) of serial data from a device one bit at a time.
It is commonly used with shift registers and other serial-output digital ICs where many input states are sent through one data line.
shiftIn() Syntax
shiftIn(dataPin, clockPin, bitOrder);
dataPin: pin to read incoming bit values.clockPin: pin used to clock each bit read.bitOrder:MSBFIRSTorLSBFIRST.
Example: byte value = shiftIn(19, 18, MSBFIRST); reads 8 serial bits and stores them in one byte.
How shiftIn() Works
- Reads one bit from data pin on each clock cycle.
- Repeats this process 8 times to form one byte.
- Places each bit in final byte based on bit order setting.
- Returns the completed byte value to your code.
Think of it as reading a line of 8 boxes one-by-one and packing them into a single number.
Serial Data Reading Concept
Serial reading means receiving bits one-by-one over time instead of using many parallel pins.
This saves GPIO pins and makes it practical to read larger input groups with minimal wiring.
Real-life analogy: instead of receiving 8 papers at once, you receive one paper at a time and stack them in order.
Bit Order (MSBFIRST vs LSBFIRST)
MSBFIRST: reads the most significant bit first.LSBFIRST: reads the least significant bit first.
Wrong bit order gives wrong values even if wiring is correct, so always match your chip datasheet.
If your bits look reversed in Serial Monitor, first check bit order before changing hardware.
Using shiftIn() with Shift Registers
A shift register can capture multiple input states and send them as one serial byte.
Typical flow: latch the current inputs -> shiftIn() reads byte -> decode bits in software.
Example decode: bool button0 = sensorByte & 0b00000001; reads bit 0 state.
When to Use shiftIn()
- Reading many buttons/switches with fewer GPIO pins.
- Interfacing with parallel-in serial-out shift registers.
- Capturing compact digital status bytes from external logic.
- Building scalable input panels without consuming many MCU pins.
Example Code
This example latches an input register and reads one byte using shiftIn().
const int DATA_PIN = 19;
const int CLOCK_PIN = 18;
const int LATCH_PIN = 5;
void setup() {
pinMode(DATA_PIN, INPUT);
pinMode(CLOCK_PIN, OUTPUT);
pinMode(LATCH_PIN, OUTPUT);
Serial.begin(115200);
}
void loop() {
digitalWrite(LATCH_PIN, LOW);
delayMicroseconds(5);
digitalWrite(LATCH_PIN, HIGH);
byte sensorByte = shiftIn(DATA_PIN, CLOCK_PIN, MSBFIRST);
Serial.print("Raw bits: ");
Serial.println(sensorByte, BIN);
Serial.print("Decimal value: ");
Serial.println(sensorByte);
delay(300);
}Example Code Explanation
- Define data, clock, and latch pins for serial input workflow.
- Configure pin modes in
setup()and start Serial output. - Toggle latch to capture current external input states into register memory before reading.
- Call
shiftIn(DATA_PIN, CLOCK_PIN, MSBFIRST)to read one full byte. - Returned byte stores 8 digital states; each bit position can represent one external channel.
- Print raw binary bits and decimal value for easy verification.
- Repeat with a short delay for readable continuous monitoring.
What Happens Inside
- External chip places one bit on data line.
- Clock pulse advances to next bit position.
- MCU samples data line on each clock step.
- 8 sampled bits are assembled into one byte.
- Byte is returned and can be decoded by bit masks.
- Loop repeats so your system keeps tracking external input changes.
Common Mistakes with shiftIn()
- Using wrong bit order (MSBFIRST/LSBFIRST) and getting reversed values.
- Incorrect clock/data wiring causing unstable or random reads.
- Skipping latch timing so captured input state is stale/inconsistent.
- Not validating bits with Serial binary output during debugging.
- Reading before latch/update step and getting stale previous-state data.
- Trying to interpret decimal output without checking binary bit positions.
Best Practices for shiftIn()
- Match bit order to device datasheet before decoding values.
- Use clear latch-clock-data sequence and keep timing consistent.
- Print both binary and decimal while validating hardware.
- Decode bits with masks for readable and scalable logic.
- Keep clock and latch transitions clean with short timing delays if needed.
- Document which external channel maps to each bit index (bit0..bit7).
Try it now
Open the simulator workspace and test shift-register byte values, bit order, and serial debug output flow.