fix input logic (pull-up) + add GPIO notes
This commit is contained in:
184
LED Blink Input Output/How-to-write-GPIO-notes.md
Normal file
184
LED Blink Input Output/How-to-write-GPIO-notes.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user