fix input logic (pull-up) + add GPIO notes

This commit is contained in:
Pratik
2026-04-03 17:14:04 +11:00
parent 2c9714c851
commit ba12279c6a
3 changed files with 273 additions and 1 deletions

View File

@@ -0,0 +1,88 @@
# Digital INPUT OUTPUT
There are three registers which initialize Digital INPUT and DIGITAL OUTPUT port:
1. DDRB
2. DDRC
3. DDRD
Each pin is 1 bit of DDRx.
Here P means Port
Example: PC → Port C
Microcontroller pins are grouped as:
1. PORTB → PB0PB7
2. PORTC → PC0PC6
3. PORTD → PD0PD7
---
## Important
- In Arduino Uno, PC7 does not exist
→ PORTC is only PC0PC6
- PB6 and PB7 are used by 16MHz crystal
→ DO NOT USE
- PC6 is RESET pin
→ DO NOT USE as GPIO
→ can reset system
- PD0 and PD1 are Serial pins (RX TX)
→ used for USB upload and debugging
→ DO NOT USE during development
---
## SPI (just remember)
- PB3 → MOSI
- PB4 → MISO
- PB5 → SCK
→ used for SPI and programming
→ can be used as GPIO but avoid if SPI used
→ PB5 has onboard LED
---
## I2C (just remember)
- PC4 → SDA
- PC5 → SCL
→ used for I2C communication
---
## Safe pins for Digital I/O
- PORTD → PD2PD7
- PORTB → PB0PB2 (PB3PB5 usable but SPI)
- PORTC → PC0PC5 (PC4 PC5 shared with I2C)
---
## Use with care
- PB3 PB4 PB5 → SPI pins
- PC4 PC5 → I2C pins
---
## Final
Best pins to use:
PD2PD7
PB0PB2
PC0PC5
Avoid:
PB6 PB7 → crystal
PC6 → reset
PD0 PD1 → serial

View 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
→ 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

View File

@@ -14,7 +14,7 @@ int main(void) {
while(1) {
// Button pressed -> pin reads LOW because of pull-up
if (PINB & (1<<PB3)) {
if (!(PINB & (1<<PB3))) {
for (int i=0;i<=20;i++){
PORTB |= (1<<PB2); // LED ON
delay_ms(200);