184 lines
2.3 KiB
Markdown
184 lines
2.3 KiB
Markdown
# 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 |