Files
embedded-programming/LED Blink Input Output/How-to-write-GPIO-notes.md
2026-04-03 17:14:04 +11:00

184 lines
2.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
→ PB1PB7 = 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