2.3 KiB
INPUT OUTPUT (DDRx Register)
To configure a pin as INPUT or OUTPUT, we use DDRx register.
- DDRx bit = 1 → OUTPUT
- DDRx bit = 0 → INPUT
Problem
Using direct assignment:
DDRB = 0b00000001;
→ PB0 = OUTPUT
→ PB1–PB7 = INPUT
This is not good because:
- it overwrites all bits
- existing configuration is lost
Correct approach (safe and professional)
Set PB0 as OUTPUT
DDRB |= (1 << PB0);
Explanation:
Assume DDRB = 11111110
(1 << PB0) = 00000001
11111110
00000001 (OR)
11111111
→ Only PB0 becomes OUTPUT
→ other pins unchanged
Set PB0 as INPUT
DDRB &= ~(1 << PB0);
Explanation:
Assume DDRB = 11111111
(1 << PB0) = 00000001
~(1 << PB0) = 11111110
11111111
11111110 (AND)
11111110
→ PB0 becomes INPUT
→ other pins unchanged
Final
- OUTPUT → DDRx |= (1 << Px)
- INPUT → DDRx &= ~(1 << Px)
This method:
- does not disturb other pins
- is scalable
- is standard embedded practice
PORTx and PINx (Output and Input Control)
0xFF can be used in hex for 8-bit and 0b11111111 in binary.
Both represent all bits = 1.
OUTPUT (Using PORTx)
After setting direction using DDRx, we use PORTx to control output.
Set pin HIGH:
PORTB |= (1<<PB0);
→ PB0 = HIGH (5V)
Set pin LOW:
PORTB &= ~(1<<PB0);
→ PB0 = LOW (0V)
This follows same bit logic (OR to set, AND with NOT to clear).
INPUT (Important concept)
To use pin as INPUT:
DDRB &= ~(1<<PB0);
Now PB0 is INPUT.
Pull-up requirement
If input is left floating:
- Noise (EMF, static) can cause false HIGH/LOW
So we enable internal pull-up:
PORTB |= (1<<PB0);
Now:
- Default = HIGH
- Pressed (connected to GND) = LOW
Reading input (PINx)
PINx register reads actual pin state.
Example:
if (!(PINB & (1<<PB0))) {
}
Logic explanation
Case 1: Button NOT pressed
PINB bit = 1
PINB & (1<<PB0) = 1
!1 = 0 → FALSE
→ goes to else
Case 2: Button pressed
PINB bit = 0
PINB & (1<<PB0) = 0
!0 = 1 → TRUE
→ enters if
Final understanding
- DDRx → direction
- PORTx → output / pull-up
- PINx → input reading
Key point
Pull-up makes:
- Not pressed → HIGH
- Pressed → LOW
So logic is inverted:
- LOW = pressed
- HIGH = not pressed